diff options
Diffstat (limited to 'drivers/scsi/qedf/qedf_els.c')
-rw-r--r-- | drivers/scsi/qedf/qedf_els.c | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c index 87e169dcebdb..1ff5bc314fc0 100644 --- a/drivers/scsi/qedf/qedf_els.c +++ b/drivers/scsi/qedf/qedf_els.c @@ -16,7 +16,7 @@ static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op, struct qedf_ioreq *els_req; struct qedf_mp_req *mp_req; struct fc_frame_header *fc_hdr; - struct e4_fcoe_task_context *task; + struct fcoe_task_context *task; int rc = 0; uint32_t did, sid; uint16_t xid; @@ -124,7 +124,7 @@ static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op, 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); @@ -143,10 +143,33 @@ void qedf_process_els_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, struct qedf_ioreq *els_req) { 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 */ @@ -185,10 +208,6 @@ static void qedf_rrq_compl(struct qedf_els_cb_arg *cb_arg) 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", @@ -388,14 +407,10 @@ void qedf_restart_rport(struct qedf_rport *fcport) mutex_lock(&lport->disc.disc_mutex); /* Recreate the rport and log back in */ rdata = fc_rport_create(lport, port_id); - if (rdata) { - mutex_unlock(&lport->disc.disc_mutex); + mutex_unlock(&lport->disc.disc_mutex); + if (rdata) fc_rport_login(rdata); - fcport->rdata = rdata; - } else { - mutex_unlock(&lport->disc.disc_mutex); - fcport->rdata = NULL; - } + fcport->rdata = rdata; } clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags); } @@ -887,6 +902,11 @@ static void qedf_rec_compl(struct qedf_els_cb_arg *cb_arg) 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); |