From 29528491ccf76ff017f29c6ff24f2d8945b43d7e Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 1 May 2018 09:01:45 -0700 Subject: scsi: qla2xxx: Fix Rport and session state getting out of sync This patch fixes rport state and session state getting out of sync. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_target.c') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 025dc2d..8564070 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -601,24 +601,18 @@ void qla2x00_async_nack_sp_done(void *s, int res) vha->fcport_count++; - if (!IS_IIDMA_CAPABLE(vha->hw) || - !vha->hw->flags.gpsc_supported) { - ql_dbg(ql_dbg_disc, vha, 0x20f3, - "%s %d %8phC post upd_fcport fcp_cnt %d\n", - __func__, __LINE__, - sp->fcport->port_name, - vha->fcport_count); - sp->fcport->disc_state = DSC_UPD_FCPORT; - qla24xx_post_upd_fcport_work(vha, sp->fcport); - } else { - ql_dbg(ql_dbg_disc, vha, 0x20f5, - "%s %d %8phC post gpsc fcp_cnt %d\n", - __func__, __LINE__, - sp->fcport->port_name, - vha->fcport_count); - - qla24xx_post_gpsc_work(vha, sp->fcport); - } + ql_dbg(ql_dbg_disc, vha, 0x20f3, + "%s %d %8phC post upd_fcport fcp_cnt %d\n", + __func__, __LINE__, + sp->fcport->port_name, + vha->fcport_count); + sp->fcport->disc_state = DSC_UPD_FCPORT; + qla24xx_post_upd_fcport_work(vha, sp->fcport); + } else { + sp->fcport->login_retry = 0; + sp->fcport->disc_state = DSC_LOGIN_COMPLETE; + sp->fcport->deleted = 0; + sp->fcport->logout_on_delete = 1; } break; -- cgit v1.1 From cc28e0ace97c5615cc2333d98827751cd0d794d1 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 1 May 2018 09:01:48 -0700 Subject: scsi: qla2xxx: Move GPSC and GFPNID out of session management Move GPSC & GFPNID commands out of session management to reduce time lag in reporting the session state to remote port. These commands are not essential when it comes to maintaining the rport state. Delay sending these commands after rport state is set to Online. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi/qla2xxx/qla_target.c') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 8564070..3e8bf72 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4835,7 +4835,6 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, switch (sess->disc_state) { case DSC_LOGIN_PEND: case DSC_GPDB: - case DSC_GPSC: case DSC_UPD_FCPORT: case DSC_LOGIN_COMPLETE: case DSC_ADISC: -- cgit v1.1 From 8ea4faf829eb2ea36dd0c989965c029390d238f3 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 1 May 2018 09:01:49 -0700 Subject: scsi: qla2xxx: Fix Inquiry command being dropped in Target mode When a connection is established, the target core session may not be created immediately. Current code will drop/terminate the command based on the session state. This patch will return BUSY status for any commands arriving on wire before the session is created. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_target.c') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 3e8bf72..5e81b64 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -5140,10 +5140,15 @@ static int __qlt_send_busy(struct qla_qpair *qpair, struct fc_port *sess = NULL; unsigned long flags; u16 temp; + port_id_t id; + + id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2]; + id.b.area = atio->u.isp24.fcp_hdr.s_id[1]; + id.b.domain = atio->u.isp24.fcp_hdr.s_id[0]; + id.b.rsvd_1 = 0; spin_lock_irqsave(&ha->tgt.sess_lock, flags); - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - atio->u.isp24.fcp_hdr.s_id); + sess = qla2x00_find_fcport_by_nportid(vha, &id, 1); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); if (!sess) { qlt_send_term_exchange(qpair, NULL, atio, 1, 0); -- cgit v1.1 From e25f76549bd7794aa171e1d998514d8d99172b1f Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 1 May 2018 09:01:50 -0700 Subject: scsi: qla2xxx: Use predefined get_datalen_for_atio() inline function - Uses predefine inline function to access add_cdb_len field in ATIO. - Return SS_RESIDUAL_UNDER status when sending BUSY Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_target.c') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 5e81b64..a77703f 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3550,13 +3550,6 @@ static int __qlt_send_term_exchange(struct qla_qpair *qpair, temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio24->u.status1.ox_id = cpu_to_le16(temp); - /* Most likely, it isn't needed */ - ctio24->u.status1.residual = get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len]); - if (ctio24->u.status1.residual != 0) - ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; - /* Memory Barrier */ wmb(); if (qpair->reqq_start_iocbs) @@ -4051,9 +4044,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) fcp_task_attr = qlt_get_fcp_task_attr(vha, atio->u.isp24.fcp_cmnd.task_attr); - data_length = be32_to_cpu(get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len])); + data_length = get_datalen_for_atio(atio); ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, fcp_task_attr, data_dir, bidi); @@ -5187,6 +5178,12 @@ static int __qlt_send_busy(struct qla_qpair *qpair, */ ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); ctio24->u.status1.scsi_status = cpu_to_le16(status); + + ctio24->u.status1.residual = get_datalen_for_atio(atio); + + if (ctio24->u.status1.residual != 0) + ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; + /* Memory Barrier */ wmb(); if (qpair->reqq_start_iocbs) -- cgit v1.1 From 84905dfe78d28b597a1c991bfc05722a8fba1184 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Tue, 1 May 2018 09:01:53 -0700 Subject: scsi: qla2xxx: Fix TMF and Multi-Queue config For target mode, task management command is queued to specific cpu base on where the SCSI command is residing. This prevent race condition of task management command getting ahead of regular scsi command. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 135 +++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 24 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_target.c') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index a77703f..b85c833 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1924,13 +1924,84 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha, spin_unlock_irqrestore(&vha->cmd_list_lock, flags); } +static struct qla_qpair_hint *qlt_find_qphint(struct scsi_qla_host *vha, + uint64_t unpacked_lun) +{ + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + struct qla_qpair_hint *h = NULL; + + if (vha->flags.qpairs_available) { + h = btree_lookup64(&tgt->lun_qpair_map, unpacked_lun); + if (!h) + h = &tgt->qphints[0]; + } else { + h = &tgt->qphints[0]; + } + + return h; +} + +static void qlt_do_tmr_work(struct work_struct *work) +{ + struct qla_tgt_mgmt_cmd *mcmd = + container_of(work, struct qla_tgt_mgmt_cmd, work); + struct qla_hw_data *ha = mcmd->vha->hw; + int rc = EIO; + uint32_t tag; + unsigned long flags; + + switch (mcmd->tmr_func) { + case QLA_TGT_ABTS: + tag = mcmd->orig_iocb.abts.exchange_addr_to_abort; + break; + default: + tag = 0; + break; + } + + rc = ha->tgt.tgt_ops->handle_tmr(mcmd, mcmd->unpacked_lun, + mcmd->tmr_func, tag); + + if (rc != 0) { + spin_lock_irqsave(mcmd->qpair->qp_lock_ptr, flags); + switch (mcmd->tmr_func) { + case QLA_TGT_ABTS: + qlt_24xx_send_abts_resp(mcmd->qpair, + &mcmd->orig_iocb.abts, + FCP_TMF_REJECTED, false); + break; + case QLA_TGT_LUN_RESET: + case QLA_TGT_CLEAR_TS: + case QLA_TGT_ABORT_TS: + case QLA_TGT_CLEAR_ACA: + case QLA_TGT_TARGET_RESET: + qlt_send_busy(mcmd->qpair, &mcmd->orig_iocb.atio, + qla_sam_status); + break; + + case QLA_TGT_ABORT_ALL: + case QLA_TGT_NEXUS_LOSS_SESS: + case QLA_TGT_NEXUS_LOSS: + qlt_send_notify_ack(mcmd->qpair, + &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0); + break; + } + spin_unlock_irqrestore(mcmd->qpair->qp_lock_ptr, flags); + + ql_dbg(ql_dbg_tgt_mgt, mcmd->vha, 0xf052, + "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n", + mcmd->vha->vp_idx, rc); + mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); + } +} + /* ha->hardware_lock supposed to be held on entry */ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct abts_recv_from_24xx *abts, struct fc_port *sess) { struct qla_hw_data *ha = vha->hw; struct qla_tgt_mgmt_cmd *mcmd; - int rc; + struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0]; if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) { /* send TASK_ABORT response immediately */ @@ -1955,23 +2026,29 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); mcmd->reset_count = ha->base_qpair->chip_reset; mcmd->tmr_func = QLA_TGT_ABTS; - mcmd->qpair = ha->base_qpair; + mcmd->qpair = h->qpair; mcmd->vha = vha; /* * LUN is looked up by target-core internally based on the passed * abts->exchange_addr_to_abort tag. */ - rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, mcmd->tmr_func, - abts->exchange_addr_to_abort); - if (rc != 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, - "qla_target(%d): tgt_ops->handle_tmr()" - " failed: %d", vha->vp_idx, rc); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -EFAULT; + mcmd->se_cmd.cpuid = h->cpuid; + + if (ha->tgt.tgt_ops->find_cmd_by_tag) { + struct qla_tgt_cmd *abort_cmd; + + abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess, + abts->exchange_addr_to_abort); + if (abort_cmd && abort_cmd->qpair) { + mcmd->qpair = abort_cmd->qpair; + mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid; + } } + INIT_WORK(&mcmd->work, qlt_do_tmr_work); + queue_work_on(mcmd->se_cmd.cpuid, qla_tgt_wq, &mcmd->work); + return 0; } @@ -4320,7 +4397,7 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, struct qla_hw_data *ha = vha->hw; struct qla_tgt_mgmt_cmd *mcmd; struct atio_from_isp *a = (struct atio_from_isp *)iocb; - int res; + struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0]; mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); if (!mcmd) { @@ -4340,24 +4417,36 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, mcmd->tmr_func = fn; mcmd->flags = flags; mcmd->reset_count = ha->base_qpair->chip_reset; - mcmd->qpair = ha->base_qpair; + mcmd->qpair = h->qpair; mcmd->vha = vha; + mcmd->se_cmd.cpuid = h->cpuid; + mcmd->unpacked_lun = lun; switch (fn) { case QLA_TGT_LUN_RESET: - abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); - break; - } + case QLA_TGT_CLEAR_TS: + case QLA_TGT_ABORT_TS: + abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); + /* drop through */ + case QLA_TGT_CLEAR_ACA: + h = qlt_find_qphint(vha, mcmd->unpacked_lun); + mcmd->qpair = h->qpair; + mcmd->se_cmd.cpuid = h->cpuid; + break; - res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func, 0); - if (res != 0) { - ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b, - "qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n", - sess->vha->vp_idx, res); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -EFAULT; + case QLA_TGT_TARGET_RESET: + case QLA_TGT_NEXUS_LOSS_SESS: + case QLA_TGT_NEXUS_LOSS: + case QLA_TGT_ABORT_ALL: + default: + /* no-op */ + break; } + INIT_WORK(&mcmd->work, qlt_do_tmr_work); + queue_work_on(mcmd->se_cmd.cpuid, qla_tgt_wq, + &mcmd->work); + return 0; } @@ -5097,8 +5186,6 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf038, "qla_target(%d): Immediate notify task %x\n", vha->vp_idx, iocb->u.isp2x.task_flags); - if (qlt_handle_task_mgmt(vha, iocb) == 0) - send_notify_ack = 0; break; case IMM_NTFY_ELS: -- cgit v1.1