diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 41 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 105 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 192 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 37 |
9 files changed, 259 insertions, 133 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index eb2ec1fb07cb..9442e18aef6f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2279,8 +2279,6 @@ enum discovery_state { DSC_LOGIN_PEND, DSC_LOGIN_FAILED, DSC_GPDB, - DSC_GFPN_ID, - DSC_GPSC, DSC_UPD_FCPORT, DSC_LOGIN_COMPLETE, DSC_ADISC, @@ -2346,6 +2344,7 @@ typedef struct fc_port { unsigned int login_succ:1; unsigned int query:1; unsigned int id_changed:1; + unsigned int rscn_rcvd:1; struct work_struct nvme_del_work; struct completion nvme_del_done; @@ -3226,6 +3225,7 @@ enum qla_work_type { QLA_EVT_GNNID, QLA_EVT_GFPNID, QLA_EVT_SP_RETRY, + QLA_EVT_IIDMA, }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 3c4c84ed0f0f..f68eb6096559 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -116,7 +116,8 @@ extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); - +int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); +void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); /* * Global Data in qla_os.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 9e914f9c3ffb..4bc2b66b299f 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3175,7 +3175,6 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); - fcport->flags &= ~FCF_ASYNC_SENT; done: fcport->flags &= ~FCF_ASYNC_ACTIVE; return rval; @@ -3239,7 +3238,7 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea) return; } - qla24xx_post_upd_fcport_work(vha, ea->fcport); + qla_post_iidma_work(vha, fcport); } static void qla24xx_async_gpsc_sp_done(void *s, int res) @@ -3257,8 +3256,6 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) "Async done-%s res %x, WWPN %8phC \n", sp->name, res, fcport->port_name); - fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); - if (res == (DID_ERROR << 16)) { /* entry status error */ goto done; @@ -3327,7 +3324,6 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport) if (!sp) goto done; - fcport->flags |= FCF_ASYNC_SENT; sp->type = SRB_CT_PTHRU_CMD; sp->name = "gpsc"; sp->gen1 = fcport->rscn_gen; @@ -3862,6 +3858,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) bool found; struct fab_scan_rp *rp; unsigned long flags; + u8 recheck = 0; ql_dbg(ql_dbg_disc, vha, 0xffff, "%s enter\n", __func__); @@ -3914,8 +3911,8 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) list_for_each_entry(fcport, &vha->vp_fcports, list) { if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) continue; + fcport->rscn_rcvd = 0; fcport->scan_state = QLA_FCPORT_FOUND; - fcport->d_id.b24 = rp->id.b24; found = true; /* * If device was not a fabric device before. @@ -3923,7 +3920,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { qla2x00_clear_loop_id(fcport); fcport->flags |= FCF_FABRIC_DEVICE; + } else if (fcport->d_id.b24 != rp->id.b24) { + qlt_schedule_sess_for_deletion(fcport); } + fcport->d_id.b24 = rp->id.b24; break; } @@ -3940,10 +3940,13 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) * Logout all previous fabric dev marked lost, except FCP2 devices. */ list_for_each_entry(fcport, &vha->vp_fcports, list) { - if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) + if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { + fcport->rscn_rcvd = 0; continue; + } if (fcport->scan_state != QLA_FCPORT_FOUND) { + fcport->rscn_rcvd = 0; if ((qla_dual_mode_enabled(vha) || qla_ini_mode_enabled(vha)) && atomic_read(&fcport->state) == FCS_ONLINE) { @@ -3961,15 +3964,31 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) continue; } } - } else - qla24xx_fcport_handle_login(vha, fcport); + } else { + if (fcport->rscn_rcvd || + fcport->disc_state != DSC_LOGIN_COMPLETE) { + fcport->rscn_rcvd = 0; + qla24xx_fcport_handle_login(vha, fcport); + } + } } + recheck = 1; out: qla24xx_sp_unmap(vha, sp); spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; spin_unlock_irqrestore(&vha->work_lock, flags); + + if (recheck) { + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->rscn_rcvd) { + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + break; + } + } + } } static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, @@ -4532,7 +4551,6 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); - fcport->flags &= ~FCF_ASYNC_SENT; done: return rval; } @@ -4594,7 +4612,6 @@ static void qla2x00_async_gfpnid_sp_done(void *s, int res) struct event_arg ea; u64 wwn; - fcport->flags &= ~FCF_ASYNC_SENT; wwn = wwn_to_u64(fpn); if (wwn) memcpy(fcport->fabric_port_name, fpn, WWN_SIZE); @@ -4623,12 +4640,10 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport) if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) return rval; - fcport->disc_state = DSC_GFPN_ID; sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); if (!sp) goto done; - fcport->flags |= FCF_ASYNC_SENT; sp->type = SRB_CT_PTHRU_CMD; sp->name = "gfpnid"; sp->gen1 = fcport->rscn_gen; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 8f55dd44adae..1aa3720ea2ed 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1021,30 +1021,11 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) vha->fcport_count++; ea->fcport->login_succ = 1; - if (!IS_IIDMA_CAPABLE(vha->hw) || - !vha->hw->flags.gpsc_supported) { - ql_dbg(ql_dbg_disc, vha, 0x20d6, - "%s %d %8phC post upd_fcport fcp_cnt %d\n", - __func__, __LINE__, ea->fcport->port_name, - vha->fcport_count); - - qla24xx_post_upd_fcport_work(vha, ea->fcport); - } else { - if (ea->fcport->id_changed) { - ea->fcport->id_changed = 0; - ql_dbg(ql_dbg_disc, vha, 0x20d7, - "%s %d %8phC post gfpnid fcp_cnt %d\n", - __func__, __LINE__, ea->fcport->port_name, - vha->fcport_count); - qla24xx_post_gfpnid_work(vha, ea->fcport); - } else { - ql_dbg(ql_dbg_disc, vha, 0x20d7, - "%s %d %8phC post gpsc fcp_cnt %d\n", - __func__, __LINE__, ea->fcport->port_name, - vha->fcport_count); - qla24xx_post_gpsc_work(vha, ea->fcport); - } - } + ql_dbg(ql_dbg_disc, vha, 0x20d6, + "%s %d %8phC post upd_fcport fcp_cnt %d\n", + __func__, __LINE__, ea->fcport->port_name, + vha->fcport_count); + qla24xx_post_upd_fcport_work(vha, ea->fcport); } else if (ea->fcport->login_succ) { /* * We have an existing session. A late RSCN delivery @@ -1167,9 +1148,6 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) fcport->login_gen, fcport->login_retry, fcport->loop_id, fcport->scan_state); - if (fcport->login_retry == 0) - return 0; - if (fcport->scan_state != QLA_FCPORT_FOUND) return 0; @@ -1194,7 +1172,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) return 0; } - fcport->login_retry--; + if (fcport->login_retry > 0) + fcport->login_retry--; switch (fcport->disc_state) { case DSC_DELETED: @@ -1350,20 +1329,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) fc_port_t *f, *tf; uint32_t id = 0, mask, rid; unsigned long flags; - - switch (ea->event) { - case FCME_RSCN: - case FCME_GIDPN_DONE: - case FCME_GPSC_DONE: - case FCME_GPNID_DONE: - case FCME_GNNID_DONE: - if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) || - test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags)) - return; - break; - default: - break; - } + fc_port_t *fcport; switch (ea->event) { case FCME_RELOGIN: @@ -1377,6 +1343,11 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) return; switch (ea->id.b.rsvd_1) { case RSCN_PORT_ADDR: + fcport = qla2x00_find_fcport_by_nportid + (vha, &ea->id, 1); + if (fcport) + fcport->rscn_rcvd = 1; + spin_lock_irqsave(&vha->work_lock, flags); if (vha->scan.scan_flags == 0) { ql_dbg(ql_dbg_disc, vha, 0xffff, @@ -4532,7 +4503,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) fcport->fw_login_state = DSC_LS_PORT_UNAVAIL; fcport->deleted = QLA_SESS_DELETED; fcport->login_retry = vha->hw->login_retry_count; - fcport->login_retry = 5; fcport->logout_on_delete = 1; if (!fcport->ct_desc.ct_sns) { @@ -5054,6 +5024,24 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) } } +void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport) +{ + qla2x00_iidma_fcport(vha, fcport); + qla24xx_update_fcport_fcp_prio(vha, fcport); +} + +int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport) +{ + struct qla_work_evt *e; + + e = qla2x00_alloc_work(vha, QLA_EVT_IIDMA); + if (!e) + return QLA_FUNCTION_FAILED; + + e->u.fcport.fcport = fcport; + return qla2x00_post_work(vha, e); +} + /* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/ static void qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) @@ -5122,13 +5110,14 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) if (IS_QLAFX00(vha->hw)) { qla2x00_set_fcport_state(fcport, FCS_ONLINE); - goto reg_port; + } else { + fcport->login_retry = 0; + fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); + fcport->disc_state = DSC_LOGIN_COMPLETE; + fcport->deleted = 0; + fcport->logout_on_delete = 1; + qla2x00_set_fcport_state(fcport, FCS_ONLINE); } - fcport->login_retry = 0; - fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); - fcport->disc_state = DSC_LOGIN_COMPLETE; - fcport->deleted = 0; - fcport->logout_on_delete = 1; qla2x00_set_fcport_state(fcport, FCS_ONLINE); qla2x00_iidma_fcport(vha, fcport); @@ -5140,7 +5129,6 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) qla24xx_update_fcport_fcp_prio(vha, fcport); -reg_port: switch (vha->host->active_mode) { case MODE_INITIATOR: qla2x00_reg_remote_port(vha, fcport); @@ -5159,6 +5147,23 @@ reg_port: default: break; } + + if (IS_IIDMA_CAPABLE(vha->hw) && vha->hw->flags.gpsc_supported) { + if (fcport->id_changed) { + fcport->id_changed = 0; + ql_dbg(ql_dbg_disc, vha, 0x20d7, + "%s %d %8phC post gfpnid fcp_cnt %d\n", + __func__, __LINE__, fcport->port_name, + vha->fcport_count); + qla24xx_post_gfpnid_work(vha, fcport); + } else { + ql_dbg(ql_dbg_disc, vha, 0x20d7, + "%s %d %8phC post gpsc fcp_cnt %d\n", + __func__, __LINE__, fcport->port_name, + vha->fcport_count); + qla24xx_post_gpsc_work(vha, fcport); + } + } } /* diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 15eaa6dded04..817c18a8e84d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5063,6 +5063,10 @@ qla2x00_do_work(struct scsi_qla_host *vha) break; case QLA_EVT_SP_RETRY: qla_sp_retry(vha, e); + break; + case QLA_EVT_IIDMA: + qla_do_iidma_work(vha, e->u.fcport.fcport); + break; } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 025dc2d3f3de..b85c833099ff 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; @@ -1930,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 */ @@ -1961,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; } @@ -3556,13 +3627,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) @@ -4057,9 +4121,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); @@ -4335,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) { @@ -4355,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; } @@ -4841,7 +4915,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: @@ -5113,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: @@ -5147,10 +5218,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); @@ -5189,6 +5265,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) diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 728ce74358e7..fecf96f0225c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -682,7 +682,7 @@ struct qla_tgt_cmd; * target module (tcm_qla2xxx). */ struct qla_tgt_func_tmpl { - + struct qla_tgt_cmd *(*find_cmd_by_tag)(struct fc_port *, uint64_t); int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, unsigned char *, uint32_t, int, int, int); void (*handle_data)(struct qla_tgt_cmd *); @@ -966,6 +966,8 @@ struct qla_tgt_mgmt_cmd { unsigned int flags; uint32_t reset_count; #define QLA24XX_MGMT_SEND_NACK 1 + struct work_struct work; + uint64_t unpacked_lun; union { struct atio_from_isp atio; struct imm_ntfy_from_isp imm_ntfy; diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 0c55d7057280..1ad7582220c3 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.06-k" +#define QLA2XXX_VERSION "10.00.00.07-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 0 diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index aadfeaac3898..0c2e82af9c0a 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -48,7 +48,6 @@ #include "tcm_qla2xxx.h" static struct workqueue_struct *tcm_qla2xxx_free_wq; -static struct workqueue_struct *tcm_qla2xxx_cmd_wq; /* * Parse WWN. @@ -630,6 +629,32 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, transl_tmr_func, GFP_ATOMIC, tag, flags); } +static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess, + uint64_t tag) +{ + struct qla_tgt_cmd *cmd = NULL; + struct se_cmd *secmd; + unsigned long flags; + + if (!sess->se_sess) + return NULL; + + spin_lock_irqsave(&sess->se_sess->sess_cmd_lock, flags); + list_for_each_entry(secmd, &sess->se_sess->sess_cmd_list, se_cmd_list) { + /* skip task management functions, including tmr->task_cmd */ + if (secmd->se_cmd_flags & SCF_SCSI_TMR_CDB) + continue; + + if (secmd->tag == tag) { + cmd = container_of(secmd, struct qla_tgt_cmd, se_cmd); + break; + } + } + spin_unlock_irqrestore(&sess->se_sess->sess_cmd_lock, flags); + + return cmd; +} + static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, @@ -1608,6 +1633,7 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id, * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. */ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { + .find_cmd_by_tag = tcm_qla2xxx_find_cmd_by_tag, .handle_cmd = tcm_qla2xxx_handle_cmd, .handle_data = tcm_qla2xxx_handle_data, .handle_tmr = tcm_qla2xxx_handle_tmr, @@ -1976,16 +2002,8 @@ static int tcm_qla2xxx_register_configfs(void) goto out_fabric_npiv; } - tcm_qla2xxx_cmd_wq = alloc_workqueue("tcm_qla2xxx_cmd", 0, 0); - if (!tcm_qla2xxx_cmd_wq) { - ret = -ENOMEM; - goto out_free_wq; - } - return 0; -out_free_wq: - destroy_workqueue(tcm_qla2xxx_free_wq); out_fabric_npiv: target_unregister_template(&tcm_qla2xxx_npiv_ops); out_fabric: @@ -1995,7 +2013,6 @@ out_fabric: static void tcm_qla2xxx_deregister_configfs(void) { - destroy_workqueue(tcm_qla2xxx_cmd_wq); destroy_workqueue(tcm_qla2xxx_free_wq); target_unregister_template(&tcm_qla2xxx_ops); |