Re: [PATCH v3 19/31] elx: efct: Hardware IO and SGL initialization

Hannes Reinecke
2020-04-16T07:32:54Z

On 4/12/20 5:32 AM, James Smart wrote:
> This patch continues the efct driver population.
>
> This patch adds driver definitions for:
> Routines to create IO interfaces (wqs, etc), SGL initialization,
> and configure hardware features.
>
> Signed-off-by: Ram Vegesna <ram.vegesna@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
>
> ---
> v3:
> Request tag pool(reqtag_pool) handling fuctions.
> ---
> drivers/scsi/elx/efct/efct_hw.c | 657 ++++++++++++++++++++++++++++++++++++++++
> drivers/scsi/elx/efct/efct_hw.h | 42 +++
> 2 files changed, 699 insertions(+)
>
> diff --git a/drivers/scsi/elx/efct/efct_hw.c b/drivers/scsi/elx/efct/efct_hw.c
> index 3e9906749da2..892493a3a35e 100644
> --- a/drivers/scsi/elx/efct/efct_hw.c
> +++ b/drivers/scsi/elx/efct/efct_hw.c
[ .. ]
> +enum efct_hw_rtn
> +efct_hw_io_abort(struct efct_hw *hw, struct efct_hw_io *io_to_abort,
> + bool send_abts, void *cb, void *arg)
> +{
> + enum sli4_abort_type atype = SLI_ABORT_MAX;
> + u32 id = 0, mask = 0;
> + enum efct_hw_rtn rc = EFCT_HW_RTN_SUCCESS;
> + struct hw_wq_callback *wqcb;
> + unsigned long flags = 0;
> +
> + if (!io_to_abort) {
> + efc_log_err(hw->os,
> + "bad parameter hw=%p io=%p\n",
> + hw, io_to_abort);
> + return EFCT_HW_RTN_ERROR;
> + }
> +
> + if (hw->state != EFCT_HW_STATE_ACTIVE) {
> + efc_log_err(hw->os, "cannot send IO abort, HW state=%d\n",
> + hw->state);
> + return EFCT_HW_RTN_ERROR;
> + }
> +
> + /* take a reference on IO being aborted */
> + if (kref_get_unless_zero(&io_to_abort->ref) == 0) {
> + /* command no longer active */
> + efc_log_test(hw->os,
> + "io not active xri=0x%x tag=0x%x\n",
> + io_to_abort->indicator, io_to_abort->reqtag);
> + return EFCT_HW_RTN_IO_NOT_ACTIVE;
> + }
> +
> + /* Must have a valid WQ reference */
> + if (!io_to_abort->wq) {
> + efc_log_test(hw->os, "io_to_abort xri=0x%x not active on WQ\n",
> + io_to_abort->indicator);
> + /* efct_ref_get(): same function */
> + kref_put(&io_to_abort->ref, io_to_abort->release);
> + return EFCT_HW_RTN_IO_NOT_ACTIVE;
> + }
> +
> + /*
> + * Validation checks complete; now check to see if already being
> + * aborted
> + */
> + spin_lock_irqsave(&hw->io_abort_lock, flags);
> + if (io_to_abort->abort_in_progress) {
> + spin_unlock_irqrestore(&hw->io_abort_lock, flags);
> + /* efct_ref_get(): same function */
> + kref_put(&io_to_abort->ref, io_to_abort->release);
> + efc_log_debug(hw->os,
> + "io already being aborted xri=0x%x tag=0x%x\n",
> + io_to_abort->indicator, io_to_abort->reqtag);
> + return EFCT_HW_RTN_IO_ABORT_IN_PROGRESS;
> + }
> +
> + /*
> + * This IO is not already being aborted. Set flag so we won't try to
> + * abort it again. After all, we only have one abort_done callback.
> + */
> + io_to_abort->abort_in_progress = true;
> + spin_unlock_irqrestore(&hw->io_abort_lock, flags);
> +
> + /*
> + * If we got here, the possibilities are:
> + * - host owned xri
> + * - io_to_abort->wq_index != U32_MAX
> + * - submit ABORT_WQE to same WQ
> + * - port owned xri:
> + * - rxri: io_to_abort->wq_index == U32_MAX
> + * - submit ABORT_WQE to any WQ
> + * - non-rxri
> + * - io_to_abort->index != U32_MAX
> + * - submit ABORT_WQE to same WQ
> + * - io_to_abort->index == U32_MAX
> + * - submit ABORT_WQE to any WQ
> + */
> + io_to_abort->abort_done = cb;
> + io_to_abort->abort_arg = arg;
> +
> + atype = SLI_ABORT_XRI;
> + id = io_to_abort->indicator;
> +
> + /* Allocate a request tag for the abort portion of this IO */
> + wqcb = efct_hw_reqtag_alloc(hw, efct_hw_wq_process_abort, io_to_abort);
> + if (!wqcb) {
> + efc_log_err(hw->os, "can't allocate request tag\n");
> + return EFCT_HW_RTN_NO_RESOURCES;
> + }
> + io_to_abort->abort_reqtag = wqcb->instance_index;
> +
> + /*
> + * If the wqe is on the pending list, then set this wqe to be
> + * aborted when the IO's wqe is removed from the list.
> + */
> + if (io_to_abort->wq) {
> + spin_lock_irqsave(&io_to_abort->wq->queue->lock, flags);
> + if (io_to_abort->wqe.list_entry.next) {
> + io_to_abort->wqe.abort_wqe_submit_needed = true;
> + io_to_abort->wqe.send_abts = send_abts;
> + io_to_abort->wqe.id = id;
> + io_to_abort->wqe.abort_reqtag =
> + io_to_abort->abort_reqtag;
> + spin_unlock_irqrestore(&io_to_abort->wq->queue->lock,
> + flags);
> + return EFC_SUCCESS;
> + }
> + spin_unlock_irqrestore(&io_to_abort->wq->queue->lock, flags);
> + }
> +
> + if (sli_abort_wqe(&hw->sli, io_to_abort->wqe.wqebuf,
> + hw->sli.wqe_size, atype, send_abts, id, mask,
> + io_to_abort->abort_reqtag, SLI4_CQ_DEFAULT)) {

Wouldn't it be better if we were to pass the 'wqe' directly here?
That would cut down on the number of arguments required, and make the
function more readable.
Not to mention that we'll be more efficient if we manage to cut down the
number of arguments to '4' or even less, as then we wouldn't need to
pass arguments on the stack.

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