From 08eb7f45de6131a72db7dd82607fd204d0d2bac2 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 21 Sep 2017 08:15:26 +0200 Subject: scsi: qla2xxx: Cocci spatch "pool_zalloc-simple" Use *_pool_zalloc rather than *_pool_alloc followed by memset with 0. Found by coccinelle spatch "api/alloc/pool_zalloc-simple.cocci" Signed-off-by: Thomas Meyer Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 3 +-- drivers/scsi/qla2xxx/qla_init.c | 3 +-- drivers/scsi/qla2xxx/qla_mbx.c | 27 +++++++++------------------ 3 files changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 2ea0ef93f5cb..451d9709bc06 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1116,14 +1116,13 @@ qla84xx_mgmt_cmd(struct bsg_job *bsg_job) return -EINVAL; } - mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); + mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); if (!mn) { ql_log(ql_log_warn, vha, 0x703c, "DMA alloc failed for fw buffer.\n"); return -ENOMEM; } - memset(mn, 0, sizeof(struct access_chip_84xx)); mn->entry_type = ACCESS_CHIP_IOCB_TYPE; mn->entry_count = 1; ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b5b48ddca962..4c53199db371 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -812,13 +812,12 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) sp->gen2 = fcport->login_gen; qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); - pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); + pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); if (pd == NULL) { ql_log(ql_log_warn, vha, 0xd043, "Failed to allocate port database structure.\n"); goto done_free_sp; } - memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); mb = sp->u.iocb_cmd.u.mbx.out_mb; mb[0] = MBC_GET_PORT_DATABASE; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 99502fa90810..7f71fd378c27 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1782,13 +1782,12 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) "Entered %s.\n", __func__); pd24 = NULL; - pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); + pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); if (pd == NULL) { ql_log(ql_log_warn, vha, 0x1050, "Failed to allocate port database structure.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); mcp->mb[0] = MBC_GET_PORT_DATABASE; if (opt != 0 && !IS_FWI2_CAPABLE(ha)) @@ -2255,13 +2254,12 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, else req = ha->req_q_map[0]; - lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); + lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); if (lg == NULL) { ql_log(ql_log_warn, vha, 0x1062, "Failed to allocate login IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(lg, 0, sizeof(struct logio_entry_24xx)); lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; @@ -2525,13 +2523,12 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d, "Entered %s.\n", __func__); - lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); + lg = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); if (lg == NULL) { ql_log(ql_log_warn, vha, 0x106e, "Failed to allocate logout IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(lg, 0, sizeof(struct logio_entry_24xx)); req = vha->req; lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; @@ -2820,13 +2817,12 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f, "Entered %s.\n", __func__); - pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); + pmap = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); if (pmap == NULL) { ql_log(ql_log_warn, vha, 0x1080, "Memory alloc failed.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(pmap, 0, FCAL_MAP_SIZE); mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP; mcp->mb[2] = MSW(pmap_dma); @@ -3014,13 +3010,12 @@ qla24xx_abort_command(srb_t *sp) return QLA_FUNCTION_FAILED; } - abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); + abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); if (abt == NULL) { ql_log(ql_log_warn, vha, 0x108d, "Failed to allocate abort IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(abt, 0, sizeof(struct abort_entry_24xx)); abt->entry_type = ABORT_IOCB_TYPE; abt->entry_count = 1; @@ -3098,13 +3093,12 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, rsp = req->rsp; } - tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); + tsk = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); if (tsk == NULL) { ql_log(ql_log_warn, vha, 0x1093, "Failed to allocate task management IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(tsk, 0, sizeof(struct tsk_mgmt_cmd)); tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; tsk->p.tsk.entry_count = 1; @@ -3856,14 +3850,13 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb, "Entered %s.\n", __func__); - vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); + vpmod = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); if (!vpmod) { ql_log(ql_log_warn, vha, 0x10bc, "Failed to allocate modify VP IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(vpmod, 0, sizeof(struct vp_config_entry_24xx)); vpmod->entry_type = VP_CONFIG_IOCB_TYPE; vpmod->entry_count = 1; vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS; @@ -3934,13 +3927,12 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) if (vp_index == 0 || vp_index >= ha->max_npiv_vports) return QLA_PARAMETER_ERROR; - vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma); + vce = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma); if (!vce) { ql_log(ql_log_warn, vha, 0x10c2, "Failed to allocate VP control IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } - memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx)); vce->entry_type = VP_CTRL_IOCB_TYPE; vce->entry_count = 1; @@ -6025,13 +6017,12 @@ int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) if (!vha->hw->flags.fw_started) goto done; - pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); + pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); if (pd == NULL) { ql_log(ql_log_warn, vha, 0xd047, "Failed to allocate port database structure.\n"); goto done_free_sp; } - memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); memset(&mc, 0, sizeof(mc)); mc.mb[0] = MBC_GET_PORT_DATABASE; -- cgit From e7240af5108fc8b068b1b21988e48f0c5005cae6 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 13 Oct 2017 09:34:03 -0700 Subject: scsi: qla2xxx: Reinstate module parameter ql2xenablemsix [mkp: fixed whitespace] Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 9 ++++++--- drivers/scsi/qla2xxx/qla_os.c | 9 +++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f852ca60c49f..46c7822c20fc 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -145,6 +145,7 @@ extern int ql2xmvasynctoatio; extern int ql2xuctrlirq; extern int ql2xnvmeenable; extern int ql2xautodetectsfp; +extern int ql2xenablemsix; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 9d9668aac6f6..ef7afd5eefe3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3486,11 +3486,14 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); /* If possible, enable MSI-X. */ - if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && - !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLAFX00(ha) && - !IS_QLA27XX(ha)) + if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) && + !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && + !IS_QLAFX00(ha) && !IS_QLA27XX(ha))) goto skip_msi; + if (ql2xenablemsix == 2) + goto skip_msix; + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && (ha->pdev->subsystem_device == 0x7040 || ha->pdev->subsystem_device == 0x7041 || diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5b2437a5ea44..84874e6b36de 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -268,6 +268,15 @@ MODULE_PARM_DESC(ql2xautodetectsfp, "Detect SFP range and set appropriate distance.\n" "1 (Default): Enable\n"); +int ql2xenablemsix = 1; +module_param(ql2xenablemsix, int, 0444); +MODULE_PARM_DESC(ql2xenablemsix, + "Set to enable MSI or MSI-X interrupt mechanism.\n" + " Default is 1, enable MSI-X interrupt mechanism.\n" + " 0 -- enable traditional pin-based mechanism.\n" + " 1 -- enable MSI-X interrupt mechanism.\n" + " 2 -- enable MSI interrupt mechanism.\n"); + /* * SCSI host template entry points */ -- cgit From c955886962a280eb90b6bde87448ee99c467c0b3 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 13 Oct 2017 09:34:04 -0700 Subject: scsi: qla2xxx: Add ATIO-Q processing for INTx mode Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 8 ++++++-- drivers/scsi/qla2xxx/qla_target.c | 12 +++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 486c075998f6..66d239cbbd66 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -922,6 +922,7 @@ struct mbx_cmd_32 { #define INTR_RSP_QUE_UPDATE_83XX 0x14 #define INTR_ATIO_QUE_UPDATE 0x1C #define INTR_ATIO_RSP_QUE_UPDATE 0x1D +#define INTR_ATIO_QUE_UPDATE_27XX 0x1E /* ISP mailbox loopback echo diagnostic error code */ #define MBS_LB_RESET 0x17 diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ef7afd5eefe3..ab97fb06c239 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3129,6 +3129,7 @@ qla24xx_intr_handler(int irq, void *dev_id) case INTR_RSP_QUE_UPDATE_83XX: qla24xx_process_response_queue(vha, rsp); break; + case INTR_ATIO_QUE_UPDATE_27XX: case INTR_ATIO_QUE_UPDATE:{ unsigned long flags2; spin_lock_irqsave(&ha->tgt.atio_lock, flags2); @@ -3259,6 +3260,7 @@ qla24xx_msix_default(int irq, void *dev_id) case INTR_RSP_QUE_UPDATE_83XX: qla24xx_process_response_queue(vha, rsp); break; + case INTR_ATIO_QUE_UPDATE_27XX: case INTR_ATIO_QUE_UPDATE:{ unsigned long flags2; spin_lock_irqsave(&ha->tgt.atio_lock, flags2); @@ -3347,7 +3349,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) .pre_vectors = QLA_BASE_VECTORS, }; - if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) { + if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) && + IS_ATIO_MSIX_CAPABLE(ha)) { desc.pre_vectors++; min_vecs++; } @@ -3432,7 +3435,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) * If target mode is enable, also request the vector for the ATIO * queue. */ - if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) { + if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) && + IS_ATIO_MSIX_CAPABLE(ha)) { qentry = &ha->msix_entries[QLA_ATIO_VECTOR]; rsp->msix = qentry; qentry->handle = rsp; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f05cfc83c9c8..12976a25f082 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6546,6 +6546,7 @@ void qlt_24xx_config_rings(struct scsi_qla_host *vha) { struct qla_hw_data *ha = vha->hw; + struct init_cb_24xx *icb; if (!QLA_TGT_MODE_ENABLED()) return; @@ -6553,14 +6554,19 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0); RD_REG_DWORD(ISP_ATIO_Q_OUT(vha)); - if (IS_ATIO_MSIX_CAPABLE(ha)) { + icb = (struct init_cb_24xx *)ha->init_cb; + + if ((ql2xenablemsix != 0) && IS_ATIO_MSIX_CAPABLE(ha)) { struct qla_msix_entry *msix = &ha->msix_entries[2]; - struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb; icb->msix_atio = cpu_to_le16(msix->entry); ql_dbg(ql_dbg_init, vha, 0xf072, "Registering ICB vector 0x%x for atio que.\n", msix->entry); + } else if (ql2xenablemsix == 0) { + icb->firmware_options_2 |= cpu_to_le32(BIT_26); + ql_dbg(ql_dbg_init, vha, 0xf07f, + "Registering INTx vector for ATIO.\n"); } } @@ -6805,7 +6811,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) if (!QLA_TGT_MODE_ENABLED()) return; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; } else { -- cgit From c0c462c8a061658ce5ae53c423b2a14bb280c2ab Mon Sep 17 00:00:00 2001 From: Duane Grigsby Date: Fri, 13 Oct 2017 09:34:05 -0700 Subject: scsi: qla2xxx: Allow MBC_GET_PORT_DATABASE to query and save the port states The MBC_GET_PORT_DATABASE command normally checks the port state information. This patch allows it to save that info in the fcport structure and ignore the check if the query flag is set. [mkp: typo] Signed-off-by: Duane Grigsby Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 4 ++++ drivers/scsi/qla2xxx/qla_mbx.c | 29 ++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 66d239cbbd66..f712c0cd46d6 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2303,6 +2303,7 @@ typedef struct fc_port { unsigned int send_els_logo:1; unsigned int login_pause:1; unsigned int login_succ:1; + unsigned int query:1; struct work_struct nvme_del_work; struct completion nvme_del_done; @@ -2369,6 +2370,8 @@ typedef struct fc_port { struct list_head gnl_entry; struct work_struct del_work; u8 iocb[IOCB_SIZE]; + u8 current_login_state; + u8 last_login_state; } fc_port_t; #define QLA_FCPORT_SCAN 1 @@ -4114,6 +4117,7 @@ typedef struct scsi_qla_host { #define QPAIR_ONLINE_CHECK_NEEDED 27 #define SET_ZIO_THRESHOLD_NEEDED 28 #define DETECT_SFP_CHANGE 29 +#define N2N_LOGIN_NEEDED 30 unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7f71fd378c27..71e56877e1eb 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1822,17 +1822,32 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) if (IS_FWI2_CAPABLE(ha)) { uint64_t zero = 0; + u8 current_login_state, last_login_state; + pd24 = (struct port_database_24xx *) pd; /* Check for logged in state. */ - if (pd24->current_login_state != PDS_PRLI_COMPLETE && - pd24->last_login_state != PDS_PRLI_COMPLETE) { - ql_dbg(ql_dbg_mbx, vha, 0x1051, - "Unable to verify login-state (%x/%x) for " - "loop_id %x.\n", pd24->current_login_state, - pd24->last_login_state, fcport->loop_id); + if (fcport->fc4f_nvme) { + current_login_state = pd24->current_login_state >> 4; + last_login_state = pd24->last_login_state >> 4; + } else { + current_login_state = pd24->current_login_state & 0xf; + last_login_state = pd24->last_login_state & 0xf; + } + fcport->current_login_state = pd24->current_login_state; + fcport->last_login_state = pd24->last_login_state; + + /* Check for logged in state. */ + if (current_login_state != PDS_PRLI_COMPLETE && + last_login_state != PDS_PRLI_COMPLETE) { + ql_dbg(ql_dbg_mbx, vha, 0x119a, + "Unable to verify login-state (%x/%x) for loop_id %x.\n", + current_login_state, last_login_state, + fcport->loop_id); rval = QLA_FUNCTION_FAILED; - goto gpd_error_out; + + if (!fcport->query) + goto gpd_error_out; } if (fcport->loop_id == FC_NO_LOOP_ID || -- cgit From edd05de1975927b51b4e8e1135ef4d6130dfd17c Mon Sep 17 00:00:00 2001 From: Duane Grigsby Date: Fri, 13 Oct 2017 09:34:06 -0700 Subject: scsi: qla2xxx: Changes to support N2N logins If we discovered a topology that is N2N then we will issue a login to the target. If our WWPN is bigger than the target's WWPN then we will initiate login, otherwise we will just wait for the target to initiate login. [mkp: many whitespace errors] Signed-off-by: Duane Grigsby Signed-off-by: Michael Hernandez Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Tested-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 24 +++++ drivers/scsi/qla2xxx/qla_fw.h | 4 +- drivers/scsi/qla2xxx/qla_gbl.h | 4 + drivers/scsi/qla2xxx/qla_init.c | 135 +++++++++++++++++++++++++++- drivers/scsi/qla2xxx/qla_iocb.c | 195 +++++++++++++++++++++++++++++++++++++--- drivers/scsi/qla2xxx/qla_isr.c | 42 ++++++++- drivers/scsi/qla2xxx/qla_mbx.c | 76 ++++++++++++++++ 7 files changed, 459 insertions(+), 21 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f712c0cd46d6..01a9b8971e88 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -323,6 +323,12 @@ struct els_logo_payload { uint8_t wwpn[WWN_SIZE]; }; +struct els_plogi_payload { + uint8_t opcode; + uint8_t rsvd[3]; + uint8_t data[112]; +}; + struct ct_arg { void *iocb; u16 nport_handle; @@ -358,6 +364,19 @@ struct srb_iocb { dma_addr_t els_logo_pyld_dma; } els_logo; struct { +#define ELS_DCMD_PLOGI 0x3 + uint32_t flags; + uint32_t els_cmd; + struct completion comp; + struct els_plogi_payload *els_plogi_pyld; + struct els_plogi_payload *els_resp_pyld; + dma_addr_t els_plogi_pyld_dma; + dma_addr_t els_resp_pyld_dma; + uint32_t fw_status[3]; + __le16 comp_status; + __le16 len; + } els_plogi; + struct { /* * Values for flags field below are as * defined in tsk_mgmt_entry struct @@ -2349,6 +2368,7 @@ typedef struct fc_port { uint8_t fc4_type; uint8_t fc4f_nvme; uint8_t scan_state; + uint8_t n2n_flag; unsigned long last_queue_full; unsigned long last_ramp_up; @@ -2372,6 +2392,7 @@ typedef struct fc_port { u8 iocb[IOCB_SIZE]; u8 current_login_state; u8 last_login_state; + struct completion n2n_done; } fc_port_t; #define QLA_FCPORT_SCAN 1 @@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host { wait_queue_head_t fcport_waitQ; wait_queue_head_t vref_waitq; uint8_t min_link_speed_feat; + uint8_t n2n_node_name[WWN_SIZE]; + uint8_t n2n_port_name[WWN_SIZE]; + uint16_t n2n_id; } scsi_qla_host_t; struct qla27xx_image_status { diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index bec641aae7b3..d5cef0727e72 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -753,9 +753,7 @@ struct els_entry_24xx { uint8_t reserved_2; uint8_t port_id[3]; - uint8_t reserved_3; - - uint16_t reserved_4; + uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ #define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 46c7822c20fc..0a23af5aa479 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t); +extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, + port_id_t); extern void qla2x00_update_fcports(scsi_qla_host_t *); @@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t, uint16_t *); int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *, struct port_database_24xx *); +int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t, + void *, uint16_t); extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *); extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4c53199db371..1c53c0774e24 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1433,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) qla24xx_post_gpdb_work(vha, ea->fcport, 0); break; default: + if (ea->fcport->n2n_flag) { + ql_dbg(ql_dbg_disc, vha, 0x2118, + "%s %d %8phC post fc4 prli\n", + __func__, __LINE__, ea->fcport->port_name); + ea->fcport->fc4f_nvme = 0; + ea->fcport->n2n_flag = 0; + qla24xx_post_prli_work(vha, ea->fcport); + } ql_dbg(ql_dbg_disc, vha, 0x2119, "%s %d %8phC unhandle event of %x\n", __func__, __LINE__, ea->fcport->port_name, ea->data[0]); @@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) return (rval); } +/* + * N2N Login + * Updates Fibre Channel Device Database with local loop devices. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + */ +static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha, + fc_port_t *fcport) +{ + struct qla_hw_data *ha = vha->hw; + int res = QLA_SUCCESS, rval; + int greater_wwpn = 0; + int logged_in = 0; + + if (ha->current_topology != ISP_CFG_N) + return res; + + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(vha->n2n_port_name)) { + ql_dbg(ql_dbg_disc, vha, 0x2002, + "HBA WWPN is greater %llx > target %llx\n", + wwn_to_u64(vha->port_name), + wwn_to_u64(vha->n2n_port_name)); + greater_wwpn = 1; + fcport->d_id.b24 = vha->n2n_id; + } + + fcport->loop_id = vha->loop_id; + fcport->fc4f_nvme = 0; + fcport->query = 1; + + ql_dbg(ql_dbg_disc, vha, 0x4001, + "Initiate N2N login handler: HBA port_id=%06x loopid=%d\n", + fcport->d_id.b24, vha->loop_id); + + /* Fill in member data. */ + if (!greater_wwpn) { + rval = qla2x00_get_port_database(vha, fcport, 0); + ql_dbg(ql_dbg_disc, vha, 0x1051, + "Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n", + fcport->current_login_state, fcport->last_login_state, + fcport->d_id.b24, fcport->loop_id, rval); + + if (((fcport->current_login_state & 0xf) == 0x4) || + ((fcport->current_login_state & 0xf) == 0x6)) + logged_in = 1; + } + + if (logged_in || greater_wwpn) { + if (!vha->nvme_local_port && vha->flags.nvme_enabled) + qla_nvme_register_hba(vha); + + /* Set connected N_Port d_id */ + if (vha->flags.nvme_enabled) + fcport->fc4f_nvme = 1; + + fcport->scan_state = QLA_FCPORT_FOUND; + fcport->fw_login_state = DSC_LS_PORT_UNAVAIL; + fcport->disc_state = DSC_GNL; + fcport->n2n_flag = 1; + fcport->flags = 3; + vha->hw->flags.gpsc_supported = 0; + + if (greater_wwpn) { + ql_dbg(ql_dbg_disc, vha, 0x20e5, + "%s %d PLOGI ELS %8phC\n", + __func__, __LINE__, fcport->port_name); + + res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI, + fcport, fcport->d_id); + } + + if (res != QLA_SUCCESS) { + ql_log(ql_log_info, vha, 0xd04d, + "PLOGI Failed: portid=%06x - retrying\n", + fcport->d_id.b24); + res = QLA_SUCCESS; + } else { + /* State 0x6 means FCP PRLI complete */ + if ((fcport->current_login_state & 0xf) == 0x6) { + ql_dbg(ql_dbg_disc, vha, 0x2118, + "%s %d %8phC post GPDB work\n", + __func__, __LINE__, fcport->port_name); + fcport->chip_reset = + vha->hw->base_qpair->chip_reset; + qla24xx_post_gpdb_work(vha, fcport, 0); + } else { + ql_dbg(ql_dbg_disc, vha, 0x2118, + "%s %d %8phC post NVMe PRLI\n", + __func__, __LINE__, fcport->port_name); + qla24xx_post_prli_work(vha, fcport); + } + } + } else { + /* Wait for next database change */ + set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags); + } + return res; +} /* * qla2x00_configure_local_loop @@ -4437,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) } } + /* Inititae N2N login. */ + if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { + rval = qla24xx_n2n_handle_login(vha, new_fcport); + if (rval != QLA_SUCCESS) + goto cleanup_allocation; + return QLA_SUCCESS; + } + /* Add devices to port list. */ id_iter = (char *)ha->gid_list; for (index = 0; index < entries; index++) { @@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) "Failed to retrieve fcport information " "-- get_port_database=%x, loop_id=0x%04x.\n", rval2, new_fcport->loop_id); - ql_dbg(ql_dbg_disc, vha, 0x2105, - "Scheduling resync.\n"); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - continue; + /* Skip retry if N2N */ + if (ha->current_topology != ISP_CFG_N) { + ql_dbg(ql_dbg_disc, vha, 0x2105, + "Scheduling resync.\n"); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + continue; + } } spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); @@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) icb->firmware_options_3 |= BIT_0; + if (IS_QLA27XX(ha)) { + icb->firmware_options_3 |= BIT_8; + ql_dbg(ql_log_info, vha, 0x0075, + "Enabling direct connection.\n"); + } + if (rval) { ql_log(ql_log_warn, vha, 0x0076, "NVRAM configuration failed.\n"); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 2f94159186d7..d810a447cb4a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { scsi_qla_host_t *vha = sp->vha; struct srb_iocb *elsio = &sp->u.iocb_cmd; + uint32_t dsd_len = 24; els_iocb->entry_type = ELS_IOCB_TYPE; els_iocb->entry_count = 1; @@ -2534,23 +2535,197 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; els_iocb->port_id[1] = sp->fcport->d_id.b.area; els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->s_id[0] = vha->d_id.b.al_pa; + els_iocb->s_id[1] = vha->d_id.b.area; + els_iocb->s_id[2] = vha->d_id.b.domain; els_iocb->control_flags = 0; - els_iocb->tx_byte_count = sizeof(struct els_logo_payload); - els_iocb->tx_address[0] = - cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); - els_iocb->tx_address[1] = - cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); - els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); + if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { + els_iocb->tx_byte_count = sizeof(struct els_plogi_payload); + els_iocb->tx_address[0] = + cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma)); + els_iocb->tx_address[1] = + cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma)); + els_iocb->tx_len = dsd_len; + + els_iocb->rx_dsd_count = 1; + els_iocb->rx_byte_count = sizeof(struct els_plogi_payload); + els_iocb->rx_address[0] = + cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma)); + els_iocb->rx_address[1] = + cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma)); + els_iocb->rx_len = dsd_len; + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, + "PLOGI ELS IOCB:\n"); + ql_dump_buffer(ql_log_info, vha, 0x0109, + (uint8_t *)els_iocb, 0x70); + } else { + els_iocb->tx_byte_count = sizeof(struct els_logo_payload); + els_iocb->tx_address[0] = + cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); + els_iocb->tx_address[1] = + cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); + els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); - els_iocb->rx_byte_count = 0; - els_iocb->rx_address[0] = 0; - els_iocb->rx_address[1] = 0; - els_iocb->rx_len = 0; + els_iocb->rx_byte_count = 0; + els_iocb->rx_address[0] = 0; + els_iocb->rx_address[1] = 0; + els_iocb->rx_len = 0; + } sp->vha->qla_stats.control_requests++; } +static void +qla2x00_els_dcmd2_sp_free(void *data) +{ + srb_t *sp = data; + struct srb_iocb *elsio = &sp->u.iocb_cmd; + + if (elsio->u.els_plogi.els_plogi_pyld) + dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE, + elsio->u.els_plogi.els_plogi_pyld, + elsio->u.els_plogi.els_plogi_pyld_dma); + + if (elsio->u.els_plogi.els_resp_pyld) + dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE, + elsio->u.els_plogi.els_resp_pyld, + elsio->u.els_plogi.els_resp_pyld_dma); + + del_timer(&elsio->timer); + qla2x00_rel_sp(sp); +} + +static void +qla2x00_els_dcmd2_iocb_timeout(void *data) +{ + srb_t *sp = data; + fc_port_t *fcport = sp->fcport; + struct scsi_qla_host *vha = sp->vha; + struct qla_hw_data *ha = vha->hw; + struct srb_iocb *lio = &sp->u.iocb_cmd; + unsigned long flags = 0; + int res; + + ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069, + "%s hdl=%x ELS Timeout, %8phC portid=%06x\n", + sp->name, sp->handle, fcport->port_name, fcport->d_id.b24); + + /* Abort the exchange */ + spin_lock_irqsave(&ha->hardware_lock, flags); + res = ha->isp_ops->abort_command(sp); + ql_dbg(ql_dbg_io, vha, 0x3070, + "mbx abort_command %s\n", + (res == QLA_SUCCESS) ? "successful" : "failed"); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + complete(&lio->u.els_plogi.comp); +} + +static void +qla2x00_els_dcmd2_sp_done(void *ptr, int res) +{ + srb_t *sp = ptr; + fc_port_t *fcport = sp->fcport; + struct srb_iocb *lio = &sp->u.iocb_cmd; + struct scsi_qla_host *vha = sp->vha; + + ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072, + "%s ELS hdl=%x, portid=%06x done %8pC\n", + sp->name, sp->handle, fcport->d_id.b24, fcport->port_name); + + complete(&lio->u.els_plogi.comp); +} + +int +qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, + fc_port_t *fcport, port_id_t remote_did) +{ + srb_t *sp; + struct srb_iocb *elsio = NULL; + struct qla_hw_data *ha = vha->hw; + int rval = QLA_SUCCESS; + void *ptr, *resp_ptr; + dma_addr_t ptr_dma; + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) { + ql_log(ql_log_info, vha, 0x70e6, + "SRB allocation failed\n"); + return -ENOMEM; + } + + elsio = &sp->u.iocb_cmd; + fcport->d_id.b.domain = remote_did.b.domain; + fcport->d_id.b.area = remote_did.b.area; + fcport->d_id.b.al_pa = remote_did.b.al_pa; + + ql_dbg(ql_dbg_io, vha, 0x3073, + "Enter: PLOGI portid=%06x\n", fcport->d_id.b24); + + sp->type = SRB_ELS_DCMD; + sp->name = "ELS_DCMD"; + sp->fcport = fcport; + qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT); + elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; + sp->done = qla2x00_els_dcmd2_sp_done; + sp->free = qla2x00_els_dcmd2_sp_free; + + ptr = elsio->u.els_plogi.els_plogi_pyld = + dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); + ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma; + + if (!elsio->u.els_plogi.els_plogi_pyld) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + resp_ptr = elsio->u.els_plogi.els_resp_pyld = + dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); + + if (!elsio->u.els_plogi.els_resp_pyld) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr); + + memset(ptr, 0, sizeof(struct els_plogi_payload)); + memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); + elsio->u.els_plogi.els_cmd = els_opcode; + elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; + qla24xx_get_port_login_templ(vha, ptr_dma + 4, + &elsio->u.els_plogi.els_plogi_pyld->data[0], + sizeof(struct els_plogi_payload)); + + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n"); + ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109, + (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70); + + init_completion(&elsio->u.els_plogi.comp); + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) { + rval = QLA_FUNCTION_FAILED; + goto out; + } + + ql_dbg(ql_dbg_io, vha, 0x3074, + "%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n", + sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24); + + wait_for_completion(&elsio->u.els_plogi.comp); + + if (elsio->u.els_plogi.comp_status != CS_COMPLETE) + rval = QLA_FUNCTION_FAILED; + +out: + sp->free(sp); + return rval; +} + static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ab97fb06c239..c7878be9dd5f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1041,6 +1041,7 @@ global_port_update: */ atomic_set(&vha->loop_down_timer, 0); if (atomic_read(&vha->loop_state) != LOOP_DOWN && + !ha->flags.n2n_ae && atomic_read(&vha->loop_state) != LOOP_DEAD) { ql_dbg(ql_dbg_async, vha, 0x5011, "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", @@ -1545,6 +1546,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, uint32_t fw_status[3]; uint8_t* fw_sts_ptr; int res; + struct srb_iocb *els; sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); if (!sp) @@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, break; case SRB_ELS_DCMD: type = "Driver ELS logo"; - ql_dbg(ql_dbg_user, vha, 0x5047, - "Completing %s: (%p) type=%d.\n", type, sp, sp->type); - sp->done(sp, 0); - return; + if (iocb_type != ELS_IOCB_TYPE) { + ql_dbg(ql_dbg_user, vha, 0x5047, + "Completing %s: (%p) type=%d.\n", + type, sp, sp->type); + sp->done(sp, 0); + return; + } + break; case SRB_CT_PTHRU_CMD: /* borrowing sts_entry_24xx.comp_status. same location as ct_entry_24xx.comp_status @@ -1584,6 +1590,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); + if (iocb_type == ELS_IOCB_TYPE) { + els = &sp->u.iocb_cmd; + els->u.els_plogi.fw_status[0] = fw_status[0]; + els->u.els_plogi.fw_status[1] = fw_status[1]; + els->u.els_plogi.fw_status[2] = fw_status[2]; + els->u.els_plogi.comp_status = fw_status[0]; + if (comp_status == CS_COMPLETE) { + res = DID_OK << 16; + } else { + if (comp_status == CS_DATA_UNDERRUN) { + res = DID_OK << 16; + els->u.els_plogi.len = + le16_to_cpu(((struct els_sts_entry_24xx *) + pkt)->total_byte_count); + } else { + els->u.els_plogi.len = 0; + res = DID_ERROR << 16; + } + } + ql_log(ql_log_info, vha, 0x503f, + "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n", + type, sp->handle, comp_status, fw_status[1], fw_status[2], + le16_to_cpu(((struct els_sts_entry_24xx *) + pkt)->total_byte_count)); + goto els_ct_done; + } + /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT * fc payload to the caller */ @@ -1631,6 +1664,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; bsg_job->reply_len = 0; } +els_ct_done: sp->done(sp, res); } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 71e56877e1eb..cb717d47339f 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) if (pd == NULL) { ql_log(ql_log_warn, vha, 0x1050, "Failed to allocate port database structure.\n"); + fcport->query = 0; return QLA_MEMORY_ALLOC_FAILED; } @@ -1926,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) gpd_error_out: dma_pool_free(ha->s_dma_pool, pd, pd_dma); + fcport->query = 0; if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1052, @@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, rptid_entry->vp_status, rptid_entry->port_id[2], rptid_entry->port_id[1], rptid_entry->port_id[0]); + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Remote WWPN %8phC.\n", + rptid_entry->u.f1.port_name); + + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: WWPN %8phC.\n", + vha->port_name); + + /* N2N. direct connect */ + if (IS_QLA27XX(ha) && + ((rptid_entry->u.f1.flags>>1) & 0x7) == 2) { + /* if our portname is higher then initiate N2N login */ + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(rptid_entry->u.f1.port_name)) { + // ??? qlt_update_host_map(vha, id); + vha->n2n_id = 0x1; + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Setting n2n_update_needed for id %d\n", + vha->n2n_id); + } else { + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Remote login - Waiting for WWPN %8phC.\n", + rptid_entry->u.f1.port_name); + } + + memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name, + WWN_SIZE); + set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + return; + } /* buffer to buffer credit flag */ vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0; @@ -4599,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version) return rval; } +int +qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, + void *buf, uint16_t bufsiz) +{ + int rval, i; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint32_t *bp; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8; + mcp->mb[2] = MSW(buf_dma); + mcp->mb[3] = LSW(buf_dma); + mcp->mb[6] = MSW(MSD(buf_dma)); + mcp->mb[7] = LSW(MSD(buf_dma)); + mcp->mb[8] = bufsiz/4; + mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x115a, + "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b, + "Done %s.\n", __func__); + bp = (uint32_t *) buf; + for (i = 0; i < (bufsiz-4)/4; i++, bp++) + *bp = cpu_to_be32(*bp); + } + + return rval; +} + static int qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) { -- cgit From 4ca8204781bc2326c091a1b4dec6d4e4c63a5e30 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 13 Oct 2017 09:34:07 -0700 Subject: scsi: qla2xxx: Update driver version to 10.00.00.02-k Signed-off-by: Himanshu Madhani Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 8c4b505c9f66..b6ec02b96d3d 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.01-k" +#define QLA2XXX_VERSION "10.00.00.02-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 0 -- cgit From c38d1baff87ffaa0c5966b57c5cfa906b58ce9e6 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 13 Oct 2017 15:43:22 -0700 Subject: scsi: qla2xxx: Use ql2xnvmeenable to enable Q-Pair for FC-NVMe In some environments, user can choose to not enable SCSI-MQ but wants to use FC-NVMe feature of the driver. Since driver relies on Q-Pairs to allocate FC-NVMe resources, use existing module parameter to create Q-Pairs when FC-NVMe is enabled. Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 2 +- drivers/scsi/qla2xxx/qla_mid.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 27 ++++++++++++++++++--------- 4 files changed, 21 insertions(+), 12 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1c53c0774e24..76edb4a02a8d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8036,7 +8036,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, return NULL; } - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL); if (qpair == NULL) { ql_log(ql_log_warn, vha, 0x0182, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c7878be9dd5f..e9b14405e7d4 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3411,7 +3411,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) ha->msix_count, ret); ha->msix_count = ret; /* Recalculate queue values */ - if (ha->mqiobase && ql2xmqsupport) { + if (ha->mqiobase && (ql2xmqsupport || ql2xnvmeenable)) { ha->max_req_queues = ha->msix_count - 1; /* ATIOQ needs 1 vector. That's 1 less QPair */ diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index c0f8f6c17b79..3630bb66a74c 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -606,7 +606,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha) struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair, *tqpair; - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { list_for_each_entry_safe(qpair, tqpair, &vha->qp_list, qp_list_elem) qla2xxx_delete_qpair(vha, qpair); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 84874e6b36de..17fc549aae96 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -433,7 +433,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, qla_init_base_qpair(vha, req, rsp); - if (ql2xmqsupport && ha->max_qpairs) { + if ((ql2xmqsupport || ql2xnvmeenable) && ha->max_qpairs) { ha->queue_pair_map = kcalloc(ha->max_qpairs, sizeof(struct qla_qpair *), GFP_KERNEL); if (!ha->queue_pair_map) { @@ -1976,7 +1976,8 @@ skip_pio: /* Determine queue resources */ ha->max_req_queues = ha->max_rsp_queues = 1; ha->msix_count = QLA_BASE_VECTORS; - if (!ql2xmqsupport || (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) + if (!ql2xmqsupport || !ql2xnvmeenable || + (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) goto mqiobase_exit; ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), @@ -2073,7 +2074,7 @@ qla83xx_iospace_config(struct qla_hw_data *ha) * By default, driver uses at least two msix vectors * (default & rspq) */ - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { /* MB interrupt uses 1 vector */ ha->max_req_queues = ha->msix_count - 1; @@ -3089,9 +3090,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_dbg(ql_dbg_init, base_vha, 0x0192, "blk/scsi-mq enabled, HW queues = %d.\n", host->nr_hw_queues); - } else - ql_dbg(ql_dbg_init, base_vha, 0x0193, - "blk/scsi-mq disabled.\n"); + } else { + if (ql2xnvmeenable) { + host->nr_hw_queues = ha->max_qpairs; + ql_dbg(ql_dbg_init, base_vha, 0x0194, + "FC-NVMe support is enabled, HW queues=%d\n", + host->nr_hw_queues); + } else { + ql_dbg(ql_dbg_init, base_vha, 0x0193, + "blk/scsi-mq disabled.\n"); + } + } qlt_probe_one_stage1(base_vha, ha); @@ -6300,7 +6309,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) switch (state) { case pci_channel_io_normal: ha->flags.eeh_busy = 0; - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } @@ -6317,7 +6326,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) pci_disable_device(pdev); /* Return back all IOs */ qla2x00_abort_all_cmds(vha, DID_RESET << 16); - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } @@ -6325,7 +6334,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) case pci_channel_io_perm_failure: ha->flags.pci_channel_io_perm_failure = 1; qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); - if (ql2xmqsupport) { + if (ql2xmqsupport || ql2xnvmeenable) { set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } -- cgit From 2d57b5efda511886daa984d5bb3da29759bb157c Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 13 Oct 2017 15:43:23 -0700 Subject: scsi: qla2xxx: Query FC4 type during RSCN processing Based on the FC4 type, login will proceed to either FCP or FC-NVMe remote ports. Signed-off-by: Giridhar Malavali Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 17fc549aae96..0b33a84f9b9f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4761,7 +4761,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (pla) qlt_plogi_ack_unref(vha, pla); else - qla24xx_async_gnl(vha, fcport); + qla24xx_async_gffid(vha, fcport); } if (free_fcport) { -- cgit From 05231a3bb7981b01f6933c0a847fcaac25622bfd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 3 Oct 2017 12:48:40 +0200 Subject: scsi: qla2xxx: don't break the bsg-lib abstractions Always use bsg_job->reply instead of scsi_req(bsg_job->req)->sense), as they always point to the same memory. Never set scsi_req(bsg_job->req)->result and we'll set that value through bsg_job_done. [mkp: applied by hand, fixed whitespace] Signed-off-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Himanshu Madhani Tested-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 10 ++++------ drivers/scsi/qla2xxx/qla_isr.c | 12 +++--------- drivers/scsi/qla2xxx/qla_mr.c | 3 +-- 3 files changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 451d9709bc06..e3ac7078d2aa 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -919,9 +919,9 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(response) + sizeof(uint8_t); - fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) + - sizeof(struct fc_bsg_reply); - memcpy(fw_sts_ptr, response, sizeof(response)); + fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply); + memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), response, + sizeof(response)); fw_sts_ptr += sizeof(response); *fw_sts_ptr = command_sent; @@ -2553,13 +2553,11 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) ql_log(ql_log_warn, vha, 0x7089, "mbx abort_command " "failed.\n"); - scsi_req(bsg_job->req)->result = bsg_reply->result = -EIO; } else { ql_dbg(ql_dbg_user, vha, 0x708a, "mbx abort_command " "success.\n"); - scsi_req(bsg_job->req)->result = bsg_reply->result = 0; } spin_lock_irqsave(&ha->hardware_lock, flags); @@ -2570,7 +2568,7 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) } spin_unlock_irqrestore(&ha->hardware_lock, flags); ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n"); - scsi_req(bsg_job->req)->result = bsg_reply->result = -ENXIO; + bsg_reply->result = -ENXIO; return 0; done: diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e9b14405e7d4..2fd79129bb2a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1544,7 +1544,6 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, struct fc_bsg_reply *bsg_reply; uint16_t comp_status; uint32_t fw_status[3]; - uint8_t* fw_sts_ptr; int res; struct srb_iocb *els; @@ -1637,11 +1636,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, type, sp->handle, comp_status, fw_status[1], fw_status[2], le16_to_cpu(((struct els_sts_entry_24xx *) pkt)->total_byte_count)); - fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) + - sizeof(struct fc_bsg_reply); - memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); - } - else { + } else { ql_dbg(ql_dbg_user, vha, 0x5040, "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x " "error subcode 1=0x%x error subcode 2=0x%x.\n", @@ -1652,10 +1647,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, pkt)->error_subcode_2)); res = DID_ERROR << 16; bsg_reply->reply_payload_rcv_len = 0; - fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) + - sizeof(struct fc_bsg_reply); - memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); } + memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), + fw_status, sizeof(fw_status)); ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056, (uint8_t *)pkt, sizeof(*pkt)); } diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index e23a3d4c36f3..d5da3981cefe 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -2245,8 +2245,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, memcpy(fstatus.reserved_3, pkt->reserved_2, 20 * sizeof(uint8_t)); - fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) + - sizeof(struct fc_bsg_reply); + fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply); memcpy(fw_sts_ptr, (uint8_t *)&fstatus, sizeof(struct qla_mt_iocb_rsp_fx00)); -- cgit From 8653188763b56e0bcbdcab30cc7b059672c900ac Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 6 Nov 2017 11:59:05 -0800 Subject: scsi: qla2xxx: Suppress a kernel complaint in qla_init_base_qpair() Avoid that the following is reported while loading the qla2xxx kernel module: BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/783 caller is debug_smp_processor_id+0x17/0x20 CPU: 7 PID: 783 Comm: modprobe Not tainted 4.14.0-rc8-dbg+ #2 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Call Trace: dump_stack+0x8e/0xce check_preemption_disabled+0xe3/0xf0 debug_smp_processor_id+0x17/0x20 qla2x00_probe_one+0xf43/0x26c0 [qla2xxx] pci_device_probe+0xca/0x140 driver_probe_device+0x2e2/0x440 __driver_attach+0xa3/0xe0 bus_for_each_dev+0x5f/0x90 driver_attach+0x19/0x20 bus_add_driver+0x1c0/0x260 driver_register+0x5b/0xd0 __pci_register_driver+0x63/0x70 qla2x00_module_init+0x1d6/0x222 [qla2xxx] do_one_initcall+0x3c/0x163 do_init_module+0x55/0x1eb load_module+0x20a2/0x2890 SYSC_finit_module+0xd7/0xf0 SyS_finit_module+0x9/0x10 entry_SYSCALL_64_fastpath+0x23/0xc2 Fixes: commit 8abfa9e22683 ("scsi: qla2xxx: Add function call to qpair for door bell") Signed-off-by: Bart Van Assche Cc: Quinn Tran Cc: Himanshu Madhani Cc: Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/qla2xxx') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0b33a84f9b9f..41e651033fc9 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -397,7 +397,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, INIT_LIST_HEAD(&ha->base_qpair->nvme_done_list); ha->base_qpair->enable_class_2 = ql2xenableclass2; /* init qpair to this cpu. Will adjust at run time. */ - qla_cpu_update(rsp->qpair, smp_processor_id()); + qla_cpu_update(rsp->qpair, raw_smp_processor_id()); ha->base_qpair->pdev = ha->pdev; if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) -- cgit