X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_target.c;h=0e8cdaa03ee4c0676accb3afefc6aa8ddbbadce9;hb=22d84726e3b82458dee015c56c88dae8c861436e;hp=0e03ca2ab3e52358c817cdd2cdc667ba2bfb1ba3;hpb=aa2a4b6569d5b10491b606a86e574dff3852597a;p=karo-tx-linux.git diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e03ca2ab3e5..0e8cdaa03ee4 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -59,13 +59,20 @@ MODULE_PARM_DESC(qlini_mode, "when ready " "\"enabled\" (default) - initiator mode will always stay enabled."); -static int ql_dm_tgt_ex_pct = 50; +static int ql_dm_tgt_ex_pct = 0; module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql_dm_tgt_ex_pct, "For Dual Mode (qlini_mode=dual), this parameter determines " "the percentage of exchanges/cmds FW will allocate resources " "for Target mode."); +int ql2xuctrlirq = 1; +module_param(ql2xuctrlirq, int, 0644); +MODULE_PARM_DESC(ql2xuctrlirq, + "User to control IRQ placement via smp_affinity." + "Valid with qlini_mode=disabled." + "1(default): enable"); + int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; static int temp_sam_status = SAM_STAT_BUSY; @@ -110,18 +117,17 @@ enum fcp_resp_rsp_codes { /* Predefs for callbacks handed to qla2xxx LLD */ static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha, struct atio_from_isp *pkt, uint8_t); -static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); +static void qlt_response_pkt(struct scsi_qla_host *ha, struct rsp_que *rsp, + response_t *pkt); static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, int fn, void *iocb, int flags); -static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd +static void qlt_send_term_exchange(struct qla_qpair *, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort); -static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd); static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct atio_from_isp *atio, uint16_t status, int qfull); static void qlt_disable_vha(struct scsi_qla_host *vha); static void qlt_clear_tgt_db(struct qla_tgt *tgt); -static void qlt_send_notify_ack(struct scsi_qla_host *vha, +static void qlt_send_notify_ack(struct qla_qpair *qpair, struct imm_ntfy_from_isp *ntfy, uint32_t add_flags, uint16_t resp_code, int resp_code_valid, uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan); @@ -132,6 +138,8 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha, void qlt_unreg_sess(struct fc_port *sess); static void qlt_24xx_handle_abts(struct scsi_qla_host *, struct abts_recv_from_24xx *); +static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *, + uint16_t); /* * Global Variables @@ -200,8 +208,8 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, host = btree_lookup32(&vha->hw->tgt.host_map, key); if (!host) - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, - "Unable to find host %06x\n", key); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, + "Unable to find host %06x\n", key); return host; } @@ -245,26 +253,22 @@ static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha) static void qlt_queue_unknown_atio(scsi_qla_host_t *vha, - struct atio_from_isp *atio, uint8_t ha_locked) + struct atio_from_isp *atio, uint8_t ha_locked) { struct qla_tgt_sess_op *u; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; unsigned long flags; if (tgt->tgt_stop) { - ql_dbg(ql_dbg_async, vha, 0xffff, - "qla_target(%d): dropping unknown ATIO_TYPE7, " - "because tgt is being stopped", vha->vp_idx); + ql_dbg(ql_dbg_async, vha, 0x502c, + "qla_target(%d): dropping unknown ATIO_TYPE7, because tgt is being stopped", + vha->vp_idx); goto out_term; } u = kzalloc(sizeof(*u), GFP_ATOMIC); - if (u == NULL) { - ql_dbg(ql_dbg_async, vha, 0xffff, - "Alloc of struct unknown_atio (size %zd) failed", sizeof(*u)); - /* It should be harmless and on the next retry should work well */ + if (u == NULL) goto out_term; - } u->vha = vha; memcpy(&u->atio, atio, sizeof(*atio)); @@ -280,7 +284,7 @@ out: return; out_term: - qlt_send_term_exchange(vha, NULL, atio, ha_locked, 0); + qlt_send_term_exchange(vha->hw->base_qpair, NULL, atio, ha_locked, 0); goto out; } @@ -295,29 +299,28 @@ static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha, list_for_each_entry_safe(u, t, &vha->unknown_atio_list, cmd_list) { if (u->aborted) { - ql_dbg(ql_dbg_async, vha, 0xffff, - "Freeing unknown %s %p, because of Abort", + ql_dbg(ql_dbg_async, vha, 0x502e, + "Freeing unknown %s %p, because of Abort\n", "ATIO_TYPE7", u); - qlt_send_term_exchange(vha, NULL, &u->atio, - ha_locked, 0); + qlt_send_term_exchange(vha->hw->base_qpair, NULL, + &u->atio, ha_locked, 0); goto abort; } host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id); if (host != NULL) { - ql_dbg(ql_dbg_async, vha, 0xffff, - "Requeuing unknown ATIO_TYPE7 %p", u); + ql_dbg(ql_dbg_async, vha, 0x502f, + "Requeuing unknown ATIO_TYPE7 %p\n", u); qlt_24xx_atio_pkt(host, &u->atio, ha_locked); } else if (tgt->tgt_stop) { - ql_dbg(ql_dbg_async, vha, 0xffff, - "Freeing unknown %s %p, because tgt is being stopped", - "ATIO_TYPE7", u); - qlt_send_term_exchange(vha, NULL, &u->atio, - ha_locked, 0); + ql_dbg(ql_dbg_async, vha, 0x503a, + "Freeing unknown %s %p, because tgt is being stopped\n", + "ATIO_TYPE7", u); + qlt_send_term_exchange(vha->hw->base_qpair, NULL, + &u->atio, ha_locked, 0); } else { - ql_dbg(ql_dbg_async, vha, 0xffff, - "u %p, vha %p, host %p, sched again..", u, - vha, host); + ql_dbg(ql_dbg_async, vha, 0x503d, + "Reschedule u %p, vha %p, host %p\n", u, vha, host); if (!queued) { queued = 1; schedule_delayed_work(&vha->unknown_atio_work, @@ -380,6 +383,8 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, struct imm_ntfy_from_isp *entry = (struct imm_ntfy_from_isp *)atio; + qlt_issue_marker(vha, ha_locked); + if ((entry->u.isp24.vp_index != 0xFF) && (entry->u.isp24.nport_handle != 0xFFFF)) { host = qlt_find_host_by_vp_idx(vha, @@ -411,7 +416,7 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, unsigned long flags; if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xffff, + ql_dbg(ql_dbg_tgt, vha, 0xe00a, "qla_target(%d): Response pkt (ABTS_RECV_24XX) " "received, with unknown vp_index %d\n", vha->vp_idx, entry->vp_index); @@ -437,7 +442,8 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, return false; } -void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) +void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, + struct rsp_que *rsp, response_t *pkt) { switch (pkt->entry_type) { case CTIO_CRC2: @@ -456,7 +462,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) vha->vp_idx, entry->vp_index); break; } - qlt_response_pkt(host, pkt); + qlt_response_pkt(host, rsp, pkt); break; } @@ -474,7 +480,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) vha->vp_idx, entry->u.isp24.vp_index); break; } - qlt_response_pkt(host, pkt); + qlt_response_pkt(host, rsp, pkt); break; } @@ -496,7 +502,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) break; } } - qlt_response_pkt(host, pkt); + qlt_response_pkt(host, rsp, pkt); break; } @@ -513,7 +519,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) "vp_index %d\n", vha->vp_idx, entry->vp_index); break; } - qlt_response_pkt(host, pkt); + qlt_response_pkt(host, rsp, pkt); break; } @@ -530,12 +536,12 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) "vp_index %d\n", vha->vp_idx, entry->vp_index); break; } - qlt_response_pkt(host, pkt); + qlt_response_pkt(host, rsp, pkt); break; } default: - qlt_response_pkt(vha, pkt); + qlt_response_pkt(vha, rsp, pkt); break; } @@ -565,13 +571,13 @@ void qla2x00_async_nack_sp_done(void *s, int res) struct scsi_qla_host *vha = sp->vha; unsigned long flags; - ql_dbg(ql_dbg_disc, vha, 0xffff, - "Async done-%s res %x %8phC type %d\n", - sp->name, res, sp->fcport->port_name, sp->type); + ql_dbg(ql_dbg_disc, vha, 0x20f2, + "Async done-%s res %x %8phC type %d\n", + sp->name, res, sp->fcport->port_name, sp->type); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); sp->fcport->flags &= ~FCF_ASYNC_SENT; - sp->fcport->chip_reset = vha->hw->chip_reset; + sp->fcport->chip_reset = vha->hw->base_qpair->chip_reset; switch (sp->type) { case SRB_NACK_PLOGI: @@ -593,19 +599,19 @@ void qla2x00_async_nack_sp_done(void *s, int res) if (!IS_IIDMA_CAPABLE(vha->hw) || !vha->hw->flags.gpsc_supported) { - ql_dbg(ql_dbg_disc, vha, 0xffff, - "%s %d %8phC post upd_fcport fcp_cnt %d\n", - __func__, __LINE__, - sp->fcport->port_name, - vha->fcport_count); + 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); qla24xx_post_upd_fcport_work(vha, sp->fcport); } else { - ql_dbg(ql_dbg_disc, vha, 0xffff, - "%s %d %8phC post gpsc fcp_cnt %d\n", - __func__, __LINE__, - sp->fcport->port_name, - vha->fcport_count); + 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); } @@ -664,9 +670,9 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport, if (rval != QLA_SUCCESS) goto done_free_sp; - ql_dbg(ql_dbg_disc, vha, 0xffff, - "Async-%s %8phC hndl %x %s\n", - sp->name, fcport->port_name, sp->handle, c); + ql_dbg(ql_dbg_disc, vha, 0x20f4, + "Async-%s %8phC hndl %x %s\n", + sp->name, fcport->port_name, sp->handle, c); return rval; @@ -688,7 +694,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e) t = qlt_create_sess(vha, e->u.nack.fcport, 0); mutex_unlock(&vha->vha_tgt.tgt_mutex); if (t) { - ql_log(ql_log_info, vha, 0xffff, + ql_log(ql_log_info, vha, 0xd034, "%s create sess success %p", __func__, t); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); /* create sess has an extra kref */ @@ -757,7 +763,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) } if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x2107, "%s: kref_get fail sess %8phC \n", __func__, sess->port_name); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); @@ -1026,7 +1032,7 @@ static void qlt_free_session_done(struct work_struct *work) sess->login_succ = 0; } - if (sess->chip_reset != sess->vha->hw->chip_reset) + if (sess->chip_reset != ha->base_qpair->chip_reset) qla2x00_clear_loop_id(sess); if (sess->conflict) { @@ -1098,7 +1104,7 @@ void qlt_unreg_sess(struct fc_port *sess) { struct scsi_qla_host *vha = sess->vha; - ql_dbg(ql_dbg_disc, sess->vha, 0xffff, + ql_dbg(ql_dbg_disc, sess->vha, 0x210a, "%s sess %p for deletion %8phC\n", __func__, sess, sess->port_name); @@ -1156,7 +1162,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) static void qla24xx_chk_fcp_state(struct fc_port *sess) { - if (sess->chip_reset != sess->vha->hw->chip_reset) { + if (sess->chip_reset != sess->vha->hw->base_qpair->chip_reset) { sess->logout_on_delete = 0; sess->logo_ack_needed = 0; sess->fw_login_state = DSC_LS_PORT_UNAVAIL; @@ -1288,7 +1294,7 @@ static struct fc_port *qlt_create_sess( if (fcport->se_sess) { if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20f6, "%s: kref_get_unless_zero failed for %8phC\n", __func__, sess->port_name); return NULL; @@ -1310,7 +1316,7 @@ static struct fc_port *qlt_create_sess( if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, &fcport->port_name[0], sess) < 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf015, "(%d) %8phC check_initiator_node_acl failed\n", vha->vp_idx, fcport->port_name); return NULL; @@ -1321,7 +1327,7 @@ static struct fc_port *qlt_create_sess( * fc_port access across ->tgt.sess_lock reaquire. */ if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20f7, "%s: kref_get_unless_zero failed for %8phC\n", __func__, sess->port_name); return NULL; @@ -1432,6 +1438,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt) if (npiv_vports) { mutex_unlock(&qla_tgt_mutex); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf021, + "NPIV is in use. Can not stop target\n"); return -EPERM; } } @@ -1442,7 +1450,7 @@ int qlt_stop_phase1(struct qla_tgt *tgt) return -EPERM; } - ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n", + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe003, "Stopping target for host %ld(%p)\n", vha->host_no, vha); /* * Mutex needed to sync with qla_tgt_fc_port_[added,deleted]. @@ -1485,9 +1493,7 @@ EXPORT_SYMBOL(qlt_stop_phase1); /* Called by tcm_qla2xxx configfs code */ void qlt_stop_phase2(struct qla_tgt *tgt) { - struct qla_hw_data *ha = tgt->ha; - scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); - unsigned long flags; + scsi_qla_host_t *vha = tgt->vha; if (tgt->tgt_stopped) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04f, @@ -1495,24 +1501,19 @@ void qlt_stop_phase2(struct qla_tgt *tgt) dump_stack(); return; } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b, - "Waiting for %d IRQ commands to complete (tgt %p)", - tgt->irq_cmd_count, tgt); + if (!tgt->tgt_stop) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b, + "%s: phase1 stop is not completed\n", __func__); + dump_stack(); + return; + } mutex_lock(&vha->vha_tgt.tgt_mutex); - spin_lock_irqsave(&ha->hardware_lock, flags); - while ((tgt->irq_cmd_count != 0) || (tgt->atio_irq_cmd_count != 0)) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - udelay(2); - spin_lock_irqsave(&ha->hardware_lock, flags); - } tgt->tgt_stop = 0; tgt->tgt_stopped = 1; - spin_unlock_irqrestore(&ha->hardware_lock, flags); mutex_unlock(&vha->vha_tgt.tgt_mutex); - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished", + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished\n", tgt); } EXPORT_SYMBOL(qlt_stop_phase2); @@ -1521,10 +1522,36 @@ EXPORT_SYMBOL(qlt_stop_phase2); static void qlt_release(struct qla_tgt *tgt) { scsi_qla_host_t *vha = tgt->vha; + void *node; + u64 key = 0; + u16 i; + struct qla_qpair_hint *h; + + if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stop && + !tgt->tgt_stopped) + qlt_stop_phase1(tgt); if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped) qlt_stop_phase2(tgt); + for (i = 0; i < vha->hw->max_qpairs + 1; i++) { + unsigned long flags; + + h = &tgt->qphints[i]; + if (h->qpair) { + spin_lock_irqsave(h->qpair->qp_lock_ptr, flags); + list_del(&h->hint_elem); + spin_unlock_irqrestore(h->qpair->qp_lock_ptr, flags); + h->qpair = NULL; + } + } + kfree(tgt->qphints); + + btree_for_each_safe64(&tgt->lun_qpair_map, key, node) + btree_remove64(&tgt->lun_qpair_map, key); + + btree_destroy64(&tgt->lun_qpair_map); + vha->vha_tgt.qla_tgt = NULL; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00d, @@ -1568,11 +1595,12 @@ static int qlt_sched_sess_work(struct qla_tgt *tgt, int type, /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static void qlt_send_notify_ack(struct scsi_qla_host *vha, +static void qlt_send_notify_ack(struct qla_qpair *qpair, struct imm_ntfy_from_isp *ntfy, uint32_t add_flags, uint16_t resp_code, int resp_code_valid, uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan) { + struct scsi_qla_host *vha = qpair->vha; struct qla_hw_data *ha = vha->hw; request_t *pkt; struct nack_to_isp *nack; @@ -1582,11 +1610,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha); - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - - pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); + pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL); if (!pkt) { ql_dbg(ql_dbg_tgt, vha, 0xe049, "qla_target(%d): %s failed: unable to allocate " @@ -1627,16 +1651,17 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); + qla2x00_start_iocbs(vha, qpair->req); } /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, +static void qlt_24xx_send_abts_resp(struct qla_qpair *qpair, struct abts_recv_from_24xx *abts, uint32_t status, bool ids_reversed) { + struct scsi_qla_host *vha = qpair->vha; struct qla_hw_data *ha = vha->hw; struct abts_resp_to_24xx *resp; uint32_t f_ctl; @@ -1646,11 +1671,8 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, "Sending task mgmt ABTS response (ha=%p, atio=%p, status=%x\n", ha, abts, status); - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - - resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL); + resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(qpair, + NULL); if (!resp) { ql_dbg(ql_dbg_tgt, vha, 0xe04a, "qla_target(%d): %s failed: unable to allocate " @@ -1706,7 +1728,10 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); } /* @@ -1719,11 +1744,9 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt, vha, 0xe007, "Sending retry TERM EXCH CTIO7 (ha=%p)\n", vha->hw); - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL); + ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready( + vha->hw->base_qpair, NULL); if (ctio == NULL) { ql_dbg(ql_dbg_tgt, vha, 0xe04b, "qla_target(%d): %s failed: unable to allocate " @@ -1754,7 +1777,8 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, wmb(); qla2x00_start_iocbs(vha, vha->req); - qlt_24xx_send_abts_resp(vha, (struct abts_recv_from_24xx *)entry, + qlt_24xx_send_abts_resp(vha->hw->base_qpair, + (struct abts_recv_from_24xx *)entry, FCP_TMF_CMPL, true); } @@ -1762,13 +1786,13 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) { struct qla_tgt_sess_op *op; struct qla_tgt_cmd *cmd; + unsigned long flags; - spin_lock(&vha->cmd_list_lock); - + spin_lock_irqsave(&vha->cmd_list_lock, flags); list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { if (tag == op->atio.u.isp24.exchange_addr) { op->aborted = true; - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); return 1; } } @@ -1776,7 +1800,7 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) { if (tag == op->atio.u.isp24.exchange_addr) { op->aborted = true; - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); return 1; } } @@ -1784,12 +1808,12 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { if (tag == cmd->atio.u.isp24.exchange_addr) { cmd->aborted = 1; - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); return 1; } } + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); - spin_unlock(&vha->cmd_list_lock); return 0; } @@ -1799,17 +1823,18 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) * for the same lun) */ static void abort_cmds_for_lun(struct scsi_qla_host *vha, - uint32_t lun, uint8_t *s_id) + u64 lun, uint8_t *s_id) { struct qla_tgt_sess_op *op; struct qla_tgt_cmd *cmd; uint32_t key; + unsigned long flags; key = sid_to_key(s_id); - spin_lock(&vha->cmd_list_lock); + spin_lock_irqsave(&vha->cmd_list_lock, flags); list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { uint32_t op_key; - uint32_t op_lun; + u64 op_lun; op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); op_lun = scsilun_to_int( @@ -1831,7 +1856,7 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha, list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { uint32_t cmd_key; - uint32_t cmd_lun; + u64 cmd_lun; cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); cmd_lun = scsilun_to_int( @@ -1839,7 +1864,7 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha, if (cmd_key == key && cmd_lun == lun) cmd->aborted = 1; } - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); } /* ha->hardware_lock supposed to be held on entry */ @@ -1849,18 +1874,15 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct qla_hw_data *ha = vha->hw; struct se_session *se_sess = sess->se_sess; struct qla_tgt_mgmt_cmd *mcmd; + struct qla_tgt_cmd *cmd; struct se_cmd *se_cmd; - u32 lun = 0; int rc; bool found_lun = false; unsigned long flags; spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { - struct qla_tgt_cmd *cmd = - container_of(se_cmd, struct qla_tgt_cmd, se_cmd); if (se_cmd->tag == abts->exchange_addr_to_abort) { - lun = cmd->unpacked_lun; found_lun = true; break; } @@ -1871,7 +1893,8 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, if (!found_lun) { if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) { /* send TASK_ABORT response immediately */ - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, + FCP_TMF_CMPL, false); return 0; } else { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081, @@ -1894,12 +1917,14 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, } memset(mcmd, 0, sizeof(*mcmd)); + cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); mcmd->sess = sess; memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); - mcmd->reset_count = vha->hw->chip_reset; + mcmd->reset_count = ha->base_qpair->chip_reset; mcmd->tmr_func = QLA_TGT_ABTS; + mcmd->qpair = ha->base_qpair; - rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func, + rc = ha->tgt.tgt_ops->handle_tmr(mcmd, cmd->unpacked_lun, mcmd->tmr_func, abts->exchange_addr_to_abort); if (rc != 0) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, @@ -1929,7 +1954,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053, "qla_target(%d): ABTS: Abort Sequence not " "supported\n", vha->vp_idx); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED, + false); return; } @@ -1937,7 +1963,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf010, "qla_target(%d): ABTS: Unknown Exchange " "Address received\n", vha->vp_idx); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED, + false); return; } @@ -1963,8 +1990,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); if (rc != 0) { - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, - false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, + FCP_TMF_REJECTED, false); } return; } @@ -1972,7 +1999,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, if (sess->deleted) { - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED, + false); return; } @@ -1981,7 +2009,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, "qla_target(%d): __qlt_24xx_handle_abts() failed: %d\n", vha->vp_idx, rc); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); + qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED, + false); return; } } @@ -1989,9 +2018,10 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, +static void qlt_24xx_send_task_mgmt_ctio(struct qla_qpair *qpair, struct qla_tgt_mgmt_cmd *mcmd, uint32_t resp_code) { + struct scsi_qla_host *ha = qpair->vha; struct atio_from_isp *atio = &mcmd->orig_iocb.atio; struct ctio7_to_24xx *ctio; uint16_t temp; @@ -2000,11 +2030,8 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, "Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n", ha, atio, resp_code); - /* Send marker if required */ - if (qlt_issue_marker(ha, 1) != QLA_SUCCESS) - return; - ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(ha, NULL); + ctio = (struct ctio7_to_24xx *)__qla2x00_alloc_iocbs(qpair, NULL); if (ctio == NULL) { ql_dbg(ql_dbg_tgt, ha, 0xe04c, "qla_target(%d): %s failed: unable to allocate " @@ -2022,8 +2049,9 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio->exchange_addr = atio->u.isp24.exchange_addr; - ctio->u.status1.flags = (atio->u.isp24.attr << 9) | - cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS); + temp = (atio->u.isp24.attr << 9)| + CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS; + ctio->u.status1.flags = cpu_to_le16(temp); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio->u.status1.ox_id = cpu_to_le16(temp); ctio->u.status1.scsi_status = @@ -2033,7 +2061,10 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(ha, ha->req); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(ha, qpair->req); } void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) @@ -2046,12 +2077,13 @@ EXPORT_SYMBOL(qlt_free_mcmd); * ha->hardware_lock supposed to be held on entry. Might drop it, then * reacquire */ -void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, +void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq) { struct atio_from_isp *atio = &cmd->atio; struct ctio7_to_24xx *ctio; uint16_t temp; + struct scsi_qla_host *vha = cmd->vha; ql_dbg(ql_dbg_tgt_dif, vha, 0x3066, "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, " @@ -2076,8 +2108,9 @@ void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio->exchange_addr = atio->u.isp24.exchange_addr; - ctio->u.status1.flags = (atio->u.isp24.attr << 9) | - cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS); + temp = (atio->u.isp24.attr << 9) | + CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS; + ctio->u.status1.flags = cpu_to_le16(temp); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio->u.status1.ox_id = cpu_to_le16(temp); ctio->u.status1.scsi_status = @@ -2101,7 +2134,11 @@ void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); + out: return; } @@ -2112,14 +2149,15 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) struct scsi_qla_host *vha = mcmd->sess->vha; struct qla_hw_data *ha = vha->hw; unsigned long flags; + struct qla_qpair *qpair = mcmd->qpair; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf013, "TM response mcmd (%p) status %#x state %#x", mcmd, mcmd->fc_tm_rsp, mcmd->flags); - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (!vha->flags.online || mcmd->reset_count != ha->chip_reset) { + if (!vha->flags.online || mcmd->reset_count != qpair->chip_reset) { /* * Either the port is not online or this request was from * previous life, just abort the processing. @@ -2127,9 +2165,9 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) ql_dbg(ql_dbg_async, vha, 0xe100, "RESET-TMR online/active/old-count/new-count = %d/%d/%d/%d.\n", vha->flags.online, qla2x00_reset_active(vha), - mcmd->reset_count, ha->chip_reset); + mcmd->reset_count, qpair->chip_reset); ha->tgt.tgt_ops->free_mcmd(mcmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return; } @@ -2140,21 +2178,21 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) ELS_PRLO || mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode == ELS_TPRLO) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x2106, "TM response logo %phC status %#x state %#x", mcmd->sess->port_name, mcmd->fc_tm_rsp, mcmd->flags); qlt_schedule_sess_for_deletion_lock(mcmd->sess); } else { - qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, - 0, 0, 0, 0, 0, 0); + qlt_send_notify_ack(vha->hw->base_qpair, + &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0); } } else { if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX) - qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts, + qlt_24xx_send_abts_resp(qpair, &mcmd->orig_iocb.abts, mcmd->fc_tm_rsp, false); else - qlt_24xx_send_task_mgmt_ctio(vha, mcmd, + qlt_24xx_send_task_mgmt_ctio(qpair, mcmd, mcmd->fc_tm_rsp); } /* @@ -2166,7 +2204,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) * qlt_xmit_tm_rsp() returns here.. */ ha->tgt.tgt_ops->free_mcmd(mcmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); } EXPORT_SYMBOL(qlt_xmit_tm_rsp); @@ -2178,7 +2216,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm) BUG_ON(cmd->sg_cnt == 0); prm->sg = (struct scatterlist *)cmd->sg; - prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, cmd->sg, + prm->seg_cnt = pci_map_sg(cmd->qpair->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); if (unlikely(prm->seg_cnt == 0)) goto out_err; @@ -2205,7 +2243,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm) if (cmd->prot_sg_cnt) { prm->prot_sg = cmd->prot_sg; - prm->prot_seg_cnt = pci_map_sg(prm->tgt->ha->pdev, + prm->prot_seg_cnt = pci_map_sg(cmd->qpair->pdev, cmd->prot_sg, cmd->prot_sg_cnt, cmd->dma_data_direction); if (unlikely(prm->prot_seg_cnt == 0)) @@ -2225,7 +2263,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm) return 0; out_err: - ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe04d, + ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe04d, "qla_target(%d): PCI mapping failed: sg_cnt=%d", 0, prm->cmd->sg_cnt); return -1; @@ -2233,51 +2271,50 @@ out_err: static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) { - struct qla_hw_data *ha = vha->hw; - + struct qla_hw_data *ha; + struct qla_qpair *qpair; if (!cmd->sg_mapped) return; - pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); + qpair = cmd->qpair; + + pci_unmap_sg(qpair->pdev, cmd->sg, cmd->sg_cnt, + cmd->dma_data_direction); cmd->sg_mapped = 0; if (cmd->prot_sg_cnt) - pci_unmap_sg(ha->pdev, cmd->prot_sg, cmd->prot_sg_cnt, + pci_unmap_sg(qpair->pdev, cmd->prot_sg, cmd->prot_sg_cnt, cmd->dma_data_direction); + if (!cmd->ctx) + return; + ha = vha->hw; if (cmd->ctx_dsd_alloced) - qla2x00_clean_dsd_pool(ha, NULL, cmd); + qla2x00_clean_dsd_pool(ha, cmd->ctx); - if (cmd->ctx) - dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma); + dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma); } -static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, +static int qlt_check_reserve_free_req(struct qla_qpair *qpair, uint32_t req_cnt) { - uint32_t cnt, cnt_in; + uint32_t cnt; + struct req_que *req = qpair->req; - if (vha->req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD(vha->req->req_q_out); - cnt_in = (uint16_t)RD_REG_DWORD(vha->req->req_q_in); + if (req->cnt < (req_cnt + 2)) { + cnt = (uint16_t)(qpair->use_shadow_reg ? *req->out_ptr : + RD_REG_DWORD_RELAXED(req->req_q_out)); - if (vha->req->ring_index < cnt) - vha->req->cnt = cnt - vha->req->ring_index; + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; else - vha->req->cnt = vha->req->length - - (vha->req->ring_index - cnt); - - if (unlikely(vha->req->cnt < (req_cnt + 2))) { - ql_dbg(ql_dbg_io, vha, 0x305a, - "qla_target(%d): There is no room in the request ring: vha->req->ring_index=%d, vha->req->cnt=%d, req_cnt=%d Req-out=%d Req-in=%d Req-Length=%d\n", - vha->vp_idx, vha->req->ring_index, - vha->req->cnt, req_cnt, cnt, cnt_in, - vha->req->length); + req->cnt = req->length - (req->ring_index - cnt); + + if (unlikely(req->cnt < (req_cnt + 2))) return -EAGAIN; - } } - vha->req->cnt -= req_cnt; + req->cnt -= req_cnt; return 0; } @@ -2285,67 +2322,73 @@ static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static inline void *qlt_get_req_pkt(struct scsi_qla_host *vha) +static inline void *qlt_get_req_pkt(struct req_que *req) { /* Adjust ring index. */ - vha->req->ring_index++; - if (vha->req->ring_index == vha->req->length) { - vha->req->ring_index = 0; - vha->req->ring_ptr = vha->req->ring; + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; } else { - vha->req->ring_ptr++; + req->ring_ptr++; } - return (cont_entry_t *)vha->req->ring_ptr; + return (cont_entry_t *)req->ring_ptr; } /* ha->hardware_lock supposed to be held on entry */ -static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha) +static inline uint32_t qlt_make_handle(struct qla_qpair *qpair) { - struct qla_hw_data *ha = vha->hw; uint32_t h; + int index; + uint8_t found = 0; + struct req_que *req = qpair->req; + + h = req->current_outstanding_cmd; + + for (index = 1; index < req->num_outstanding_cmds; index++) { + h++; + if (h == req->num_outstanding_cmds) + h = 1; - h = ha->tgt.current_handle; - /* always increment cmd handle */ - do { - ++h; - if (h > DEFAULT_OUTSTANDING_COMMANDS) - h = 1; /* 0 is QLA_TGT_NULL_HANDLE */ - if (h == ha->tgt.current_handle) { - ql_dbg(ql_dbg_io, vha, 0x305b, - "qla_target(%d): Ran out of " - "empty cmd slots in ha %p\n", vha->vp_idx, ha); - h = QLA_TGT_NULL_HANDLE; + if (h == QLA_TGT_SKIP_HANDLE) + continue; + + if (!req->outstanding_cmds[h]) { + found = 1; break; } - } while ((h == QLA_TGT_NULL_HANDLE) || - (h == QLA_TGT_SKIP_HANDLE) || - (ha->tgt.cmds[h-1] != NULL)); + } - if (h != QLA_TGT_NULL_HANDLE) - ha->tgt.current_handle = h; + if (found) { + req->current_outstanding_cmd = h; + } else { + ql_dbg(ql_dbg_io, qpair->vha, 0x305b, + "qla_target(%d): Ran out of empty cmd slots\n", + qpair->vha->vp_idx); + h = QLA_TGT_NULL_HANDLE; + } return h; } /* ha->hardware_lock supposed to be held on entry */ -static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, - struct scsi_qla_host *vha) +static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, + struct qla_tgt_prm *prm) { uint32_t h; struct ctio7_to_24xx *pkt; - struct qla_hw_data *ha = vha->hw; struct atio_from_isp *atio = &prm->cmd->atio; uint16_t temp; - pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr; + pkt = (struct ctio7_to_24xx *)qpair->req->ring_ptr; prm->pkt = pkt; memset(pkt, 0, sizeof(*pkt)); pkt->entry_type = CTIO_TYPE7; pkt->entry_count = (uint8_t)prm->req_cnt; - pkt->vp_index = vha->vp_idx; + pkt->vp_index = prm->cmd->vp_idx; - h = qlt_make_handle(vha); + h = qlt_make_handle(qpair); if (unlikely(h == QLA_TGT_NULL_HANDLE)) { /* * CTIO type 7 from the firmware doesn't provide a way to @@ -2354,16 +2397,18 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, */ return -EAGAIN; } else - ha->tgt.cmds[h - 1] = prm->cmd; + qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; - pkt->nport_handle = prm->cmd->loop_id; + pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; + pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; pkt->exchange_addr = atio->u.isp24.exchange_addr; - pkt->u.status0.flags |= (atio->u.isp24.attr << 9); + temp = atio->u.isp24.attr << 9; + pkt->u.status0.flags |= cpu_to_le16(temp); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); pkt->u.status0.ox_id = cpu_to_le16(temp); pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset); @@ -2385,7 +2430,8 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm, /* Build continuation packets */ while (prm->seg_cnt > 0) { cont_a64_entry_t *cont_pkt64 = - (cont_a64_entry_t *)qlt_get_req_pkt(vha); + (cont_a64_entry_t *)qlt_get_req_pkt( + prm->cmd->qpair->req); /* * Make sure that from cont_pkt64 none of @@ -2496,35 +2542,35 @@ static void qlt_print_dif_err(struct qla_tgt_prm *prm) /* ASCQ */ switch (prm->sense_buffer[13]) { case 1: - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + ql_dbg(ql_dbg_tgt_dif, vha, 0xe00b, "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] " "se_cmd=%p tag[%x]", cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, cmd->atio.u.isp24.exchange_addr); break; case 2: - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + ql_dbg(ql_dbg_tgt_dif, vha, 0xe00c, "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] " "se_cmd=%p tag[%x]", cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, cmd->atio.u.isp24.exchange_addr); break; case 3: - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + ql_dbg(ql_dbg_tgt_dif, vha, 0xe00f, "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] " "se_cmd=%p tag[%x]", cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, cmd->atio.u.isp24.exchange_addr); break; default: - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + ql_dbg(ql_dbg_tgt_dif, vha, 0xe010, "BE detected Dif ERR: lba[%llx|%lld] len[%x] " "se_cmd=%p tag[%x]", cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, cmd->atio.u.isp24.exchange_addr); break; } - ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff, cmd->cdb, 16); + ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xe011, cmd->cdb, 16); } } @@ -2535,24 +2581,23 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, struct qla_tgt_prm *prm, int xmit_type, uint8_t scsi_status, uint32_t *full_req_cnt) { - struct qla_tgt *tgt = cmd->tgt; - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = vha->hw; struct se_cmd *se_cmd = &cmd->se_cmd; + struct qla_qpair *qpair = cmd->qpair; prm->cmd = cmd; - prm->tgt = tgt; + prm->tgt = cmd->tgt; + prm->pkt = NULL; prm->rq_result = scsi_status; prm->sense_buffer = &cmd->sense_buffer[0]; prm->sense_buffer_len = TRANSPORT_SENSE_BUFFER; prm->sg = NULL; prm->seg_cnt = -1; prm->req_cnt = 1; + prm->residual = 0; prm->add_status_pkt = 0; - - /* Send marker if required */ - if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) - return -EFAULT; + prm->prot_sg = NULL; + prm->prot_seg_cnt = 0; + prm->tot_dsds = 0; if ((xmit_type & QLA_TGT_XMIT_DATA) && qlt_has_data(cmd)) { if (qlt_pci_map_calc_cnt(prm) != 0) @@ -2563,7 +2608,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { prm->residual = se_cmd->residual_count; - ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c, + ql_dbg_qp(ql_dbg_io + ql_dbg_verbose, qpair, 0x305c, "Residual underflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n", prm->residual, se_cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, @@ -2571,7 +2616,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, prm->rq_result |= SS_RESIDUAL_UNDER; } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { prm->residual = se_cmd->residual_count; - ql_dbg(ql_dbg_io, vha, 0x305d, + ql_dbg_qp(ql_dbg_io, qpair, 0x305d, "Residual overflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n", prm->residual, se_cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, cmd->bufflen, prm->rq_result); @@ -2585,7 +2630,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, */ if (qlt_has_data(cmd)) { if (QLA_TGT_SENSE_VALID(prm->sense_buffer) || - (IS_FWI2_CAPABLE(ha) && + (IS_FWI2_CAPABLE(cmd->vha->hw) && (prm->rq_result != 0))) { prm->add_status_pkt = 1; (*full_req_cnt)++; @@ -2596,17 +2641,17 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, return 0; } -static inline int qlt_need_explicit_conf(struct qla_hw_data *ha, - struct qla_tgt_cmd *cmd, int sending_sense) +static inline int qlt_need_explicit_conf(struct qla_tgt_cmd *cmd, + int sending_sense) { - if (ha->tgt.enable_class_2) + if (cmd->qpair->enable_class_2) return 0; if (sending_sense) return cmd->conf_compl_supported; else - return ha->tgt.enable_explicit_conf && - cmd->conf_compl_supported; + return cmd->qpair->enable_explicit_conf && + cmd->conf_compl_supported; } static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, @@ -2615,7 +2660,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len, (uint32_t)sizeof(ctio->u.status1.sense_data)); ctio->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_SEND_STATUS); - if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) { + if (qlt_need_explicit_conf(prm->cmd, 0)) { ctio->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_EXPLICIT_CONFORM | CTIO7_FLAGS_CONFORM_REQ); @@ -2625,9 +2670,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, if (QLA_TGT_SENSE_VALID(prm->sense_buffer)) { int i; - if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) { + if (qlt_need_explicit_conf(prm->cmd, 1)) { if ((prm->rq_result & SS_SCSI_STATUS_BYTE) != 0) { - ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe017, + ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe017, "Skipping EXPLICIT_CONFORM and " "CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ " "non GOOD status\n"); @@ -2795,7 +2840,7 @@ qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx, } static inline int -qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) +qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) { uint32_t *cur_dsd; uint32_t transfer_length = 0; @@ -2814,16 +2859,17 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) struct atio_from_isp *atio = &prm->cmd->atio; struct qla_tc_param tc; uint16_t t16; + scsi_qla_host_t *vha = cmd->vha; ha = vha->hw; - pkt = (struct ctio_crc2_to_fw *)vha->req->ring_ptr; + pkt = (struct ctio_crc2_to_fw *)qpair->req->ring_ptr; prm->pkt = pkt; memset(pkt, 0, sizeof(*pkt)); - ql_dbg(ql_dbg_tgt, vha, 0xe071, + ql_dbg_qp(ql_dbg_tgt, cmd->qpair, 0xe071, "qla_target(%d):%s: se_cmd[%p] CRC2 prot_op[0x%x] cmd prot sg:cnt[%p:%x] lba[%llu]\n", - vha->vp_idx, __func__, se_cmd, se_cmd->prot_op, + cmd->vp_idx, __func__, se_cmd, se_cmd->prot_op, prm->prot_sg, prm->prot_seg_cnt, se_cmd->t_task_lba); if ((se_cmd->prot_op == TARGET_PROT_DIN_INSERT) || @@ -2886,9 +2932,9 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) /* Update entry type to indicate Command Type CRC_2 IOCB */ pkt->entry_type = CTIO_CRC2; pkt->entry_count = 1; - pkt->vp_index = vha->vp_idx; + pkt->vp_index = cmd->vp_idx; - h = qlt_make_handle(vha); + h = qlt_make_handle(qpair); if (unlikely(h == QLA_TGT_NULL_HANDLE)) { /* * CTIO type 7 from the firmware doesn't provide a way to @@ -2897,9 +2943,10 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) */ return -EAGAIN; } else - ha->tgt.cmds[h-1] = prm->cmd; + qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; + pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; @@ -3003,7 +3050,7 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) crc_queuing_error: /* Cleanup will be performed by the caller */ - vha->hw->tgt.cmds[h - 1] = NULL; + qpair->req->outstanding_cmds[h] = NULL; return QLA_FUNCTION_FAILED; } @@ -3016,33 +3063,28 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, uint8_t scsi_status) { struct scsi_qla_host *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; + struct qla_qpair *qpair = cmd->qpair; struct ctio7_to_24xx *pkt; struct qla_tgt_prm prm; uint32_t full_req_cnt = 0; unsigned long flags = 0; int res; - spin_lock_irqsave(&ha->hardware_lock, flags); if (cmd->sess && cmd->sess->deleted) { cmd->state = QLA_TGT_STATE_PROCESSED; if (cmd->sess->logout_completed) /* no need to terminate. FW already freed exchange. */ qlt_abort_cmd_on_host_reset(cmd->vha, cmd); else - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + qlt_send_term_exchange(qpair, cmd, &cmd->atio, 0, 0); return 0; } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - memset(&prm, 0, sizeof(prm)); - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe018, - "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p]\n", + ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018, + "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p] qp %d\n", (xmit_type & QLA_TGT_XMIT_STATUS) ? 1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction, - &cmd->se_cmd); + &cmd->se_cmd, qpair->id); res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, &full_req_cnt); @@ -3050,39 +3092,39 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, return res; } - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); if (xmit_type == QLA_TGT_XMIT_STATUS) vha->tgt_counters.core_qla_snd_status++; else vha->tgt_counters.core_qla_que_buf++; - if (!ha->flags.fw_started || cmd->reset_count != ha->chip_reset) { + if (!qpair->fw_started || cmd->reset_count != qpair->chip_reset) { /* * Either the port is not online or this request was from * previous life, just abort the processing. */ cmd->state = QLA_TGT_STATE_PROCESSED; qlt_abort_cmd_on_host_reset(cmd->vha, cmd); - ql_dbg(ql_dbg_async, vha, 0xe101, + ql_dbg_qp(ql_dbg_async, qpair, 0xe101, "RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n", vha->flags.online, qla2x00_reset_active(vha), - cmd->reset_count, ha->chip_reset); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + cmd->reset_count, qpair->chip_reset); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return 0; } /* Does F/W have an IOCBs for this request */ - res = qlt_check_reserve_free_req(vha, full_req_cnt); + res = qlt_check_reserve_free_req(qpair, full_req_cnt); if (unlikely(res)) goto out_unmap_unlock; if (cmd->se_cmd.prot_op && (xmit_type & QLA_TGT_XMIT_DATA)) - res = qlt_build_ctio_crc2_pkt(&prm, vha); + res = qlt_build_ctio_crc2_pkt(qpair, &prm); else - res = qlt_24xx_build_ctio_pkt(&prm, vha); + res = qlt_24xx_build_ctio_pkt(qpair, &prm); if (unlikely(res != 0)) { - vha->req->cnt += full_req_cnt; + qpair->req->cnt += full_req_cnt; goto out_unmap_unlock; } @@ -3104,7 +3146,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, cpu_to_le32(prm.residual); pkt->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_SEND_STATUS); - if (qlt_need_explicit_conf(ha, cmd, 0)) { + if (qlt_need_explicit_conf(cmd, 0)) { pkt->u.status0.flags |= cpu_to_le16( CTIO7_FLAGS_EXPLICIT_CONFORM | @@ -3119,9 +3161,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, * req_pkt(). */ struct ctio7_to_24xx *ctio = - (struct ctio7_to_24xx *)qlt_get_req_pkt(vha); + (struct ctio7_to_24xx *)qlt_get_req_pkt( + qpair->req); - ql_dbg(ql_dbg_io, vha, 0x305e, + ql_dbg_qp(ql_dbg_tgt, qpair, 0x305e, "Building additional status packet 0x%p.\n", ctio); @@ -3148,7 +3191,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, */ qlt_24xx_init_ctio_to_isp((struct ctio7_to_24xx *)ctio, &prm); - pr_debug("Status CTIO7: %p\n", ctio); } } else qlt_24xx_init_ctio_to_isp(pkt, &prm); @@ -3159,14 +3201,17 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return 0; out_unmap_unlock: qlt_unmap_sg(vha, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return res; } @@ -3176,11 +3221,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) { struct ctio7_to_24xx *pkt; struct scsi_qla_host *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; struct qla_tgt *tgt = cmd->tgt; struct qla_tgt_prm prm; - unsigned long flags; + unsigned long flags = 0; int res = 0; + struct qla_qpair *qpair = cmd->qpair; memset(&prm, 0, sizeof(prm)); prm.cmd = cmd; @@ -3188,17 +3233,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) prm.sg = NULL; prm.req_cnt = 1; - /* Send marker if required */ - if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) - return -EIO; - /* Calculate number of entries and segments required */ if (qlt_pci_map_calc_cnt(&prm) != 0) return -EAGAIN; - spin_lock_irqsave(&ha->hardware_lock, flags); - - if (!ha->flags.fw_started || (cmd->reset_count != ha->chip_reset) || + if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) || (cmd->sess && cmd->sess->deleted)) { /* * Either the port is not online or this request was from @@ -3206,25 +3245,25 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) */ cmd->state = QLA_TGT_STATE_NEED_DATA; qlt_abort_cmd_on_host_reset(cmd->vha, cmd); - ql_dbg(ql_dbg_async, vha, 0xe102, + ql_dbg_qp(ql_dbg_async, qpair, 0xe102, "RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n", vha->flags.online, qla2x00_reset_active(vha), - cmd->reset_count, ha->chip_reset); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + cmd->reset_count, qpair->chip_reset); return 0; } + spin_lock_irqsave(qpair->qp_lock_ptr, flags); /* Does F/W have an IOCBs for this request */ - res = qlt_check_reserve_free_req(vha, prm.req_cnt); + res = qlt_check_reserve_free_req(qpair, prm.req_cnt); if (res != 0) goto out_unlock_free_unmap; if (cmd->se_cmd.prot_op) - res = qlt_build_ctio_crc2_pkt(&prm, vha); + res = qlt_build_ctio_crc2_pkt(qpair, &prm); else - res = qlt_24xx_build_ctio_pkt(&prm, vha); + res = qlt_24xx_build_ctio_pkt(qpair, &prm); if (unlikely(res != 0)) { - vha->req->cnt += prm.req_cnt; + qpair->req->cnt += prm.req_cnt; goto out_unlock_free_unmap; } @@ -3240,14 +3279,17 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return res; out_unlock_free_unmap: qlt_unmap_sg(vha, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return res; } @@ -3258,7 +3300,7 @@ EXPORT_SYMBOL(qlt_rdy_to_xfer); * it is assumed either hardware_lock or qpair lock is held. */ static void -qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, +qlt_handle_dif_error(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, struct ctio_crc_from_fw *sts) { uint8_t *ap = &sts->actual_dif[0]; @@ -3266,6 +3308,7 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, uint64_t lba = cmd->se_cmd.t_task_lba; uint8_t scsi_status, sense_key, asc, ascq; unsigned long flags; + struct scsi_qla_host *vha = cmd->vha; cmd->trc_flags |= TRC_DIF_ERR; @@ -3284,15 +3327,12 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, /* check appl tag */ if (cmd->e_app_tag != cmd->a_app_tag) { - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, - "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " - "Ref[%x|%x], App[%x|%x], " - "Guard [%x|%x] cmd=%p ox_id[%04x]", - cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, - cmd->a_ref_tag, cmd->e_ref_tag, - cmd->a_app_tag, cmd->e_app_tag, - cmd->a_guard, cmd->e_guard, - cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + ql_dbg(ql_dbg_tgt_dif, vha, 0xe00d, + "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, + cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd, + cmd->atio.u.isp24.fcp_hdr.ox_id); cmd->dif_err_code = DIF_ERR_APP; scsi_status = SAM_STAT_CHECK_CONDITION; @@ -3303,15 +3343,12 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, /* check ref tag */ if (cmd->e_ref_tag != cmd->a_ref_tag) { - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, - "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " - "Ref[%x|%x], App[%x|%x], " - "Guard[%x|%x] cmd=%p ox_id[%04x] ", - cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, - cmd->a_ref_tag, cmd->e_ref_tag, - cmd->a_app_tag, cmd->e_app_tag, - cmd->a_guard, cmd->e_guard, - cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + ql_dbg(ql_dbg_tgt_dif, vha, 0xe00e, + "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard[%x|%x] cmd=%p ox_id[%04x] ", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, + cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd, + cmd->atio.u.isp24.fcp_hdr.ox_id); cmd->dif_err_code = DIF_ERR_REF; scsi_status = SAM_STAT_CHECK_CONDITION; @@ -3323,15 +3360,13 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, /* check guard */ if (cmd->e_guard != cmd->a_guard) { - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, - "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " - "Ref[%x|%x], App[%x|%x], " - "Guard [%x|%x] cmd=%p ox_id[%04x]", - cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, - cmd->a_ref_tag, cmd->e_ref_tag, - cmd->a_app_tag, cmd->e_app_tag, - cmd->a_guard, cmd->e_guard, - cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + ql_dbg(ql_dbg_tgt_dif, vha, 0xe012, + "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, + cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd, + cmd->atio.u.isp24.fcp_hdr.ox_id); + cmd->dif_err_code = DIF_ERR_GRD; scsi_status = SAM_STAT_CHECK_CONDITION; sense_key = ABORTED_COMMAND; @@ -3354,7 +3389,8 @@ out: } spin_unlock_irqrestore(&cmd->cmd_lock, flags); - qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq); + qlt_send_resp_ctio(qpair, cmd, scsi_status, sense_key, asc, + ascq); /* assume scsi status gets out on the wire. * Will not wait for completion. */ @@ -3420,9 +3456,6 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha, unsigned long flags = 0; int rc; - if (qlt_issue_marker(vha, ha_locked) < 0) - return; - if (ha_locked) { rc = __qlt_send_term_imm_notif(vha, imm); @@ -3449,21 +3482,24 @@ done: spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); } -/* If hardware_lock held on entry, might drop it, then reaquire */ -/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ -static int __qlt_send_term_exchange(struct scsi_qla_host *vha, +/* + * If hardware_lock held on entry, might drop it, then reaquire + * This function sends the appropriate CTIO to ISP 2xxx or 24xx + */ +static int __qlt_send_term_exchange(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio) { + struct scsi_qla_host *vha = qpair->vha; struct ctio7_to_24xx *ctio24; struct qla_hw_data *ha = vha->hw; request_t *pkt; int ret = 0; uint16_t temp; - ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha); + ql_dbg(ql_dbg_tgt, vha, 0xe009, "Sending TERM EXCH CTIO (ha=%p)\n", ha); - pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL); + pkt = (request_t *)qla2x00_alloc_iocbs_ready(qpair, NULL); if (pkt == NULL) { ql_dbg(ql_dbg_tgt, vha, 0xe050, "qla_target(%d): %s failed: unable to allocate " @@ -3494,9 +3530,9 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio24->exchange_addr = atio->u.isp24.exchange_addr; - ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_TERMINATE); + temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 | + CTIO7_FLAGS_TERMINATE; + ctio24->u.status1.flags = cpu_to_le16(temp); temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); ctio24->u.status1.ox_id = cpu_to_le16(temp); @@ -3509,28 +3545,35 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); return ret; } -static void qlt_send_term_exchange(struct scsi_qla_host *vha, +static void qlt_send_term_exchange(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort) { + struct scsi_qla_host *vha; unsigned long flags = 0; int rc; - if (qlt_issue_marker(vha, ha_locked) < 0) - return; + /* why use different vha? NPIV */ + if (cmd) + vha = cmd->vha; + else + vha = qpair->vha; if (ha_locked) { - rc = __qlt_send_term_exchange(vha, cmd, atio); + rc = __qlt_send_term_exchange(qpair, cmd, atio); if (rc == -ENOMEM) qlt_alloc_qfull_cmd(vha, atio, 0, 0); goto done; } - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - rc = __qlt_send_term_exchange(vha, cmd, atio); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + rc = __qlt_send_term_exchange(qpair, cmd, atio); if (rc == -ENOMEM) qlt_alloc_qfull_cmd(vha, atio, 0, 0); @@ -3542,7 +3585,7 @@ done: } if (!ha_locked) - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return; } @@ -3614,17 +3657,17 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd) * 1) XFER Rdy completion + CMD_T_ABORT * 2) TCM TMR - drain_state_list */ - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, - "multiple abort. %p transport_state %x, t_state %x," - " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state, - cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf016, + "multiple abort. %p transport_state %x, t_state %x, " + "se_cmd_flags %x\n", cmd, cmd->se_cmd.transport_state, + cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags); return EIO; } cmd->aborted = 1; cmd->trc_flags |= TRC_ABORT; spin_unlock_irqrestore(&cmd->cmd_lock, flags); - qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1); + qlt_send_term_exchange(cmd->qpair, cmd, &cmd->atio, 0, 1); return 0; } EXPORT_SYMBOL(qlt_abort_cmd); @@ -3663,13 +3706,14 @@ EXPORT_SYMBOL(qlt_free_cmd); /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, +static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio, struct qla_tgt_cmd *cmd, uint32_t status) { int term = 0; + struct scsi_qla_host *vha = qpair->vha; if (cmd->se_cmd.prot_op) - ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + ql_dbg(ql_dbg_tgt_dif, vha, 0xe013, "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] " "se_cmd=%p tag[%x] op %#x/%s", cmd->lba, cmd->lba, @@ -3686,55 +3730,53 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, term = 1; if (term) - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); + qlt_term_ctio_exchange(qpair, ctio, cmd, status); return term; } -/* ha->hardware_lock supposed to be held on entry */ -static inline struct qla_tgt_cmd *qlt_get_cmd(struct scsi_qla_host *vha, - uint32_t handle) -{ - struct qla_hw_data *ha = vha->hw; - - handle--; - if (ha->tgt.cmds[handle] != NULL) { - struct qla_tgt_cmd *cmd = ha->tgt.cmds[handle]; - ha->tgt.cmds[handle] = NULL; - return cmd; - } else - return NULL; -} /* ha->hardware_lock supposed to be held on entry */ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha, - uint32_t handle, void *ctio) + struct rsp_que *rsp, uint32_t handle, void *ctio) { struct qla_tgt_cmd *cmd = NULL; + struct req_que *req; + int qid = GET_QID(handle); + uint32_t h = handle & ~QLA_TGT_HANDLE_MASK; - /* Clear out internal marks */ - handle &= ~(CTIO_COMPLETION_HANDLE_MARK | - CTIO_INTERMEDIATE_HANDLE_MARK); + if (unlikely(h == QLA_TGT_SKIP_HANDLE)) + return NULL; - if (handle != QLA_TGT_NULL_HANDLE) { - if (unlikely(handle == QLA_TGT_SKIP_HANDLE)) - return NULL; + if (qid == rsp->req->id) { + req = rsp->req; + } else if (vha->hw->req_q_map[qid]) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1000a, + "qla_target(%d): CTIO completion with different QID %d handle %x\n", + vha->vp_idx, rsp->id, handle); + req = vha->hw->req_q_map[qid]; + } else { + return NULL; + } + + h &= QLA_CMD_HANDLE_MASK; - /* handle-1 is actually used */ - if (unlikely(handle > DEFAULT_OUTSTANDING_COMMANDS)) { + if (h != QLA_TGT_NULL_HANDLE) { + if (unlikely(h > req->num_outstanding_cmds)) { ql_dbg(ql_dbg_tgt, vha, 0xe052, "qla_target(%d): Wrong handle %x received\n", vha->vp_idx, handle); return NULL; } - cmd = qlt_get_cmd(vha, handle); + + cmd = (struct qla_tgt_cmd *)req->outstanding_cmds[h]; if (unlikely(cmd == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe053, - "qla_target(%d): Suspicious: unable to " - "find the command with handle %x\n", vha->vp_idx, - handle); + ql_dbg(ql_dbg_async, vha, 0xe053, + "qla_target(%d): Suspicious: unable to find the command with handle %x req->id %d rsp->id %d\n", + vha->vp_idx, handle, req->id, rsp->id); return NULL; } + req->outstanding_cmds[h] = NULL; } else if (ctio != NULL) { /* We can't get loop ID from CTIO7 */ ql_dbg(ql_dbg_tgt, vha, 0xe054, @@ -3747,33 +3789,30 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha, } /* hardware_lock should be held by caller. */ -static void +void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) { struct qla_hw_data *ha = vha->hw; - uint32_t handle; if (cmd->sg_mapped) qlt_unmap_sg(vha, cmd); - handle = qlt_make_handle(vha); - /* TODO: fix debug message type and ids. */ if (cmd->state == QLA_TGT_STATE_PROCESSED) { ql_dbg(ql_dbg_io, vha, 0xff00, - "HOST-ABORT: handle=%d, state=PROCESSED.\n", handle); + "HOST-ABORT: state=PROCESSED.\n"); } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { cmd->write_data_transferred = 0; cmd->state = QLA_TGT_STATE_DATA_IN; ql_dbg(ql_dbg_io, vha, 0xff01, - "HOST-ABORT: handle=%d, state=DATA_IN.\n", handle); + "HOST-ABORT: state=DATA_IN.\n"); ha->tgt.tgt_ops->handle_data(cmd); return; } else { ql_dbg(ql_dbg_io, vha, 0xff03, - "HOST-ABORT: handle=%d, state=BAD(%d).\n", handle, + "HOST-ABORT: state=BAD(%d).\n", cmd->state); dump_stack(); } @@ -3782,51 +3821,16 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) ha->tgt.tgt_ops->free_cmd(cmd); } -void -qlt_host_reset_handler(struct qla_hw_data *ha) -{ - struct qla_tgt_cmd *cmd; - unsigned long flags; - scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - scsi_qla_host_t *vha = NULL; - struct qla_tgt *tgt = base_vha->vha_tgt.qla_tgt; - uint32_t i; - - if (!base_vha->hw->tgt.tgt_ops) - return; - - if (!tgt || qla_ini_mode_enabled(base_vha)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003, - "Target mode disabled\n"); - return; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xff10, - "HOST-ABORT-HNDLR: base_vha->dpc_flags=%lx.\n", - base_vha->dpc_flags); - - spin_lock_irqsave(&ha->hardware_lock, flags); - for (i = 1; i < DEFAULT_OUTSTANDING_COMMANDS + 1; i++) { - cmd = qlt_get_cmd(base_vha, i); - if (!cmd) - continue; - /* ha->tgt.cmds entry is cleared by qlt_get_cmd. */ - vha = cmd->vha; - qlt_abort_cmd_on_host_reset(vha, cmd); - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - - /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ -static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, - uint32_t status, void *ctio) +static void qlt_do_ctio_completion(struct scsi_qla_host *vha, + struct rsp_que *rsp, uint32_t handle, uint32_t status, void *ctio) { struct qla_hw_data *ha = vha->hw; struct se_cmd *se_cmd; struct qla_tgt_cmd *cmd; + struct qla_qpair *qpair = rsp->qpair; if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) { /* That could happen only in case of an error/reset/abort */ @@ -3838,7 +3842,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, return; } - cmd = qlt_ctio_to_cmd(vha, handle, ctio); + cmd = qlt_ctio_to_cmd(vha, rsp, handle, ctio); if (cmd == NULL) return; @@ -3883,7 +3887,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, */ cmd->sess->logout_on_delete = 0; cmd->sess->send_els_logo = 1; - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20f8, "%s %d %8phC post del sess\n", __func__, __LINE__, cmd->sess->port_name); @@ -3902,7 +3906,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, *((u64 *)&crc->actual_dif[0]), *((u64 *)&crc->expected_dif[0])); - qlt_handle_dif_error(vha, cmd, ctio); + qlt_handle_dif_error(qpair, cmd, ctio); return; } default: @@ -3922,7 +3926,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, if ((cmd->state != QLA_TGT_STATE_NEED_DATA) && (!cmd->aborted)) { cmd->trc_flags |= TRC_CTIO_ERR; - if (qlt_term_ctio_exchange(vha, ctio, cmd, status)) + if (qlt_term_ctio_exchange(qpair, ctio, cmd, status)) return; } } @@ -3998,18 +4002,16 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) { scsi_qla_host_t *vha = cmd->vha; struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct fc_port *sess = cmd->sess; struct atio_from_isp *atio = &cmd->atio; unsigned char *cdb; unsigned long flags; uint32_t data_length; int ret, fcp_task_attr, data_dir, bidi = 0; + struct qla_qpair *qpair = cmd->qpair; cmd->cmd_in_wq = 0; cmd->trc_flags |= TRC_DO_WORK; - if (tgt->tgt_stop) - goto out_term; if (cmd->aborted) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082, @@ -4021,8 +4023,6 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) spin_lock_init(&cmd->cmd_lock); cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; cmd->se_cmd.tag = atio->u.isp24.exchange_addr; - cmd->unpacked_lun = scsilun_to_int( - (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); if (atio->u.isp24.fcp_cmnd.rddata && atio->u.isp24.fcp_cmnd.wrdata) { @@ -4060,12 +4060,12 @@ out_term: * argument to qlt_send_term_exchange() and free the memory here. */ cmd->trc_flags |= TRC_DO_WORK_ERR; - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0); qlt_decr_num_pend_cmds(vha); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); @@ -4085,6 +4085,110 @@ static void qlt_do_work(struct work_struct *work) __qlt_do_work(cmd); } +void qlt_clr_qp_table(struct scsi_qla_host *vha) +{ + unsigned long flags; + struct qla_hw_data *ha = vha->hw; + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + void *node; + u64 key = 0; + + ql_log(ql_log_info, vha, 0x706c, + "User update Number of Active Qpairs %d\n", + ha->tgt.num_act_qpairs); + + spin_lock_irqsave(&ha->tgt.atio_lock, flags); + + btree_for_each_safe64(&tgt->lun_qpair_map, key, node) + btree_remove64(&tgt->lun_qpair_map, key); + + ha->base_qpair->lun_cnt = 0; + for (key = 0; key < ha->max_qpairs; key++) + if (ha->queue_pair_map[key]) + ha->queue_pair_map[key]->lun_cnt = 0; + + spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); +} + +static void qlt_assign_qpair(struct scsi_qla_host *vha, + struct qla_tgt_cmd *cmd) +{ + struct qla_qpair *qpair, *qp; + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + struct qla_qpair_hint *h; + + if (vha->flags.qpairs_available) { + h = btree_lookup64(&tgt->lun_qpair_map, cmd->unpacked_lun); + if (unlikely(!h)) { + /* spread lun to qpair ratio evently */ + int lcnt = 0, rc; + struct scsi_qla_host *base_vha = + pci_get_drvdata(vha->hw->pdev); + + qpair = vha->hw->base_qpair; + if (qpair->lun_cnt == 0) { + qpair->lun_cnt++; + h = qla_qpair_to_hint(tgt, qpair); + BUG_ON(!h); + rc = btree_insert64(&tgt->lun_qpair_map, + cmd->unpacked_lun, h, GFP_ATOMIC); + if (rc) { + qpair->lun_cnt--; + ql_log(ql_log_info, vha, 0xd037, + "Unable to insert lun %llx into lun_qpair_map\n", + cmd->unpacked_lun); + } + goto out; + } else { + lcnt = qpair->lun_cnt; + } + + h = NULL; + list_for_each_entry(qp, &base_vha->qp_list, + qp_list_elem) { + if (qp->lun_cnt == 0) { + qp->lun_cnt++; + h = qla_qpair_to_hint(tgt, qp); + BUG_ON(!h); + rc = btree_insert64(&tgt->lun_qpair_map, + cmd->unpacked_lun, h, GFP_ATOMIC); + if (rc) { + qp->lun_cnt--; + ql_log(ql_log_info, vha, 0xd038, + "Unable to insert lun %llx into lun_qpair_map\n", + cmd->unpacked_lun); + } + qpair = qp; + goto out; + } else { + if (qp->lun_cnt < lcnt) { + lcnt = qp->lun_cnt; + qpair = qp; + continue; + } + } + } + BUG_ON(!qpair); + qpair->lun_cnt++; + h = qla_qpair_to_hint(tgt, qpair); + BUG_ON(!h); + rc = btree_insert64(&tgt->lun_qpair_map, + cmd->unpacked_lun, h, GFP_ATOMIC); + if (rc) { + qpair->lun_cnt--; + ql_log(ql_log_info, vha, 0xd039, + "Unable to insert lun %llx into lun_qpair_map\n", + cmd->unpacked_lun); + } + } + } else { + h = &tgt->qphints[0]; + } +out: + cmd->qpair = h->qpair; + cmd->se_cmd.cpuid = h->cpuid; +} + static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, struct fc_port *sess, struct atio_from_isp *atio) @@ -4099,7 +4203,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; memset(cmd, 0, sizeof(struct qla_tgt_cmd)); - + cmd->cmd_type = TYPE_TGT_CMD; memcpy(&cmd->atio, atio, sizeof(*atio)); cmd->state = QLA_TGT_STATE_NEW; cmd->tgt = vha->vha_tgt.qla_tgt; @@ -4113,14 +4217,15 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, cmd->trc_flags = 0; cmd->jiffies_at_alloc = get_jiffies_64(); - cmd->reset_count = vha->hw->chip_reset; + cmd->unpacked_lun = scsilun_to_int( + (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); + qlt_assign_qpair(vha, cmd); + cmd->reset_count = vha->hw->base_qpair->chip_reset; + cmd->vp_idx = vha->vp_idx; return cmd; } -static void qlt_send_busy(struct scsi_qla_host *, struct atio_from_isp *, - uint16_t); - static void qlt_create_sess_from_atio(struct work_struct *work) { struct qla_tgt_sess_op *op = container_of(work, @@ -4166,10 +4271,15 @@ static void qlt_create_sess_from_atio(struct work_struct *work) */ cmd = qlt_get_tag(vha, sess, &op->atio); if (!cmd) { - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_busy(vha, &op->atio, SAM_STAT_BUSY); + struct qla_qpair *qpair = ha->base_qpair; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + qlt_send_busy(qpair, &op->atio, SAM_STAT_BUSY); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); kfree(op); return; } @@ -4182,9 +4292,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work) kfree(op); return; out_term: - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + qlt_send_term_exchange(vha->hw->base_qpair, NULL, &op->atio, 0, 0); kfree(op); } @@ -4214,9 +4322,9 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, memcpy(&op->atio, atio, sizeof(*atio)); op->vha = vha; - spin_lock(&vha->cmd_list_lock); + spin_lock_irqsave(&vha->cmd_list_lock, flags); list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list); - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); INIT_WORK(&op->work, qlt_create_sess_from_atio); queue_work(qla_tgt_wq, &op->work); @@ -4226,7 +4334,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, /* Another WWN used to have our s_id. Our PLOGI scheduled its * session deletion, but it's still in sess_del_work wq */ if (sess->deleted) { - ql_dbg(ql_dbg_io, vha, 0x3061, + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002, "New command while old session %p is being deleted\n", sess); return -EFAULT; @@ -4236,7 +4344,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. */ if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_tgt, vha, 0xffff, + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, "%s: kref_get fail, %8phC oxid %x \n", __func__, sess->port_name, be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id)); @@ -4255,15 +4363,15 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, cmd->cmd_in_wq = 1; cmd->trc_flags |= TRC_NEW_CMD; - cmd->se_cmd.cpuid = ha->msix_count ? - ha->tgt.rspq_vector_cpuid : WORK_CPU_UNBOUND; spin_lock_irqsave(&vha->cmd_list_lock, flags); list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list); spin_unlock_irqrestore(&vha->cmd_list_lock, flags); INIT_WORK(&cmd->work, qlt_do_work); - if (ha->msix_count) { + if (vha->flags.qpairs_available) { + queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &cmd->work); + } else if (ha->msix_count) { if (cmd->atio.u.isp24.fcp_cmnd.rddata) queue_work_on(smp_processor_id(), qla_tgt_wq, &cmd->work); @@ -4273,8 +4381,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, } else { queue_work(qla_tgt_wq, &cmd->work); } - return 0; + return 0; } /* ha->hardware_lock supposed to be held on entry */ @@ -4304,7 +4412,8 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, } mcmd->tmr_func = fn; mcmd->flags = flags; - mcmd->reset_count = vha->hw->chip_reset; + mcmd->reset_count = ha->base_qpair->chip_reset; + mcmd->qpair = ha->base_qpair; switch (fn) { case QLA_TGT_LUN_RESET: @@ -4331,13 +4440,12 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) struct qla_hw_data *ha = vha->hw; struct qla_tgt *tgt; struct fc_port *sess; - uint32_t lun, unpacked_lun; + u64 unpacked_lun; int fn; unsigned long flags; tgt = vha->vha_tgt.qla_tgt; - lun = a->u.isp24.fcp_cmnd.lun; fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; spin_lock_irqsave(&ha->tgt.sess_lock, flags); @@ -4345,7 +4453,8 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) a->u.isp24.fcp_hdr.s_id); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); + unpacked_lun = + scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun); if (!sess) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024, @@ -4368,7 +4477,7 @@ static int __qlt_abort_task(struct scsi_qla_host *vha, struct atio_from_isp *a = (struct atio_from_isp *)iocb; struct qla_hw_data *ha = vha->hw; struct qla_tgt_mgmt_cmd *mcmd; - uint32_t lun, unpacked_lun; + u64 unpacked_lun; int rc; mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); @@ -4384,10 +4493,11 @@ static int __qlt_abort_task(struct scsi_qla_host *vha, memcpy(&mcmd->orig_iocb.imm_ntfy, iocb, sizeof(mcmd->orig_iocb.imm_ntfy)); - lun = a->u.isp24.fcp_cmnd.lun; - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); - mcmd->reset_count = vha->hw->chip_reset; + unpacked_lun = + scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun); + mcmd->reset_count = ha->base_qpair->chip_reset; mcmd->tmr_func = QLA_TGT_2G_ABORT_TASK; + mcmd->qpair = ha->base_qpair; rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, mcmd->tmr_func, le16_to_cpu(iocb->u.isp2x.seq_id)); @@ -4491,7 +4601,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn, * Another wwn used to have our s_id/loop_id * kill the session, but don't free the loop_id */ - ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff, + ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01b, "Invalidating sess %p loop_id %d wwn %llx.\n", other_sess, other_sess->loop_id, other_wwn); @@ -4527,12 +4637,13 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) struct qla_tgt_cmd *cmd; uint32_t key; int count = 0; + unsigned long flags; key = (((u32)s_id->b.domain << 16) | ((u32)s_id->b.area << 8) | ((u32)s_id->b.al_pa)); - spin_lock(&vha->cmd_list_lock); + spin_lock_irqsave(&vha->cmd_list_lock, flags); list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); @@ -4557,7 +4668,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) count++; } } - spin_unlock(&vha->cmd_list_lock); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); return count; } @@ -4670,9 +4781,9 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, sess->keep_nport_handle = ((sess->loop_id == loop_id) && (sess->d_id.b24 == port_id.b24)); - ql_dbg(ql_dbg_disc, vha, 0xffff, - "%s %d %8phC post del sess\n", - __func__, __LINE__, sess->port_name); + ql_dbg(ql_dbg_disc, vha, 0x20f9, + "%s %d %8phC post del sess\n", + __func__, __LINE__, sess->port_name); qlt_schedule_sess_for_deletion_lock(sess); @@ -4742,7 +4853,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, /* Make session global (not used in fabric mode) */ if (ha->current_topology != ISP_CFG_F) { if (sess) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20fa, "%s %d %8phC post nack\n", __func__, __LINE__, sess->port_name); qla24xx_post_nack_work(vha, sess, iocb, @@ -4755,7 +4866,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, } } else { if (sess) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20fb, "%s %d %8phC post nack\n", __func__, __LINE__, sess->port_name); qla24xx_post_nack_work(vha, sess, iocb, @@ -4789,7 +4900,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20fc, "%s: logo %llx res %d sess %p ", __func__, wwn, res, sess); if (res == 0) { @@ -4813,15 +4924,15 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, { struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, - 0, 0, 0, 0, 0, 0); + qlt_send_notify_ack(ha->base_qpair, + &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0); tgt->link_reinit_iocb_pending = 0; } sess = qla2x00_find_fcport_by_wwpn(vha, iocb->u.isp24.port_name, 1); if (sess) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20fd, "sess %p lid %d|%d DS %d LS %d\n", sess, sess->loop_id, loop_id, sess->disc_state, sess->fw_login_state); @@ -4877,8 +4988,8 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, le16_to_cpu(iocb->u.isp24.nport_handle), iocb->u.isp24.status_subcode); if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, - 0, 0, 0, 0, 0, 0); + qlt_send_notify_ack(ha->base_qpair, + &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0); } memcpy(&tgt->link_reinit_iocb, iocb, sizeof(*iocb)); tgt->link_reinit_iocb_pending = 1; @@ -4972,33 +5083,36 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, } if (send_notify_ack) - qlt_send_notify_ack(vha, iocb, add_flags, 0, 0, 0, 0, 0); + qlt_send_notify_ack(ha->base_qpair, iocb, add_flags, 0, 0, 0, + 0, 0); } /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire * This function sends busy to ISP 2xxx or 24xx. */ -static int __qlt_send_busy(struct scsi_qla_host *vha, +static int __qlt_send_busy(struct qla_qpair *qpair, struct atio_from_isp *atio, uint16_t status) { + struct scsi_qla_host *vha = qpair->vha; struct ctio7_to_24xx *ctio24; struct qla_hw_data *ha = vha->hw; request_t *pkt; struct fc_port *sess = NULL; unsigned long flags; + u16 temp; 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); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); if (!sess) { - qlt_send_term_exchange(vha, NULL, atio, 1, 0); + qlt_send_term_exchange(qpair, NULL, atio, 1, 0); return 0; } /* Sending marker isn't necessary, since we called from ISR */ - pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); + pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL); if (!pkt) { ql_dbg(ql_dbg_io, vha, 0x3063, "qla_target(%d): %s failed: unable to allocate " @@ -5019,10 +5133,10 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; ctio24->exchange_addr = atio->u.isp24.exchange_addr; - ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - cpu_to_le16( + temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS | - CTIO7_FLAGS_DONT_RET_CTIO); + CTIO7_FLAGS_DONT_RET_CTIO; + ctio24->u.status1.flags = cpu_to_le16(temp); /* * CTIO from fw w/o se_cmd doesn't provide enough info to retry it, * if the explicit conformation is used. @@ -5031,7 +5145,10 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, ctio24->u.status1.scsi_status = cpu_to_le16(status); /* Memory Barrier */ wmb(); - qla2x00_start_iocbs(vha, vha->req); + if (qpair->reqq_start_iocbs) + qpair->reqq_start_iocbs(qpair); + else + qla2x00_start_iocbs(vha, qpair->req); return 0; } @@ -5050,6 +5167,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct se_session *se_sess; struct qla_tgt_cmd *cmd; int tag; + unsigned long flags; if (unlikely(tgt->tgt_stop)) { ql_dbg(ql_dbg_io, vha, 0x300a, @@ -5108,8 +5226,9 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, cmd->tgt = vha->vha_tgt.qla_tgt; cmd->vha = vha; - cmd->reset_count = vha->hw->chip_reset; + cmd->reset_count = ha->base_qpair->chip_reset; cmd->q_full = 1; + cmd->qpair = ha->base_qpair; if (qfull) { cmd->q_full = 1; @@ -5118,6 +5237,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, } else cmd->term_exchg = 1; + spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags); list_add_tail(&cmd->cmd_list, &vha->hw->tgt.q_full_list); vha->hw->tgt.num_qfull_cmds_alloc++; @@ -5125,35 +5245,41 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, vha->qla_stats.stat_max_qfull_cmds_alloc) vha->qla_stats.stat_max_qfull_cmds_alloc = vha->hw->tgt.num_qfull_cmds_alloc; + spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags); } int -qlt_free_qfull_cmds(struct scsi_qla_host *vha) +qlt_free_qfull_cmds(struct qla_qpair *qpair) { + struct scsi_qla_host *vha = qpair->vha; struct qla_hw_data *ha = vha->hw; unsigned long flags; struct qla_tgt_cmd *cmd, *tcmd; - struct list_head free_list; + struct list_head free_list, q_full_list; int rc = 0; if (list_empty(&ha->tgt.q_full_list)) return 0; INIT_LIST_HEAD(&free_list); + INIT_LIST_HEAD(&q_full_list); - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - + spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags); if (list_empty(&ha->tgt.q_full_list)) { - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); + spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags); return 0; } - list_for_each_entry_safe(cmd, tcmd, &ha->tgt.q_full_list, cmd_list) { + list_splice_init(&vha->hw->tgt.q_full_list, &q_full_list); + spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags); + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + list_for_each_entry_safe(cmd, tcmd, &q_full_list, cmd_list) { if (cmd->q_full) /* cmd->state is a borrowed field to hold status */ - rc = __qlt_send_busy(vha, &cmd->atio, cmd->state); + rc = __qlt_send_busy(qpair, &cmd->atio, cmd->state); else if (cmd->term_exchg) - rc = __qlt_send_term_exchange(vha, NULL, &cmd->atio); + rc = __qlt_send_term_exchange(qpair, NULL, &cmd->atio); if (rc == -ENOMEM) break; @@ -5177,7 +5303,7 @@ qlt_free_qfull_cmds(struct scsi_qla_host *vha) /* piggy back on hardware_lock for protection */ vha->hw->tgt.num_qfull_cmds_alloc--; } - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); cmd = NULL; @@ -5188,23 +5314,31 @@ qlt_free_qfull_cmds(struct scsi_qla_host *vha) */ qlt_free_cmd(cmd); } + + if (!list_empty(&q_full_list)) { + spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags); + list_splice(&q_full_list, &vha->hw->tgt.q_full_list); + spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags); + } + return rc; } static void -qlt_send_busy(struct scsi_qla_host *vha, - struct atio_from_isp *atio, uint16_t status) +qlt_send_busy(struct qla_qpair *qpair, struct atio_from_isp *atio, + uint16_t status) { int rc = 0; + struct scsi_qla_host *vha = qpair->vha; - rc = __qlt_send_busy(vha, atio, status); + rc = __qlt_send_busy(qpair, atio, status); if (rc == -ENOMEM) qlt_alloc_qfull_cmd(vha, atio, status, 1); } static int -qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, - struct atio_from_isp *atio, bool ha_locked) +qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair, + struct atio_from_isp *atio, uint8_t ha_locked) { struct qla_hw_data *ha = vha->hw; uint16_t status; @@ -5216,7 +5350,7 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); status = temp_sam_status; - qlt_send_busy(vha, atio, status); + qlt_send_busy(qpair, atio, status); if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -5255,16 +5389,17 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, "sending QUEUE_FULL\n", vha->vp_idx); if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL); + qlt_send_busy(ha->base_qpair, atio, + SAM_STAT_TASK_SET_FULL); if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&ha->hardware_lock, + flags); break; } - - if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) { - rc = qlt_chk_qfull_thresh_hold(vha, atio, ha_locked); + rc = qlt_chk_qfull_thresh_hold(vha, ha->base_qpair, + atio, ha_locked); if (rc != 0) { tgt->atio_irq_cmd_count--; return; @@ -5276,19 +5411,19 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, if (unlikely(rc != 0)) { if (rc == -ESRCH) { if (!ha_locked) - spin_lock_irqsave - (&ha->hardware_lock, flags); + spin_lock_irqsave(&ha->hardware_lock, + flags); #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ - qlt_send_busy(vha, atio, SAM_STAT_BUSY); + qlt_send_busy(ha->base_qpair, atio, + SAM_STAT_BUSY); #else - qlt_send_term_exchange(vha, NULL, atio, 1, 0); + qlt_send_term_exchange(ha->base_qpair, NULL, + atio, 1, 0); #endif - if (!ha_locked) - spin_unlock_irqrestore - (&ha->hardware_lock, flags); - + spin_unlock_irqrestore( + &ha->hardware_lock, flags); } else { if (tgt->tgt_stop) { ql_dbg(ql_dbg_tgt, vha, 0xe059, @@ -5303,7 +5438,8 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, if (!ha_locked) spin_lock_irqsave( &ha->hardware_lock, flags); - qlt_send_busy(vha, atio, SAM_STAT_BUSY); + qlt_send_busy(ha->base_qpair, + atio, SAM_STAT_BUSY); if (!ha_locked) spin_unlock_irqrestore( &ha->hardware_lock, flags); @@ -5344,7 +5480,8 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, /* ha->hardware_lock supposed to be held on entry */ /* called via callback from qla2xxx */ -static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) +static void qlt_response_pkt(struct scsi_qla_host *vha, + struct rsp_que *rsp, response_t *pkt) { struct qla_hw_data *ha = vha->hw; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; @@ -5361,14 +5498,12 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) * Otherwise, some commands can stuck. */ - tgt->irq_cmd_count++; - switch (pkt->entry_type) { case CTIO_CRC2: case CTIO_TYPE7: { struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; - qlt_do_ctio_completion(vha, entry->handle, + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); break; @@ -5387,19 +5522,17 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) break; } - rc = qlt_chk_qfull_thresh_hold(vha, atio, true); - if (rc != 0) { - tgt->irq_cmd_count--; + rc = qlt_chk_qfull_thresh_hold(vha, rsp->qpair, atio, 1); + if (rc != 0) return; - } rc = qlt_handle_cmd_for_atio(vha, atio); if (unlikely(rc != 0)) { if (rc == -ESRCH) { #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ - qlt_send_busy(vha, atio, 0); + qlt_send_busy(rsp->qpair, atio, 0); #else - qlt_send_term_exchange(vha, NULL, atio, 1, 0); + qlt_send_term_exchange(rsp->qpair, NULL, atio, 1, 0); #endif } else { if (tgt->tgt_stop) { @@ -5407,14 +5540,14 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) "qla_target: Unable to send " "command to target, sending TERM " "EXCHANGE for rsp\n"); - qlt_send_term_exchange(vha, NULL, + qlt_send_term_exchange(rsp->qpair, NULL, atio, 1, 0); } else { ql_dbg(ql_dbg_tgt, vha, 0xe060, "qla_target(%d): Unable to send " "command to target, sending BUSY " "status\n", vha->vp_idx); - qlt_send_busy(vha, atio, 0); + qlt_send_busy(rsp->qpair, atio, 0); } } } @@ -5424,7 +5557,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) case CONTINUE_TGT_IO_TYPE: { struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; - qlt_do_ctio_completion(vha, entry->handle, + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); break; @@ -5433,7 +5566,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) case CTIO_A64_TYPE: { struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; - qlt_do_ctio_completion(vha, entry->handle, + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); break; @@ -5523,7 +5656,6 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) break; } - tgt->irq_cmd_count--; } /* @@ -5536,14 +5668,8 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; int login_code; - if (!ha->tgt.tgt_ops) - return; - - if (unlikely(tgt == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe03a, - "ASYNC EVENT %#x, but no tgt (ha %p)\n", code, ha); + if (!tgt || tgt->tgt_stop || tgt->tgt_stopped) return; - } if (((code == MBA_POINT_TO_POINT) || (code == MBA_CHG_IN_CONNECTION)) && IS_QLA2100(ha)) @@ -5553,7 +5679,6 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, * Otherwise, some commands can stuck. */ - tgt->irq_cmd_count++; switch (code) { case MBA_RESET: /* Reset */ @@ -5576,7 +5701,8 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3])); if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, (void *)&tgt->link_reinit_iocb, + qlt_send_notify_ack(ha->base_qpair, + (void *)&tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0); tgt->link_reinit_iocb_pending = 0; } @@ -5595,17 +5721,17 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, break; case MBA_REJECTED_FCP_CMD: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, - "qla_target(%d): Async event LS_REJECT occurred " - "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, - le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]), - le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3])); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf017, + "qla_target(%d): Async event LS_REJECT occurred (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", + vha->vp_idx, + le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]), + le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3])); if (le16_to_cpu(mailbox[3]) == 1) { /* exchange starvation. */ vha->hw->exch_starvation++; if (vha->hw->exch_starvation > 5) { - ql_log(ql_log_warn, vha, 0xffff, + ql_log(ql_log_warn, vha, 0xd03a, "Exchange starvation-. Resetting RISC\n"); vha->hw->exch_starvation = 0; @@ -5641,7 +5767,6 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, break; } - tgt->irq_cmd_count--; } static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, @@ -5705,12 +5830,12 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, case MODE_DUAL: if (newfcport) { if (!IS_IIDMA_CAPABLE(vha->hw) || !vha->hw->flags.gpsc_supported) { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20fe, "%s %d %8phC post upd_fcport fcp_cnt %d\n", __func__, __LINE__, fcport->port_name, vha->fcport_count); qla24xx_post_upd_fcport_work(vha, fcport); } else { - ql_dbg(ql_dbg_disc, vha, 0xffff, + ql_dbg(ql_dbg_disc, vha, 0x20ff, "%s %d %8phC post gpsc fcp_cnt %d\n", __func__, __LINE__, fcport->port_name, vha->fcport_count); qla24xx_post_gpsc_work(vha, fcport); @@ -5836,7 +5961,7 @@ static void qlt_abort_work(struct qla_tgt *tgt, } if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff, + ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01c, "%s: kref_get fail %8phC \n", __func__, sess->port_name); sess = NULL; @@ -5859,7 +5984,8 @@ out_term2: out_term: spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); + qlt_24xx_send_abts_resp(ha->base_qpair, &prm->abts, + FCP_TMF_REJECTED, false); spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -5873,7 +5999,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, unsigned long flags; uint8_t *s_id = NULL; /* to hide compiler warnings */ int rc; - uint32_t lun, unpacked_lun; + u64 unpacked_lun; int fn; void *iocb; @@ -5900,7 +6026,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, } if (!kref_get_unless_zero(&sess->sess_kref)) { - ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff, + ql_dbg(ql_dbg_tgt_tmr, vha, 0xf020, "%s: kref_get fail %8phC\n", __func__, sess->port_name); sess = NULL; @@ -5909,9 +6035,9 @@ static void qlt_tmr_work(struct qla_tgt *tgt, } iocb = a; - lun = a->u.isp24.fcp_cmnd.lun; fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); + unpacked_lun = + scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun); rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); ha->tgt.tgt_ops->put_sess(sess); @@ -5926,7 +6052,7 @@ out_term2: ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); out_term: - qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0); + qlt_send_term_exchange(ha->base_qpair, NULL, &prm->tm_iocb2, 1, 0); } static void qlt_sess_work_fn(struct work_struct *work) @@ -5974,6 +6100,8 @@ static void qlt_sess_work_fn(struct work_struct *work) int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) { struct qla_tgt *tgt; + int rc, i; + struct qla_qpair_hint *h; if (!QLA_TGT_MODE_ENABLED()) return 0; @@ -5996,9 +6124,47 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) return -ENOMEM; } + tgt->qphints = kzalloc((ha->max_qpairs + 1) * + sizeof(struct qla_qpair_hint), GFP_KERNEL); + if (!tgt->qphints) { + kfree(tgt); + ql_log(ql_log_warn, base_vha, 0x0197, + "Unable to allocate qpair hints.\n"); + return -ENOMEM; + } + if (!(base_vha->host->hostt->supported_mode & MODE_TARGET)) base_vha->host->hostt->supported_mode |= MODE_TARGET; + rc = btree_init64(&tgt->lun_qpair_map); + if (rc) { + kfree(tgt->qphints); + kfree(tgt); + ql_log(ql_log_info, base_vha, 0x0198, + "Unable to initialize lun_qpair_map btree\n"); + return -EIO; + } + h = &tgt->qphints[0]; + h->qpair = ha->base_qpair; + INIT_LIST_HEAD(&h->hint_elem); + h->cpuid = ha->base_qpair->cpuid; + list_add_tail(&h->hint_elem, &ha->base_qpair->hints_list); + + for (i = 0; i < ha->max_qpairs; i++) { + unsigned long flags; + + struct qla_qpair *qpair = ha->queue_pair_map[i]; + h = &tgt->qphints[i + 1]; + INIT_LIST_HEAD(&h->hint_elem); + if (qpair) { + h->qpair = qpair; + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + list_add_tail(&h->hint_elem, &qpair->hints_list); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + h->cpuid = qpair->cpuid; + } + } + tgt->ha = ha; tgt->vha = base_vha; init_waitqueue_head(&tgt->waitQ); @@ -6229,7 +6395,6 @@ qlt_enable_vha(struct scsi_qla_host *vha) struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; unsigned long flags; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - int rspq_ent = QLA83XX_RSPQ_MSIX_ENTRY_NUMBER; if (!tgt) { ql_dbg(ql_dbg_tgt, vha, 0xe069, @@ -6248,17 +6413,6 @@ qlt_enable_vha(struct scsi_qla_host *vha) qla24xx_disable_vp(vha); qla24xx_enable_vp(vha); } else { - if (ha->msix_entries) { - ql_dbg(ql_dbg_tgt, vha, 0xffff, - "%s: host%ld : vector %d cpu %d\n", - __func__, vha->host_no, - ha->msix_entries[rspq_ent].vector, - ha->msix_entries[rspq_ent].cpuid); - - ha->tgt.rspq_vector_cpuid = - ha->msix_entries[rspq_ent].cpuid; - } - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); qla2x00_wait_for_hba_online(base_vha); @@ -6385,14 +6539,15 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked) * can not be trusted. There is no point in passing * it further up. */ - ql_log(ql_log_warn, vha, 0xffff, + ql_log(ql_log_warn, vha, 0xd03c, "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n", pkt->u.isp24.fcp_hdr.s_id, be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id), le32_to_cpu(pkt->u.isp24.exchange_addr), pkt); adjust_corrupted_atio(pkt); - qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0); + qlt_send_term_exchange(ha->base_qpair, NULL, pkt, + ha_locked, 0); } else { qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt, ha_locked); @@ -6443,8 +6598,9 @@ void qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) { struct qla_hw_data *ha = vha->hw; - u32 tmp; - u16 t; + + if (!QLA_TGT_MODE_ENABLED()) + return; if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { if (!ha->tgt.saved_set) { @@ -6459,24 +6615,10 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) ha->tgt.saved_set = 1; } - if (qla_tgt_mode_enabled(vha)) { + if (qla_tgt_mode_enabled(vha)) nv->exchange_count = cpu_to_le16(0xFFFF); - } else { /* dual */ - if (ql_dm_tgt_ex_pct > 100) { - ql_dm_tgt_ex_pct = 50; - } else if (ql_dm_tgt_ex_pct == 100) { - /* leave some for FW */ - ql_dm_tgt_ex_pct = 95; - } - - tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct; - tmp = tmp/100; - if (tmp > 0xffff) - tmp = 0xffff; - - t = tmp & 0xffff; - nv->exchange_count = cpu_to_le16(t); - } + else /* dual */ + nv->exchange_count = cpu_to_le16(ql2xexchoffld); /* Enable target mode */ nv->firmware_options_1 |= cpu_to_le32(BIT_4); @@ -6520,7 +6662,7 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) return; } - if (ha->tgt.enable_class_2) { + if (ha->base_qpair->enable_class_2) { if (vha->flags.init_done) fc_host_supported_classes(vha->host) = FC_COS_CLASS2 | FC_COS_CLASS3; @@ -6561,8 +6703,6 @@ void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) { struct qla_hw_data *ha = vha->hw; - u32 tmp; - u16 t; if (!QLA_TGT_MODE_ENABLED()) return; @@ -6580,23 +6720,10 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) ha->tgt.saved_set = 1; } - if (qla_tgt_mode_enabled(vha)) { + if (qla_tgt_mode_enabled(vha)) nv->exchange_count = cpu_to_le16(0xFFFF); - } else { /* dual */ - if (ql_dm_tgt_ex_pct > 100) { - ql_dm_tgt_ex_pct = 50; - } else if (ql_dm_tgt_ex_pct == 100) { - /* leave some for FW */ - ql_dm_tgt_ex_pct = 95; - } - - tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct; - tmp = tmp/100; - if (tmp > 0xffff) - tmp = 0xffff; - t = tmp & 0xffff; - nv->exchange_count = cpu_to_le16(t); - } + else /* dual */ + nv->exchange_count = cpu_to_le16(ql2xexchoffld); /* Enable target mode */ nv->firmware_options_1 |= cpu_to_le32(BIT_4); @@ -6639,7 +6766,7 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) return; } - if (ha->tgt.enable_class_2) { + if (ha->base_qpair->enable_class_2) { if (vha->flags.init_done) fc_host_supported_classes(vha->host) = FC_COS_CLASS2 | FC_COS_CLASS3; @@ -6686,21 +6813,6 @@ qlt_83xx_iospace_config(struct qla_hw_data *ha) ha->msix_count += 1; /* For ATIO Q */ } -int -qlt_24xx_process_response_error(struct scsi_qla_host *vha, - struct sts_entry_24xx *pkt) -{ - switch (pkt->entry_type) { - case ABTS_RECV_24XX: - case ABTS_RESP_24XX: - case CTIO_TYPE7: - case NOTIFY_ACK_TYPE: - case CTIO_CRC2: - return 1; - default: - return 0; - } -} void qlt_modify_vp_config(struct scsi_qla_host *vha, @@ -6742,7 +6854,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) rc = btree_init32(&ha->tgt.host_map); if (rc) - ql_log(ql_log_info, base_vha, 0xffff, + ql_log(ql_log_info, base_vha, 0xd03d, "Unable to initialize ha->host_map btree\n"); qlt_update_vp_map(base_vha, SET_VP_IDX); @@ -6778,7 +6890,8 @@ qlt_handle_abts_recv_work(struct work_struct *work) struct qla_hw_data *ha = vha->hw; unsigned long flags; - if (qla2x00_reset_active(vha) || (op->chip_reset != ha->chip_reset)) + if (qla2x00_reset_active(vha) || + (op->chip_reset != ha->base_qpair->chip_reset)) return; spin_lock_irqsave(&ha->tgt.atio_lock, flags); @@ -6786,14 +6899,15 @@ qlt_handle_abts_recv_work(struct work_struct *work) spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_response_pkt_all_vps(vha, (response_t *)&op->atio); + qlt_response_pkt_all_vps(vha, op->rsp, (response_t *)&op->atio); spin_unlock_irqrestore(&ha->hardware_lock, flags); kfree(op); } void -qlt_handle_abts_recv(struct scsi_qla_host *vha, response_t *pkt) +qlt_handle_abts_recv(struct scsi_qla_host *vha, struct rsp_que *rsp, + response_t *pkt) { struct qla_tgt_sess_op *op; @@ -6803,13 +6917,14 @@ qlt_handle_abts_recv(struct scsi_qla_host *vha, response_t *pkt) /* do not reach for ATIO queue here. This is best effort err * recovery at this point. */ - qlt_response_pkt_all_vps(vha, pkt); + qlt_response_pkt_all_vps(vha, rsp, pkt); return; } memcpy(&op->atio, pkt, sizeof(*pkt)); op->vha = vha; - op->chip_reset = vha->hw->chip_reset; + op->chip_reset = vha->hw->base_qpair->chip_reset; + op->rsp = rsp; INIT_WORK(&op->work, qlt_handle_abts_recv_work); queue_work(qla_tgt_wq, &op->work); return; @@ -6870,25 +6985,25 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd) case SET_AL_PA: slot = btree_lookup32(&vha->hw->tgt.host_map, key); if (!slot) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018, "Save vha in host_map %p %06x\n", vha, key); rc = btree_insert32(&vha->hw->tgt.host_map, key, vha, GFP_ATOMIC); if (rc) - ql_log(ql_log_info, vha, 0xffff, + ql_log(ql_log_info, vha, 0xd03e, "Unable to insert s_id into host_map: %06x\n", key); return; } - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, - "replace existing vha in host_map %p %06x\n", vha, key); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019, + "replace existing vha in host_map %p %06x\n", vha, key); btree_update32(&vha->hw->tgt.host_map, key, vha); break; case RESET_VP_IDX: vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL; break; case RESET_AL_PA: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a, "clear vha in host_map %p %06x\n", vha, key); slot = btree_lookup32(&vha->hw->tgt.host_map, key); if (slot) @@ -6950,7 +7065,7 @@ int __init qlt_init(void) sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct qla_tgt_mgmt_cmd), 0, NULL); if (!qla_tgt_mgmt_cmd_cachep) { - ql_log(ql_log_fatal, NULL, 0xe06d, + ql_log(ql_log_fatal, NULL, 0xd04b, "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n"); return -ENOMEM; }