From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- kernel/drivers/scsi/qedf/qedf_els.c | 137 ++++++++++++++++++++++++++++++++++++--------- 1 files changed, 108 insertions(+), 29 deletions(-) diff --git a/kernel/drivers/scsi/qedf/qedf_els.c b/kernel/drivers/scsi/qedf/qedf_els.c index 5178cd0..625e58c 100644 --- a/kernel/drivers/scsi/qedf/qedf_els.c +++ b/kernel/drivers/scsi/qedf/qedf_els.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * QLogic FCoE Offload Driver * Copyright (c) 2016-2018 Cavium Inc. - * - * This software is available under the terms of the GNU General Public License - * (GPL) Version 2, available from the file COPYING in the main directory of - * this source tree. */ #include "qedf.h" @@ -127,7 +124,7 @@ task = qedf_get_task_mem(&qedf->tasks, xid); qedf_init_mp_task(els_req, task, sqe); - /* Put timer on original I/O request */ + /* Put timer on els request */ if (timer_msec) qedf_cmd_timer_set(qedf, els_req, timer_msec); @@ -135,6 +132,8 @@ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Ringing doorbell for ELS " "req\n"); qedf_ring_doorbell(fcport); + set_bit(QEDF_CMD_OUTSTANDING, &els_req->flags); + spin_unlock_irqrestore(&fcport->rport_lock, flags); els_err: return rc; @@ -143,20 +142,38 @@ void qedf_process_els_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, struct qedf_ioreq *els_req) { - struct fcoe_task_context *task_ctx; - struct scsi_cmnd *sc_cmd; - uint16_t xid; struct fcoe_cqe_midpath_info *mp_info; + struct qedf_rport *fcport; QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Entered with xid = 0x%x" " cmd_type = %d.\n", els_req->xid, els_req->cmd_type); + if ((els_req->event == QEDF_IOREQ_EV_ELS_FLUSH) + || (els_req->event == QEDF_IOREQ_EV_CLEANUP_SUCCESS) + || (els_req->event == QEDF_IOREQ_EV_CLEANUP_FAILED)) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "ELS completion xid=0x%x after flush event=0x%x", + els_req->xid, els_req->event); + return; + } + + fcport = els_req->fcport; + + /* When flush is active, + * let the cmds be completed from the cleanup context + */ + if (test_bit(QEDF_RPORT_IN_TARGET_RESET, &fcport->flags) || + test_bit(QEDF_RPORT_IN_LUN_RESET, &fcport->flags)) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "Dropping ELS completion xid=0x%x as fcport is flushing", + els_req->xid); + return; + } + + clear_bit(QEDF_CMD_OUTSTANDING, &els_req->flags); + /* Kill the ELS timer */ cancel_delayed_work(&els_req->timeout_work); - - xid = els_req->xid; - task_ctx = qedf_get_task_mem(&qedf->tasks, xid); - sc_cmd = els_req->sc_cmd; /* Get ELS response length from CQE */ mp_info = &cqe->cqe_info.midpath_info; @@ -185,20 +202,23 @@ orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(&qedf->dbg_ctx, + "Original io_req is NULL, rrq_req = %p.\n", rrq_req); goto out_free; - - if (rrq_req->event != QEDF_IOREQ_EV_ELS_TMO && - rrq_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT) - cancel_delayed_work_sync(&orig_io_req->timeout_work); + } refcount = kref_read(&orig_io_req->refcount); QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "rrq_compl: orig io = %p," " orig xid = 0x%x, rrq_xid = 0x%x, refcount=%d\n", orig_io_req, orig_io_req->xid, rrq_req->xid, refcount); - /* This should return the aborted io_req to the command pool */ - if (orig_io_req) + /* + * This should return the aborted io_req to the command pool. Note that + * we need to check the refcound in case the original request was + * flushed but we get a completion on this xid. + */ + if (orig_io_req && refcount > 0) kref_put(&orig_io_req->refcount, qedf_release_cmd); out_free: @@ -225,6 +245,7 @@ uint32_t sid; uint32_t r_a_tov; int rc; + int refcount; if (!aborted_io_req) { QEDF_ERR(NULL, "abort_io_req is NULL.\n"); @@ -232,6 +253,15 @@ } fcport = aborted_io_req->fcport; + + if (!fcport) { + refcount = kref_read(&aborted_io_req->refcount); + QEDF_ERR(NULL, + "RRQ work was queued prior to a flush xid=0x%x, refcount=%d.\n", + aborted_io_req->xid, refcount); + kref_put(&aborted_io_req->refcount, qedf_release_cmd); + return -EINVAL; + } /* Check that fcport is still offloaded */ if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { @@ -245,6 +275,19 @@ } qedf = fcport->qedf; + + /* + * Sanity check that we can send a RRQ to make sure that refcount isn't + * 0 + */ + refcount = kref_read(&aborted_io_req->refcount); + if (refcount != 1) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_ELS, + "refcount for xid=%x io_req=%p refcount=%d is not 1.\n", + aborted_io_req->xid, aborted_io_req, refcount); + return -EINVAL; + } + lport = qedf->lport; sid = fcport->sid; r_a_tov = lport->r_a_tov; @@ -327,32 +370,47 @@ struct fc_lport *lport; struct fc_rport_priv *rdata; u32 port_id; + unsigned long flags; - if (!fcport) + if (!fcport) { + QEDF_ERR(NULL, "fcport is NULL.\n"); return; + } + spin_lock_irqsave(&fcport->rport_lock, flags); if (test_bit(QEDF_RPORT_IN_RESET, &fcport->flags) || !test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags) || test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) { QEDF_ERR(&(fcport->qedf->dbg_ctx), "fcport %p already in reset or not offloaded.\n", fcport); + spin_unlock_irqrestore(&fcport->rport_lock, flags); return; } /* Set that we are now in reset */ set_bit(QEDF_RPORT_IN_RESET, &fcport->flags); + spin_unlock_irqrestore(&fcport->rport_lock, flags); rdata = fcport->rdata; - if (rdata) { + if (rdata && !kref_get_unless_zero(&rdata->kref)) { + fcport->rdata = NULL; + rdata = NULL; + } + + if (rdata && rdata->rp_state == RPORT_ST_READY) { lport = fcport->qedf->lport; port_id = rdata->ids.port_id; QEDF_ERR(&(fcport->qedf->dbg_ctx), "LOGO port_id=%x.\n", port_id); fc_rport_logoff(rdata); + kref_put(&rdata->kref, fc_rport_destroy); + mutex_lock(&lport->disc.disc_mutex); /* Recreate the rport and log back in */ rdata = fc_rport_create(lport, port_id); + mutex_unlock(&lport->disc.disc_mutex); if (rdata) fc_rport_login(rdata); + fcport->rdata = rdata; } clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags); } @@ -380,8 +438,11 @@ * If we are flushing the command just free the cb_arg as none of the * response data will be valid. */ - if (els_req->event == QEDF_IOREQ_EV_ELS_FLUSH) + if (els_req->event == QEDF_IOREQ_EV_ELS_FLUSH) { + QEDF_ERR(NULL, "els_req xid=0x%x event is flush.\n", + els_req->xid); goto free_arg; + } fcport = els_req->fcport; mp_req = &(els_req->mp_req); @@ -494,8 +555,10 @@ orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(NULL, "orig_io_req is NULL.\n"); goto out_free; + } clear_bit(QEDF_CMD_SRR_SENT, &orig_io_req->flags); @@ -509,8 +572,11 @@ orig_io_req, orig_io_req->xid, srr_req->xid, refcount); /* If a SRR times out, simply free resources */ - if (srr_req->event == QEDF_IOREQ_EV_ELS_TMO) + if (srr_req->event == QEDF_IOREQ_EV_ELS_TMO) { + QEDF_ERR(&qedf->dbg_ctx, + "ELS timeout rec_xid=0x%x.\n", srr_req->xid); goto out_put; + } /* Normalize response data into struct fc_frame */ mp_req = &(srr_req->mp_req); @@ -561,7 +627,7 @@ struct qedf_rport *fcport; struct fc_lport *lport; struct qedf_els_cb_arg *cb_arg = NULL; - u32 sid, r_a_tov; + u32 r_a_tov; int rc; if (!orig_io_req) { @@ -587,7 +653,6 @@ qedf = fcport->qedf; lport = qedf->lport; - sid = fcport->sid; r_a_tov = lport->r_a_tov; QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Sending SRR orig_io=%p, " @@ -684,8 +749,11 @@ cb_arg = io_req->cb_arg; /* If we timed out just free resources */ - if (io_req->event == QEDF_IOREQ_EV_ELS_TMO || !cqe) + if (io_req->event == QEDF_IOREQ_EV_ELS_TMO || !cqe) { + QEDF_ERR(&qedf->dbg_ctx, + "cqe is NULL or timeout event (0x%x)", io_req->event); goto free; + } /* Kill the timer we put on the request */ cancel_delayed_work_sync(&io_req->timeout_work); @@ -788,8 +856,10 @@ orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(NULL, "orig_io_req is NULL.\n"); goto out_free; + } if (rec_req->event != QEDF_IOREQ_EV_ELS_TMO && rec_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT) @@ -801,8 +871,12 @@ orig_io_req, orig_io_req->xid, rec_req->xid, refcount); /* If a REC times out, free resources */ - if (rec_req->event == QEDF_IOREQ_EV_ELS_TMO) + if (rec_req->event == QEDF_IOREQ_EV_ELS_TMO) { + QEDF_ERR(&qedf->dbg_ctx, + "Got TMO event, orig_io_req %p orig_io_xid=0x%x.\n", + orig_io_req, orig_io_req->xid); goto out_put; + } /* Normalize response data into struct fc_frame */ mp_req = &(rec_req->mp_req); @@ -828,6 +902,11 @@ opcode = fc_frame_payload_op(fp); if (opcode == ELS_LS_RJT) { rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + if (!rjt) { + QEDF_ERR(&qedf->dbg_ctx, "payload get failed"); + goto out_free_frame; + } + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Received LS_RJT for REC: er_reason=0x%x, " "er_explan=0x%x.\n", rjt->er_reason, rjt->er_explan); -- Gitblit v1.6.2