There are a couple of kernel cases when we restart a remote port due to ABTS timeout that we need to handle: 1. Flush any outstanding ABTS requests when flushing I/Os so that we do not hold up the eh_abort handler indefinitely causing process hangs. 2. Check if we are currently uploading a connection before issuing an ABTS. Signed-off-by: Chad Dupuis <chad.dupuis@xxxxxxxxxx> --- drivers/scsi/qedf/qedf_io.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index 589414f06376..f669df03f37d 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -1457,6 +1457,31 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun) goto free_cmd; } + if (io_req->cmd_type == QEDF_ABTS) { + rc = kref_get_unless_zero(&io_req->refcount); + if (!rc) { + QEDF_ERR(&(qedf->dbg_ctx), + "Could not get kref for abort io_req=0x%p xid=0x%x.\n", + io_req, io_req->xid); + continue; + } + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "Flushing abort xid=0x%x.\n", io_req->xid); + + clear_bit(QEDF_CMD_IN_ABORT, &io_req->flags); + + if (io_req->sc_cmd) { + if (io_req->return_scsi_cmd_on_abts) + qedf_scsi_done(qedf, io_req, DID_ERROR); + } + + /* Notify eh_abort handler that ABTS is complete */ + complete(&io_req->abts_done); + kref_put(&io_req->refcount, qedf_release_cmd); + + goto free_cmd; + } + if (!io_req->sc_cmd) continue; if (lun > 0) { @@ -1534,6 +1559,11 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) goto abts_err; } + if (test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) { + QEDF_ERR(&qedf->dbg_ctx, "fcport is uploading.\n"); + rc = 1; + goto out; + } kref_get(&io_req->refcount); @@ -1573,6 +1603,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) * task at the firmware. */ qedf_initiate_cleanup(io_req, return_scsi_cmd_on_abts); +out: return rc; } -- 2.12.3