On 12/20/19 11:37 PM, James Smart wrote: > This patch continues the libefc library population. > > This patch adds library interface definitions for: > - Remote node (aka remote port) allocation, initializaion and > destroy routines. > > Signed-off-by: Ram Vegesna <ram.vegesna@xxxxxxxxxxxx> > Signed-off-by: James Smart <jsmart2021@xxxxxxxxx> > --- > drivers/scsi/elx/libefc/efc_node.c | 1343 ++++++++++++++++++++++++++++++++++++ > drivers/scsi/elx/libefc/efc_node.h | 188 +++++ > 2 files changed, 1531 insertions(+) > create mode 100644 drivers/scsi/elx/libefc/efc_node.c > create mode 100644 drivers/scsi/elx/libefc/efc_node.h > > diff --git a/drivers/scsi/elx/libefc/efc_node.c b/drivers/scsi/elx/libefc/efc_node.c > new file mode 100644 > index 000000000000..57bf25a5d76a > --- /dev/null > +++ b/drivers/scsi/elx/libefc/efc_node.c > @@ -0,0 +1,1343 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2019 Broadcom. All Rights Reserved. The term > + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. > + */ > + > +#include "efc.h" > + > +/* HW node callback events from the user driver */ > +int > +efc_remote_node_cb(void *arg, int event, > + void *data) > +{ > + struct efc *efc = arg; > + enum efc_sm_event sm_event = EFC_EVT_LAST; > + struct efc_remote_node *rnode = data; > + struct efc_node *node = rnode->node; > + unsigned long flags = 0; > + > + switch (event) { > + case EFC_HW_NODE_ATTACH_OK: > + sm_event = EFC_EVT_NODE_ATTACH_OK; > + break; > + > + case EFC_HW_NODE_ATTACH_FAIL: > + sm_event = EFC_EVT_NODE_ATTACH_FAIL; > + break; > + > + case EFC_HW_NODE_FREE_OK: > + sm_event = EFC_EVT_NODE_FREE_OK; > + break; > + > + case EFC_HW_NODE_FREE_FAIL: > + sm_event = EFC_EVT_NOD> + default: > + efc_log_test(efc, "unhandled event %#x\n", event); > + return -1; > + } > + > + spin_lock_irqsave(&efc->lock, flags); > + efc_node_post_event(node, sm_event, NULL); > + spin_unlock_irqrestore(&efc->lock, flags); > + > + return 0; > +} > + > +/* Find an FC node structure given the FC port ID */ > +struct efc_node * > +efc_node_find(struct efc_sli_port *sport, u32 port_id) > +{ > + struct efc_node *node; > + > + node = efc_spv_get(sport->lookup, port_id); > + return node; > +} > + > +int > +efc_node_create_pool(struct efc *efc, u32 node_count) > +{ > + u32 i; > + struct efc_node *node; > + u64 max_xfer_size; > + struct efc_dma *dma; > + > + efc->nodes_count = node_count; > + > + efc->nodes = kmalloc_array(node_count, sizeof(struct efc_node *), > + GFP_ATOMIC); > + if (!efc->nodes) > + return -1; > + > + memset(efc->nodes, 0, node_count * sizeof(struct efc_node *)); > + > + if (efc->max_xfer_size) > + max_xfer_size = efc->max_xfer_size; > + else > + max_xfer_size = 65536; > + > + INIT_LIST_HEAD(&efc->nodes_free_list); > + > + for (i = 0; i < node_count; i++) { > + dma = NULL; > + node = kzalloc(sizeof(*node), GFP_ATOMIC); > + if (!node) { > + efc_log_err(efc, "node allocation failed"); > + goto error; > + } > + /* Assign any persistent field values */ > + node->instance_index = i; > + node->max_wr_xfer_size = max_xfer_size; > + node->rnode.indicator = U32_MAX; > + > + dma = &node->sparm_dma_buf; > + dma->size = 256; > + dma->virt = dma_alloc_coherent(&efc->pcidev->dev, dma->size, > + &dma->phys, GFP_DMA); > + if (!dma->virt) { > + kfree(node); > + efc_log_err(efc, "efc_dma_alloc failed"); > + goto error; > + } > + > + efc->nodes[i] = node; > + INIT_LIST_HEAD(&node->list_entry); > + list_add_tail(&node->list_entry, &efc->nodes_free_list); > + } > + return 0; > + > +error: > + efc_node_free_pool(efc); > + return -1; > +} > + Can't you use a normal mempool here, and allocate the dma region when required? I guess the node pool is used only infrequently, so performance shouldn't be impacted ... But it would reduce the pressure on the IOMMU, no? [ .. ] > +void efc_node_post_els_resp(struct efc_node *node, > + enum efc_hw_node_els_event evt, void *arg) > +{ > + enum efc_sm_event sm_event = EFC_EVT_LAST; > + struct efc *efc = node->efc; > + unsigned long flags = 0; > + > + switch (evt) { > + case EFC_HW_SRRS_ELS_REQ_OK: > + sm_event = EFC_EVT_SRRS_ELS_REQ_OK; > + break; > + case EFC_HW_SRRS_ELS_CMPL_OK: > + sm_event = EFC_EVT_SRRS_ELS_CMPL_OK; > + break; > + case EFC_HW_SRRS_ELS_REQ_FAIL: > + sm_event = EFC_EVT_SRRS_ELS_REQ_FAIL; > + break; > + case EFC_HW_SRRS_ELS_CMPL_FAIL: > + sm_event = EFC_EVT_SRRS_ELS_CMPL_FAIL; > + break; > + case EFC_HW_SRRS_ELS_REQ_RJT: > + sm_event = EFC_EVT_SRRS_ELS_REQ_RJT; > + break; > + case EFC_HW_ELS_REQ_ABORTED: > + sm_event = EFC_EVT_ELS_REQ_ABORTED; > + break; Please collapse. Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@xxxxxxx +49 911 74053 688 SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg HRB 36809 (AG Nürnberg), GF: Felix Imendörffer