diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 13 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 29 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 140 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 195 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 73 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 132 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mr.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 40 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 12 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
13 files changed, 560 insertions, 90 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 2ea0ef93f5cb..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; @@ -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); @@ -2554,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); @@ -2571,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_def.h b/drivers/scsi/qla2xxx/qla_def.h index 486c075998f6..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 @@ -922,6 +941,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 @@ -2302,6 +2322,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; @@ -2347,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; @@ -2368,6 +2390,9 @@ 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; + struct completion n2n_done; } fc_port_t; #define QLA_FCPORT_SCAN 1 @@ -4113,6 +4138,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 */ @@ -4223,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 3ad375f85b59..fa115c7433e5 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 *); @@ -145,6 +147,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); @@ -486,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 44cf875a484a..1bafa043f9f1 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; @@ -1434,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]); @@ -4367,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 @@ -4438,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++) { @@ -4479,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); @@ -7555,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"); @@ -7910,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_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,24 +2535,198 @@ 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) { struct bsg_job *bsg_job = sp->u.bsg_job; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 9d9668aac6f6..2fd79129bb2a 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", @@ -1543,8 +1544,8 @@ 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; sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); if (!sp) @@ -1561,10 +1562,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 +1589,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 */ @@ -1604,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", @@ -1619,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)); } @@ -1631,6 +1658,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); } @@ -3129,6 +3157,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 +3288,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 +3377,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++; } @@ -3374,7 +3405,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 */ @@ -3432,7 +3463,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; @@ -3486,11 +3518,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_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 99502fa90810..cb717d47339f 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1782,13 +1782,13 @@ 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"); + fcport->query = 0; 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)) @@ -1823,17 +1823,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 || @@ -1912,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, @@ -2255,13 +2271,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 +2540,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 +2834,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 +3027,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 +3110,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; @@ -3753,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; @@ -3856,14 +3899,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 +3976,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; @@ -4592,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) { @@ -6025,13 +6108,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; diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index cbf544dbf883..bd9f14bf7ac2 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_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)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 50286cf02eca..46f2d0cf7c0d 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 */ @@ -386,7 +395,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)) @@ -422,7 +431,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) { @@ -1965,7 +1974,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), @@ -2062,7 +2072,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; @@ -3080,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); @@ -4743,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) { @@ -6292,7 +6310,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); } @@ -6309,7 +6327,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); } @@ -6317,7 +6335,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); } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f946bf889015..18069edd4773 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 { 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 |