All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare@suse.de>
To: James Smart <jsmart2021@gmail.com>, linux-scsi@vger.kernel.org
Cc: dwagner@suse.de, maier@linux.ibm.com, bvanassche@acm.org,
	herbszt@gmx.de, natechancellor@gmail.com, rdunlap@infradead.org,
	Ram Vegesna <ram.vegesna@broadcom.com>
Subject: Re: [PATCH v3 20/31] elx: efct: Hardware queues processing
Date: Thu, 16 Apr 2020 09:37:55 +0200	[thread overview]
Message-ID: <d03fc64e-54e2-5d62-da8a-fc8a5cc67b85@suse.de> (raw)
In-Reply-To: <20200412033303.29574-21-jsmart2021@gmail.com>

On 4/12/20 5:32 AM, James Smart wrote:
> This patch continues the efct driver population.
> 
> This patch adds driver definitions for:
> Routines for EQ, CQ, WQ and RQ processing.
> Routines for IO object pool allocation and deallocation.
> 
> Signed-off-by: Ram Vegesna <ram.vegesna@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> 
> ---
> v3:
>    Return defined values
>    Changed IO pool allocation logic to avoid using efct_pool.
> ---
>   drivers/scsi/elx/efct/efct_hw.c | 369 ++++++++++++++++++++++++++++++++++++++++
>   drivers/scsi/elx/efct/efct_hw.h |  36 ++++
>   drivers/scsi/elx/efct/efct_io.c | 198 +++++++++++++++++++++
>   drivers/scsi/elx/efct/efct_io.h | 191 +++++++++++++++++++++
>   4 files changed, 794 insertions(+)
>   create mode 100644 drivers/scsi/elx/efct/efct_io.c
>   create mode 100644 drivers/scsi/elx/efct/efct_io.h
> 
> diff --git a/drivers/scsi/elx/efct/efct_hw.c b/drivers/scsi/elx/efct/efct_hw.c
> index 892493a3a35e..6cdc7e27b148 100644
> --- a/drivers/scsi/elx/efct/efct_hw.c
> +++ b/drivers/scsi/elx/efct/efct_hw.c
> @@ -2146,3 +2146,372 @@ efct_hw_reqtag_reset(struct efct_hw *hw)
>   		list_add_tail(&wqcb->list_entry, &reqtag_pool->freelist);
>   	}
>   }
> +
> +int
> +efct_hw_queue_hash_find(struct efct_queue_hash *hash, u16 id)
> +{
> +	int	rc = -1;
> +	int	index = id & (EFCT_HW_Q_HASH_SIZE - 1);
> +
> +	/*
> +	 * Since the hash is always bigger than the maximum number of Qs, then
> +	 * we never have to worry about an infinite loop. We will always find
> +	 * an unused entry.
> +	 */
> +	do {
> +		if (hash[index].in_use &&
> +		    hash[index].id == id)
> +			rc = hash[index].index;
> +		else
> +			index = (index + 1) & (EFCT_HW_Q_HASH_SIZE - 1);
> +	} while (rc == -1 && hash[index].in_use);
> +
> +	return rc;
> +}
> +
> +int
> +efct_hw_process(struct efct_hw *hw, u32 vector,
> +		u32 max_isr_time_msec)
> +{
> +	struct hw_eq *eq;
> +	int rc = 0;
> +
> +	/*
> +	 * The caller should disable interrupts if they wish to prevent us
> +	 * from processing during a shutdown. The following states are defined:
> +	 *   EFCT_HW_STATE_UNINITIALIZED - No queues allocated
> +	 *   EFCT_HW_STATE_QUEUES_ALLOCATED - The state after a chip reset,
> +	 *                                    queues are cleared.
> +	 *   EFCT_HW_STATE_ACTIVE - Chip and queues are operational
> +	 *   EFCT_HW_STATE_RESET_IN_PROGRESS - reset, we still want completions
> +	 *   EFCT_HW_STATE_TEARDOWN_IN_PROGRESS - We still want mailbox
> +	 *                                        completions.
> +	 */
> +	if (hw->state == EFCT_HW_STATE_UNINITIALIZED)
> +		return EFC_SUCCESS;
> +
> +	/* Get pointer to struct hw_eq */
> +	eq = hw->hw_eq[vector];
> +	if (!eq)
> +		return EFC_SUCCESS;
> +
> +	eq->use_count++;
> +
> +	rc = efct_hw_eq_process(hw, eq, max_isr_time_msec);
> +
> +	return rc;
> +}
> +
> +int
> +efct_hw_eq_process(struct efct_hw *hw, struct hw_eq *eq,
> +		   u32 max_isr_time_msec)
> +{
> +	u8		eqe[sizeof(struct sli4_eqe)] = { 0 };
> +	u32	tcheck_count;
> +	time_t		tstart;
> +	time_t		telapsed;
> +	bool		done = false;
> +
> +	tcheck_count = EFCT_HW_TIMECHECK_ITERATIONS;
> +	tstart = jiffies_to_msecs(jiffies);
> +
> +	while (!done && !sli_eq_read(&hw->sli, eq->queue, eqe)) {
> +		u16	cq_id = 0;
> +		int		rc;
> +
> +		rc = sli_eq_parse(&hw->sli, eqe, &cq_id);
> +		if (unlikely(rc)) {
> +			if (rc == SLI4_EQE_STATUS_EQ_FULL) {
> +				u32 i;
> +
> +				/*
> +				 * Received a sentinel EQE indicating the
> +				 * EQ is full. Process all CQs
> +				 */
> +				for (i = 0; i < hw->cq_count; i++)
> +					efct_hw_cq_process(hw, hw->hw_cq[i]);
> +				continue;
> +			} else {
> +				return rc;
> +			}
> +		} else {
> +			int index;
> +
> +			index  = efct_hw_queue_hash_find(hw->cq_hash, cq_id);
> +
> +			if (likely(index >= 0))
> +				efct_hw_cq_process(hw, hw->hw_cq[index]);
> +			else
> +				efc_log_err(hw->os, "bad CQ_ID %#06x\n",
> +					     cq_id);
> +		}
> +
> +		if (eq->queue->n_posted > eq->queue->posted_limit)
> +			sli_queue_arm(&hw->sli, eq->queue, false);
> +
> +		if (tcheck_count && (--tcheck_count == 0)) {
> +			tcheck_count = EFCT_HW_TIMECHECK_ITERATIONS;
> +			telapsed = jiffies_to_msecs(jiffies) - tstart;
> +			if (telapsed >= max_isr_time_msec)
> +				done = true;
> +		}
> +	}
> +	sli_queue_eq_arm(&hw->sli, eq->queue, true);
> +
> +	return EFC_SUCCESS;
> +}
> +
> +static int
> +_efct_hw_wq_write(struct hw_wq *wq, struct efct_hw_wqe *wqe)
> +{
> +	int queue_rc;
> +
> +	/* Every so often, set the wqec bit to generate comsummed completions */
> +	if (wq->wqec_count)
> +		wq->wqec_count--;
> +
> +	if (wq->wqec_count == 0) {
> +		struct sli4_generic_wqe *genwqe = (void *)wqe->wqebuf;
> +
> +		genwqe->cmdtype_wqec_byte |= SLI4_GEN_WQE_WQEC;
> +		wq->wqec_count = wq->wqec_set_count;
> +	}
> +
> +	/* Decrement WQ free count */
> +	wq->free_count--;
> +
> +	queue_rc = sli_wq_write(&wq->hw->sli, wq->queue, wqe->wqebuf);
> +
> +	return (queue_rc < 0) ? -1 : 0;
> +}
> +
> +static void
> +hw_wq_submit_pending(struct hw_wq *wq, u32 update_free_count)
> +{
> +	struct efct_hw_wqe *wqe;
> +	unsigned long flags = 0;
> +
> +	spin_lock_irqsave(&wq->queue->lock, flags);
> +
> +	/* Update free count with value passed in */
> +	wq->free_count += update_free_count;
> +
> +	while ((wq->free_count > 0) && (!list_empty(&wq->pending_list))) {
> +		wqe = list_first_entry(&wq->pending_list,
> +				       struct efct_hw_wqe, list_entry);
> +		list_del(&wqe->list_entry);
> +		_efct_hw_wq_write(wq, wqe);
> +
> +		if (wqe->abort_wqe_submit_needed) {
> +			wqe->abort_wqe_submit_needed = false;
> +			sli_abort_wqe(&wq->hw->sli, wqe->wqebuf,
> +				      wq->hw->sli.wqe_size,
> +				      SLI_ABORT_XRI, wqe->send_abts, wqe->id,
> +				      0, wqe->abort_reqtag, SLI4_CQ_DEFAULT);
> +					  INIT_LIST_HEAD(&wqe->list_entry);

See? Would could drop at least 4 arguments by passing in the wqe 
directly ...

> +			list_add_tail(&wqe->list_entry, &wq->pending_list);
> +			wq->wq_pending_count++;
> +		}
> +	}
> +
> +	spin_unlock_irqrestore(&wq->queue->lock, flags);
> +}
> +
> +void
> +efct_hw_cq_process(struct efct_hw *hw, struct hw_cq *cq)
> +{
> +	u8		cqe[sizeof(struct sli4_mcqe)];
> +	u16	rid = U16_MAX;
> +	enum sli4_qentry	ctype;		/* completion type */
> +	int		status;
> +	u32	n_processed = 0;
> +	u32	tstart, telapsed;
> +
> +	tstart = jiffies_to_msecs(jiffies);
> +
> +	while (!sli_cq_read(&hw->sli, cq->queue, cqe)) {
> +		status = sli_cq_parse(&hw->sli, cq->queue,
> +				      cqe, &ctype, &rid);
> +		/*
> +		 * The sign of status is significant. If status is:
> +		 * == 0 : call completed correctly and
> +		 * the CQE indicated success
> +		 * > 0 : call completed correctly and
> +		 * the CQE indicated an error
> +		 * < 0 : call failed and no information is available about the
> +		 * CQE
> +		 */
> +		if (status < 0) {
> +			if (status == SLI4_MCQE_STATUS_NOT_COMPLETED)
> +				/*
> +				 * Notification that an entry was consumed,
> +				 * but not completed
> +				 */
> +				continue;
> +
> +			break;
> +		}
> +
> +		switch (ctype) {
> +		case SLI_QENTRY_ASYNC:
> +			sli_cqe_async(&hw->sli, cqe);
> +			break;
> +		case SLI_QENTRY_MQ:
> +			/*
> +			 * Process MQ entry. Note there is no way to determine
> +			 * the MQ_ID from the completion entry.
> +			 */
> +			efct_hw_mq_process(hw, status, hw->mq);
> +			break;
> +		case SLI_QENTRY_WQ:
> +			efct_hw_wq_process(hw, cq, cqe, status, rid);
> +			break;
> +		case SLI_QENTRY_WQ_RELEASE: {
> +			u32 wq_id = rid;
> +			int index;
> +			struct hw_wq *wq = NULL;
> +
> +			index = efct_hw_queue_hash_find(hw->wq_hash, wq_id);
> +
> +			if (likely(index >= 0)) {
> +				wq = hw->hw_wq[index];
> +			} else {
> +				efc_log_err(hw->os, "bad WQ_ID %#06x\n", wq_id);
> +				break;
> +			}
> +			/* Submit any HW IOs that are on the WQ pending list */
> +			hw_wq_submit_pending(wq, wq->wqec_set_count);
> +
> +			break;
> +		}
> +
> +		case SLI_QENTRY_RQ:
> +			efct_hw_rqpair_process_rq(hw, cq, cqe);
> +			break;
> +		case SLI_QENTRY_XABT: {
> +			efct_hw_xabt_process(hw, cq, cqe, rid);
> +			break;
> +		}
> +		default:
> +			efc_log_test(hw->os,
> +				      "unhandled ctype=%#x rid=%#x\n",
> +				     ctype, rid);
> +			break;
> +		}
> +
> +		n_processed++;
> +		if (n_processed == cq->queue->proc_limit)
> +			break;
> +
> +		if (cq->queue->n_posted >= cq->queue->posted_limit)
> +			sli_queue_arm(&hw->sli, cq->queue, false);
> +	}
> +
> +	sli_queue_arm(&hw->sli, cq->queue, true);
> +
> +	if (n_processed > cq->queue->max_num_processed)
> +		cq->queue->max_num_processed = n_processed;
> +	telapsed = jiffies_to_msecs(jiffies) - tstart;
> +	if (telapsed > cq->queue->max_process_time)
> +		cq->queue->max_process_time = telapsed;
> +}
> +
> +void
> +efct_hw_wq_process(struct efct_hw *hw, struct hw_cq *cq,
> +		   u8 *cqe, int status, u16 rid)
> +{
> +	struct hw_wq_callback *wqcb;
> +
> +	if (rid == EFCT_HW_REQUE_XRI_REGTAG) {
> +		if (status)
> +			efc_log_err(hw->os, "reque xri failed, status = %d\n",
> +				     status);
> +		return;
> +	}
> +
> +	wqcb = efct_hw_reqtag_get_instance(hw, rid);
> +	if (!wqcb) {
> +		efc_log_err(hw->os, "invalid request tag: x%x\n", rid);
> +		return;
> +	}
> +
> +	if (!wqcb->callback) {
> +		efc_log_err(hw->os, "wqcb callback is NULL\n");
> +		return;
> +	}
> +
> +	(*wqcb->callback)(wqcb->arg, cqe, status);
> +}
> +
> +void
> +efct_hw_xabt_process(struct efct_hw *hw, struct hw_cq *cq,
> +		     u8 *cqe, u16 rid)
> +{
> +	/* search IOs wait free list */
> +	struct efct_hw_io *io = NULL;
> +	unsigned long flags = 0;
> +
> +	io = efct_hw_io_lookup(hw, rid);
> +	if (!io) {
> +		/* IO lookup failure should never happen */
> +		efc_log_err(hw->os,
> +			     "Error: xabt io lookup failed rid=%#x\n", rid);
> +		return;
> +	}
> +
> +	if (!io->xbusy)
> +		efc_log_debug(hw->os, "xabt io not busy rid=%#x\n", rid);
> +	else
> +		/* mark IO as no longer busy */
> +		io->xbusy = false;
> +
> +	/*
> +	 * For IOs that were aborted internally, we need to issue any pending
> +	 * callback here.
> +	 */
> +	if (io->done) {
> +		efct_hw_done_t done = io->done;
> +		void		*arg = io->arg;
> +
> +		/*
> +		 * Use latched status as this is always saved for an internal
> +		 * abort
> +		 */
> +		int status = io->saved_status;
> +		u32 len = io->saved_len;
> +		u32 ext = io->saved_ext;
> +
> +		io->done = NULL;
> +		io->status_saved = false;
> +
> +		done(io, io->rnode, len, status, ext, arg);
> +	}
> +
> +	spin_lock_irqsave(&hw->io_lock, flags);
> +	if (io->state == EFCT_HW_IO_STATE_INUSE ||
> +	    io->state == EFCT_HW_IO_STATE_WAIT_FREE) {
> +		/* if on wait_free list, caller has already freed IO;
> +		 * remove from wait_free list and add to free list.
> +		 * if on in-use list, already marked as no longer busy;
> +		 * just leave there and wait for caller to free.
> +		 */
> +		if (io->state == EFCT_HW_IO_STATE_WAIT_FREE) {
> +			io->state = EFCT_HW_IO_STATE_FREE;
> +			list_del(&io->list_entry);
> +			efct_hw_io_free_move_correct_list(hw, io);
> +		}
> +	}
> +	spin_unlock_irqrestore(&hw->io_lock, flags);
> +}
> +
> +static int
> +efct_hw_flush(struct efct_hw *hw)
> +{
> +	u32	i = 0;
> +
> +	/* Process any remaining completions */
> +	for (i = 0; i < hw->eq_count; i++)
> +		efct_hw_process(hw, i, ~0);
> +
> +	return EFC_SUCCESS;
> +}
> diff --git a/drivers/scsi/elx/efct/efct_hw.h b/drivers/scsi/elx/efct/efct_hw.h
> index 86736d5295ec..b427a4eda5a3 100644
> --- a/drivers/scsi/elx/efct/efct_hw.h
> +++ b/drivers/scsi/elx/efct/efct_hw.h
> @@ -678,4 +678,40 @@ extern struct hw_wq_callback
>   *efct_hw_reqtag_get_instance(struct efct_hw *hw, u32 instance_index);
>   void efct_hw_reqtag_reset(struct efct_hw *hw);
>   
> +/* RQ completion handlers for RQ pair mode */
> +extern int
> +efct_hw_rqpair_process_rq(struct efct_hw *hw,
> +			  struct hw_cq *cq, u8 *cqe);
> +extern
> +enum efct_hw_rtn efct_hw_rqpair_sequence_free(struct efct_hw *hw,
> +						struct efc_hw_sequence *seq);
> +static inline void
> +efct_hw_sequence_copy(struct efc_hw_sequence *dst,
> +		      struct efc_hw_sequence *src)
> +{
> +	/* Copy src to dst, then zero out the linked list link */
> +	*dst = *src;
> +}
> +
> +static inline enum efct_hw_rtn
> +efct_hw_sequence_free(struct efct_hw *hw, struct efc_hw_sequence *seq)
> +{
> +	/* Only RQ pair mode is supported */
> +	return efct_hw_rqpair_sequence_free(hw, seq);
> +}
> +extern int
> +efct_hw_eq_process(struct efct_hw *hw, struct hw_eq *eq,
> +		   u32 max_isr_time_msec);
> +void efct_hw_cq_process(struct efct_hw *hw, struct hw_cq *cq);
> +extern void
> +efct_hw_wq_process(struct efct_hw *hw, struct hw_cq *cq,
> +		   u8 *cqe, int status, u16 rid);
> +extern void
> +efct_hw_xabt_process(struct efct_hw *hw, struct hw_cq *cq,
> +		     u8 *cqe, u16 rid);
> +extern int
> +efct_hw_process(struct efct_hw *hw, u32 vector, u32 max_isr_time_msec);
> +extern int
> +efct_hw_queue_hash_find(struct efct_queue_hash *hash, u16 id);
> +
>   #endif /* __EFCT_H__ */
> diff --git a/drivers/scsi/elx/efct/efct_io.c b/drivers/scsi/elx/efct/efct_io.c
> new file mode 100644
> index 000000000000..8ea05b59c892
> --- /dev/null
> +++ b/drivers/scsi/elx/efct/efct_io.c
> @@ -0,0 +1,198 @@
> +// 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 "efct_driver.h"
> +#include "efct_hw.h"
> +#include "efct_io.h"
> +
> +struct efct_io_pool {
> +	struct efct *efct;
> +	spinlock_t lock;	/* IO pool lock */
> +	u32 io_num_ios;		/* Total IOs allocated */
> +	struct efct_io *ios[EFCT_NUM_SCSI_IOS];
> +	struct list_head freelist;
> +
> +};
> +
> +struct efct_io_pool *
> +efct_io_pool_create(struct efct *efct, u32 num_sgl)
> +{
> +	u32 i = 0;
> +	struct efct_io_pool *io_pool;
> +	struct efct_io *io;
> +
> +	/* Allocate the IO pool */
> +	io_pool = kzalloc(sizeof(*io_pool), GFP_KERNEL);
> +	if (!io_pool)
> +		return NULL;
> +
> +	io_pool->efct = efct;
> +	INIT_LIST_HEAD(&io_pool->freelist);
> +	/* initialize IO pool lock */
> +	spin_lock_init(&io_pool->lock);
> +
> +	for (i = 0; i < EFCT_NUM_SCSI_IOS; i++) {
> +		io = kmalloc(sizeof(*io), GFP_KERNEL);
> +		if (!io)
> +			break;
> +
> +		io_pool->io_num_ios++;
> +		io_pool->ios[i] = io;
> +		io->tag = i;
> +		io->instance_index = i;
> +
> +		/* Allocate a response buffer */
> +		io->rspbuf.size = SCSI_RSP_BUF_LENGTH;
> +		io->rspbuf.virt = dma_alloc_coherent(&efct->pcidev->dev,
> +						     io->rspbuf.size,
> +						     &io->rspbuf.phys, GFP_DMA);
> +		if (!io->rspbuf.virt) {
> +			efc_log_err(efct, "dma_alloc rspbuf failed\n");
> +			efct_io_pool_free(io_pool);
> +			return NULL;
> +		}
> +
> +		/* Allocate SGL */
> +		io->sgl = kzalloc(sizeof(*io->sgl) * num_sgl, GFP_ATOMIC);
> +		if (!io->sgl) {
> +			efct_io_pool_free(io_pool);
> +			return NULL;
> +		}
> +
> +		memset(io->sgl, 0, sizeof(*io->sgl) * num_sgl);
> +		io->sgl_allocated = num_sgl;
> +		io->sgl_count = 0;
> +
> +		INIT_LIST_HEAD(&io->list_entry);
> +		list_add_tail(&io->list_entry, &io_pool->freelist);
> +	}
> +
> +	return io_pool;
> +}
> +
> +int
> +efct_io_pool_free(struct efct_io_pool *io_pool)
> +{
> +	struct efct *efct;
> +	u32 i;
> +	struct efct_io *io;
> +
> +	if (io_pool) {
> +		efct = io_pool->efct;
> +
> +		for (i = 0; i < io_pool->io_num_ios; i++) {
> +			io = io_pool->ios[i];
> +			if (!io)
> +				continue;
> +
> +			kfree(io->sgl);
> +			dma_free_coherent(&efct->pcidev->dev,
> +					  io->rspbuf.size, io->rspbuf.virt,
> +					  io->rspbuf.phys);
> +			memset(&io->rspbuf, 0, sizeof(struct efc_dma));
> +		}
> +
> +		kfree(io_pool);
> +		efct->xport->io_pool = NULL;
> +	}
> +
> +	return EFC_SUCCESS;
> +}
> +
> +u32 efct_io_pool_allocated(struct efct_io_pool *io_pool)
> +{
> +	return io_pool->io_num_ios;
> +}
> +
> +struct efct_io *
> +efct_io_pool_io_alloc(struct efct_io_pool *io_pool)
> +{
> +	struct efct_io *io = NULL;
> +	struct efct *efct;
> +	unsigned long flags = 0;
> +
> +	efct = io_pool->efct;
> +
> +	spin_lock_irqsave(&io_pool->lock, flags);
> +
> +	if (!list_empty(&io_pool->freelist)) {
> +		io = list_first_entry(&io_pool->freelist, struct efct_io,
> +				     list_entry);
> +	}
> +
> +	if (io) {
> +		list_del(&io->list_entry);
> +		spin_unlock_irqrestore(&io_pool->lock, flags);
> +
> +		io->io_type = EFCT_IO_TYPE_MAX;
> +		io->hio_type = EFCT_HW_IO_MAX;
> +		io->hio = NULL;
> +		io->transferred = 0;
> +		io->efct = efct;
> +		io->timeout = 0;
> +		io->sgl_count = 0;
> +		io->tgt_task_tag = 0;
> +		io->init_task_tag = 0;
> +		io->hw_tag = 0;
> +		io->display_name = "pending";
> +		io->seq_init = 0;
> +		io->els_req_free = false;
> +		io->io_free = 0;
> +		io->release = NULL;
> +		atomic_add_return(1, &efct->xport->io_active_count);
> +		atomic_add_return(1, &efct->xport->io_total_alloc);
> +	} else {
> +		spin_unlock_irqrestore(&io_pool->lock, flags);
> +	}
> +	return io;
> +}
> +
> +/* Free an object used to track an IO */
> +void
> +efct_io_pool_io_free(struct efct_io_pool *io_pool, struct efct_io *io)
> +{
> +	struct efct *efct;
> +	struct efct_hw_io *hio = NULL;
> +	unsigned long flags = 0;
> +
> +	efct = io_pool->efct;
> +
> +	spin_lock_irqsave(&io_pool->lock, flags);
> +	hio = io->hio;
> +	io->hio = NULL;
> +	io->io_free = 1;
> +	INIT_LIST_HEAD(&io->list_entry);
> +	list_add(&io->list_entry, &io_pool->freelist);
> +	spin_unlock_irqrestore(&io_pool->lock, flags);
> +
> +	if (hio)
> +		efct_hw_io_free(&efct->hw, hio);
> +
> +	atomic_sub_return(1, &efct->xport->io_active_count);
> +	atomic_add_return(1, &efct->xport->io_total_free);
> +}
> +
> +/* Find an I/O given it's node and ox_id */
> +struct efct_io *
> +efct_io_find_tgt_io(struct efct *efct, struct efc_node *node,
> +		    u16 ox_id, u16 rx_id)
> +{
> +	struct efct_io	*io = NULL;
> +	unsigned long flags = 0;
> +	u8 found = false;
> +
> +	spin_lock_irqsave(&node->active_ios_lock, flags);
> +	list_for_each_entry(io, &node->active_ios, list_entry) {
> +		if ((io->cmd_tgt && io->init_task_tag == ox_id) &&
> +		    (rx_id == 0xffff || io->tgt_task_tag == rx_id)) {
> +			if (kref_get_unless_zero(&io->ref))
> +				found = true;
> +			break;
> +		}
> +	}
> +	spin_unlock_irqrestore(&node->active_ios_lock, flags);
> +	return found ? io : NULL;
> +}
> diff --git a/drivers/scsi/elx/efct/efct_io.h b/drivers/scsi/elx/efct/efct_io.h
> new file mode 100644
> index 000000000000..e28d8ed2f7ff
> --- /dev/null
> +++ b/drivers/scsi/elx/efct/efct_io.h
> @@ -0,0 +1,191 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2019 Broadcom. All Rights Reserved. The term
> + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
> + */
> +
> +#if !defined(__EFCT_IO_H__)
> +#define __EFCT_IO_H__
> +
> +#include "efct_lio.h"
> +
> +#define EFCT_LOG_ENABLE_IO_ERRORS(efct)		\
> +		(((efct) != NULL) ? (((efct)->logmask & (1U << 6)) != 0) : 0)
> +
> +#define io_error_log(io, fmt, ...)  \
> +	do { \
> +		if (EFCT_LOG_ENABLE_IO_ERRORS(io->efct)) \
> +			efc_log_warn(io->efct, fmt, ##__VA_ARGS__); \
> +	} while (0)
> +
> +#define SCSI_CMD_BUF_LENGTH	48
> +#define SCSI_RSP_BUF_LENGTH	(FCP_RESP_WITH_EXT + SCSI_SENSE_BUFFERSIZE)
> +#define EFCT_NUM_SCSI_IOS	8192
> +
> +enum efct_io_type {
> +	EFCT_IO_TYPE_IO = 0,
> +	EFCT_IO_TYPE_ELS,
> +	EFCT_IO_TYPE_CT,
> +	EFCT_IO_TYPE_CT_RESP,
> +	EFCT_IO_TYPE_BLS_RESP,
> +	EFCT_IO_TYPE_ABORT,
> +
> +	EFCT_IO_TYPE_MAX,
> +};
> +
> +enum efct_els_state {
> +	EFCT_ELS_REQUEST = 0,
> +	EFCT_ELS_REQUEST_DELAYED,
> +	EFCT_ELS_REQUEST_DELAY_ABORT,
> +	EFCT_ELS_REQ_ABORT,
> +	EFCT_ELS_REQ_ABORTED,
> +	EFCT_ELS_ABORT_IO_COMPL,
> +};
> +
> +struct efct_io {
> +	struct list_head	list_entry;
> +	struct list_head	io_pending_link;
> +	/* reference counter and callback function */
> +	struct kref		ref;
> +	void (*release)(struct kref *arg);
> +	/* pointer back to efct */
> +	struct efct		*efct;
> +	/* unique instance index value */
> +	u32			instance_index;
> +	/* display name */
> +	const char		*display_name;
> +	/* pointer to node */
> +	struct efc_node		*node;
> +	/* (io_pool->io_free_list) free list link */
> +	/* initiator task tag (OX_ID) for back-end and SCSI logging */
> +	u32			init_task_tag;
> +	/* target task tag (RX_ID) - for back-end and SCSI logging */
> +	u32			tgt_task_tag;
> +	/* HW layer unique IO id - for back-end and SCSI logging */
> +	u32			hw_tag;
> +	/* unique IO identifier */
> +	u32			tag;
> +	/* SGL */
> +	struct efct_scsi_sgl	*sgl;
> +	/* Number of allocated SGEs */
> +	u32			sgl_allocated;
> +	/* Number of SGEs in this SGL */
> +	u32			sgl_count;
> +	/* backend target private IO data */
> +	struct efct_scsi_tgt_io tgt_io;
> +	/* expected data transfer length, based on FC header */
> +	u32			exp_xfer_len;
> +
> +	/* Declarations private to HW/SLI */
> +	void			*hw_priv;
> +
> +	/* indicates what this struct efct_io structure is used for */
> +	enum efct_io_type	io_type;
> +	struct efct_hw_io	*hio;
> +	size_t			transferred;
> +
> +	/* set if auto_trsp was set */
> +	bool			auto_resp;
> +	/* set if low latency request */
> +	bool			low_latency;
> +	/* selected WQ steering request */
> +	u8			wq_steering;
> +	/* selected WQ class if steering is class */
> +	u8			wq_class;
> +	/* transfer size for current request */
> +	u64			xfer_req;
> +	/* target callback function */
> +	efct_scsi_io_cb_t	scsi_tgt_cb;
> +	/* target callback function argument */
> +	void			*scsi_tgt_cb_arg;
> +	/* abort callback function */
> +	efct_scsi_io_cb_t	abort_cb;
> +	/* abort callback function argument */
> +	void			*abort_cb_arg;
> +	/* BLS callback function */
> +	efct_scsi_io_cb_t	bls_cb;
> +	/* BLS callback function argument */
> +	void			*bls_cb_arg;
> +	/* TMF command being processed */
> +	enum efct_scsi_tmf_cmd	tmf_cmd;
> +	/* rx_id from the ABTS that initiated the command abort */
> +	u16			abort_rx_id;
> +
> +	/* True if this is a Target command */
> +	bool			cmd_tgt;
> +	/* when aborting, indicates ABTS is to be sent */
> +	bool			send_abts;
> +	/* True if this is an Initiator command */
> +	bool			cmd_ini;
> +	/* True if local node has sequence initiative */
> +	bool			seq_init;
> +	/* iparams for hw io send call */
> +	union efct_hw_io_param_u iparam;
> +	/* HW IO type */
> +	enum efct_hw_io_type	hio_type;
> +	/* wire length */
> +	u64			wire_len;
> +	/* saved HW callback */
> +	void			*hw_cb;
> +
> +	/* for ELS requests/responses */
> +	/* True if ELS is pending */
> +	bool			els_pend;
> +	/* True if ELS is active */
> +	bool			els_active;
> +	/* ELS request payload buffer */
> +	struct efc_dma		els_req;
> +	/* ELS response payload buffer */
> +	struct efc_dma		els_rsp;
> +	bool			els_req_free;
> +	/* Retries remaining */
> +	u32			els_retries_remaining;
> +	void (*els_callback)(struct efc_node *node,
> +			     struct efc_node_cb *cbdata, void *cbarg);
> +	void			*els_callback_arg;
> +	/* timeout */
> +	u32			els_timeout_sec;
> +
> +	/* delay timer */
> +	struct timer_list	delay_timer;
> +
> +	/* for abort handling */
> +	/* pointer to IO to abort */
> +	struct efct_io		*io_to_abort;
> +
> +	enum efct_els_state	state;
> +	/* Protects els cmds */
> +	spinlock_t		els_lock;
> +
> +	/* SCSI Response buffer */
> +	struct efc_dma		rspbuf;
> +	/* Timeout value in seconds for this IO */
> +	u32			timeout;
> +	/* CS_CTL priority for this IO */
> +	u8			cs_ctl;
> +	/* Is io object in freelist > */
> +	u8			io_free;
> +	u32			app_id;
> +};
> +
> +struct efct_io_cb_arg {
> +	int status;		/* completion status */
> +	int ext_status;		/* extended completion status */
> +	void *app;		/* application argument */
> +};
> +
> +struct efct_io_pool *
> +efct_io_pool_create(struct efct *efct, u32 num_sgl);
> +extern int
> +efct_io_pool_free(struct efct_io_pool *io_pool);
> +extern u32
> +efct_io_pool_allocated(struct efct_io_pool *io_pool);
> +
> +extern struct efct_io *
> +efct_io_pool_io_alloc(struct efct_io_pool *io_pool);
> +extern void
> +efct_io_pool_io_free(struct efct_io_pool *io_pool, struct efct_io *io);
> +extern struct efct_io *
> +efct_io_find_tgt_io(struct efct *efct, struct efc_node *node,
> +		    u16 ox_id, u16 rx_id);
> +#endif /* __EFCT_IO_H__ */
> 
Other than that:

Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke            Teamlead Storage & Networking
hare@suse.de                               +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer

  reply	other threads:[~2020-04-16  7:38 UTC|newest]

Thread overview: 124+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-12  3:32 [PATCH v3 00/31] [NEW] efct: Broadcom (Emulex) FC Target driver James Smart
2020-04-12  3:32 ` [PATCH v3 01/31] elx: libefc_sli: SLI-4 register offsets and field definitions James Smart
2020-04-14 15:23   ` Daniel Wagner
2020-04-22  4:28     ` James Smart
2020-04-15 12:06   ` Hannes Reinecke
2020-04-23  1:52   ` Roman Bolshakov
2020-04-12  3:32 ` [PATCH v3 02/31] elx: libefc_sli: SLI Descriptors and Queue entries James Smart
2020-04-14 18:02   ` Daniel Wagner
2020-04-22  4:41     ` James Smart
2020-04-15 12:14   ` Hannes Reinecke
2020-04-15 17:43     ` James Bottomley
2020-04-22  4:44     ` James Smart
2020-04-12  3:32 ` [PATCH v3 03/31] elx: libefc_sli: Data structures and defines for mbox commands James Smart
2020-04-14 19:01   ` Daniel Wagner
2020-04-15 12:22   ` Hannes Reinecke
2020-04-12  3:32 ` [PATCH v3 04/31] elx: libefc_sli: queue create/destroy/parse routines James Smart
2020-04-15 10:04   ` Daniel Wagner
2020-04-22  5:05     ` James Smart
2020-04-24  7:29       ` Daniel Wagner
2020-04-24 15:21         ` James Smart
2020-04-15 12:27   ` Hannes Reinecke
2020-04-12  3:32 ` [PATCH v3 05/31] elx: libefc_sli: Populate and post different WQEs James Smart
2020-04-15 14:34   ` Daniel Wagner
2020-04-22  5:08     ` James Smart
2020-04-12  3:32 ` [PATCH v3 06/31] elx: libefc_sli: bmbx routines and SLI config commands James Smart
2020-04-15 16:10   ` Daniel Wagner
2020-04-22  5:12     ` James Smart
2020-04-12  3:32 ` [PATCH v3 07/31] elx: libefc_sli: APIs to setup SLI library James Smart
2020-04-15 12:49   ` Hannes Reinecke
2020-04-15 17:06   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 08/31] elx: libefc: Generic state machine framework James Smart
2020-04-15 12:37   ` Hannes Reinecke
2020-04-15 17:20   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 09/31] elx: libefc: Emulex FC discovery library APIs and definitions James Smart
2020-04-15 12:41   ` Hannes Reinecke
2020-04-15 17:32   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 10/31] elx: libefc: FC Domain state machine interfaces James Smart
2020-04-15 12:50   ` Hannes Reinecke
2020-04-15 17:50   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 11/31] elx: libefc: SLI and FC PORT " James Smart
2020-04-15 15:38   ` Hannes Reinecke
2020-04-22 23:12     ` James Smart
2020-04-15 18:04   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 12/31] elx: libefc: Remote node " James Smart
2020-04-15 15:51   ` Hannes Reinecke
2020-04-23  1:35     ` James Smart
2020-04-23  8:02       ` Daniel Wagner
2020-04-23 18:24         ` James Smart
2020-04-15 18:19   ` Daniel Wagner
2020-04-23  1:32     ` James Smart
2020-04-23  7:49       ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 13/31] elx: libefc: Fabric " James Smart
2020-04-15 18:51   ` Daniel Wagner
2020-04-16  6:37   ` Hannes Reinecke
2020-04-23  1:38     ` James Smart
2020-04-12  3:32 ` [PATCH v3 14/31] elx: libefc: FC node ELS and state handling James Smart
2020-04-15 18:56   ` Daniel Wagner
2020-04-23  2:50     ` James Smart
2020-04-23  8:05       ` Daniel Wagner
2020-04-23  8:12         ` Nathan Chancellor
2020-04-16  6:47   ` Hannes Reinecke
2020-04-23  2:55     ` James Smart
2020-04-12  3:32 ` [PATCH v3 15/31] elx: efct: Data structures and defines for hw operations James Smart
2020-04-16  6:51   ` Hannes Reinecke
2020-04-23  2:57     ` James Smart
2020-04-16  7:22   ` Daniel Wagner
2020-04-23  2:59     ` James Smart
2020-04-12  3:32 ` [PATCH v3 16/31] elx: efct: Driver initialization routines James Smart
2020-04-16  7:11   ` Hannes Reinecke
2020-04-23  3:09     ` James Smart
2020-04-16  8:03   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 17/31] elx: efct: Hardware queues creation and deletion James Smart
2020-04-16  7:14   ` Hannes Reinecke
2020-04-16  8:24   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 18/31] elx: efct: RQ buffer, memory pool allocation and deallocation APIs James Smart
2020-04-16  7:24   ` Hannes Reinecke
2020-04-23  3:16     ` James Smart
2020-04-16  8:41   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 19/31] elx: efct: Hardware IO and SGL initialization James Smart
2020-04-16  7:32   ` Hannes Reinecke
2020-04-16  8:47   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 20/31] elx: efct: Hardware queues processing James Smart
2020-04-16  7:37   ` Hannes Reinecke [this message]
2020-04-16  9:17   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 21/31] elx: efct: Unsolicited FC frame processing routines James Smart
2020-04-16  9:36   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 22/31] elx: efct: Extended link Service IO handling James Smart
2020-04-16  7:58   ` Hannes Reinecke
2020-04-23  3:30     ` James Smart
2020-04-16  9:49   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 23/31] elx: efct: SCSI IO handling routines James Smart
2020-04-16 11:40   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 24/31] elx: efct: LIO backend interface routines James Smart
2020-04-12  4:57   ` Bart Van Assche
2020-04-16 11:48     ` Daniel Wagner
2020-04-22  4:20     ` James Smart
2020-04-22  5:09       ` Bart Van Assche
2020-04-23  1:39         ` James Smart
2020-04-16  8:02   ` Hannes Reinecke
2020-04-16 12:34   ` Daniel Wagner
2020-04-22  4:20     ` James Smart
2020-04-12  3:32 ` [PATCH v3 25/31] elx: efct: Hardware IO submission routines James Smart
2020-04-16  8:10   ` Hannes Reinecke
2020-04-16 12:45     ` Daniel Wagner
2020-04-23  3:37       ` James Smart
2020-04-16 12:44   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 26/31] elx: efct: link statistics and SFP data James Smart
2020-04-16 12:55   ` Daniel Wagner
2020-04-12  3:32 ` [PATCH v3 27/31] elx: efct: xport and hardware teardown routines James Smart
2020-04-16  9:45   ` Hannes Reinecke
2020-04-16 13:01   ` Daniel Wagner
2020-04-12  3:33 ` [PATCH v3 28/31] elx: efct: Firmware update, async link processing James Smart
2020-04-16 10:01   ` Hannes Reinecke
2020-04-16 13:10   ` Daniel Wagner
2020-04-12  3:33 ` [PATCH v3 29/31] elx: efct: scsi_transport_fc host interface support James Smart
2020-04-12  3:33 ` [PATCH v3 30/31] elx: efct: Add Makefile and Kconfig for efct driver James Smart
2020-04-16 10:02   ` Hannes Reinecke
2020-04-16 13:15   ` Daniel Wagner
2020-04-12  3:33 ` [PATCH v3 31/31] elx: efct: Tie into kernel Kconfig and build process James Smart
2020-04-12  6:16   ` kbuild test robot
2020-04-12  6:16     ` kbuild test robot
2020-04-12  7:56   ` kbuild test robot
2020-04-12  7:56     ` kbuild test robot
2020-04-16 13:15   ` Daniel Wagner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d03fc64e-54e2-5d62-da8a-fc8a5cc67b85@suse.de \
    --to=hare@suse.de \
    --cc=bvanassche@acm.org \
    --cc=dwagner@suse.de \
    --cc=herbszt@gmx.de \
    --cc=jsmart2021@gmail.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=maier@linux.ibm.com \
    --cc=natechancellor@gmail.com \
    --cc=ram.vegesna@broadcom.com \
    --cc=rdunlap@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.