Re: [PATCH v2 12/32] elx: libefc: Remote node state machine interfaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux