diff options
author | Saurav Kashyap <skashyap@marvell.com> | 2019-03-26 10:38:38 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-03-28 04:54:52 +0300 |
commit | 69ef2c692510d5154c613569caeeed3c74806231 (patch) | |
tree | 5a9e9b0ee3ecfe4d1c0eacaa4067e76769ac422b /drivers/scsi/qedf/qedf_els.c | |
parent | 5d5e55659b375a39a42dad988869cd9966d20255 (diff) | |
download | linux-69ef2c692510d5154c613569caeeed3c74806231.tar.xz |
scsi: qedf: Modify abort and tmf handler to handle edge condition and flush
An I/O can be in any state when flush is called, it can be in abort,
waiting for abort, RRQ send and waiting or TMF send.
- HZ can be different on different architecture, correctly set abort
timeout value.
- Flush can complete the I/Os prematurely, handle refcount for aborted
I/Os and for which RRQ is pending.
- Differentiate LUN/TARGET reset, as cleanup needs to be send to firmware
accordingly.
- Add flush mutex to sync cleanup call from abort and flush routine.
- Clear abort/outstanding bit on timeout.
Signed-off-by: Shyam Sundar <shyam.sundar@marvell.com>
Signed-off-by: Chad Dupuis <cdupuis@marvell.com>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qedf/qedf_els.c')
-rw-r--r-- | drivers/scsi/qedf/qedf_els.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c index a60819b40eaf..ac2bfc26bcdb 100644 --- a/drivers/scsi/qedf/qedf_els.c +++ b/drivers/scsi/qedf/qedf_els.c @@ -201,8 +201,12 @@ static void qedf_rrq_compl(struct qedf_els_cb_arg *cb_arg) " 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: @@ -229,6 +233,7 @@ int qedf_send_rrq(struct qedf_ioreq *aborted_io_req) 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"); @@ -237,6 +242,15 @@ int qedf_send_rrq(struct qedf_ioreq *aborted_io_req) 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)) { QEDF_ERR(NULL, "fcport is no longer offloaded.\n"); @@ -249,6 +263,19 @@ int qedf_send_rrq(struct qedf_ioreq *aborted_io_req) } 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; |