diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 155 |
1 files changed, 132 insertions, 23 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index df57655779ed..5b2437a5ea44 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -113,12 +113,12 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registrations. " "0 - no FDMI. Default is 1 - perform FDMI."); -#define MAX_Q_DEPTH 32 +#define MAX_Q_DEPTH 64 static int ql2xmaxqdepth = MAX_Q_DEPTH; module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xmaxqdepth, "Maximum queue depth to set for each LUN. " - "Default is 32."); + "Default is 64."); #if (IS_ENABLED(CONFIG_NVME_FC)) int ql2xenabledif; @@ -200,7 +200,7 @@ MODULE_PARM_DESC(ql2xgffidenable, "Enables GFF_ID checks of port type. " "Default is 0 - Do not use GFF_ID information."); -int ql2xasynctmfenable; +int ql2xasynctmfenable = 1; module_param(ql2xasynctmfenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xasynctmfenable, "Enables issue of TM IOCBs asynchronously via IOCB mechanism" @@ -262,6 +262,12 @@ MODULE_PARM_DESC(ql2xmvasynctoatio, "0 (Default). Do not move IOCBs" "1 - Move IOCBs."); +int ql2xautodetectsfp = 1; +module_param(ql2xautodetectsfp, int, 0444); +MODULE_PARM_DESC(ql2xautodetectsfp, + "Detect SFP range and set appropriate distance.\n" + "1 (Default): Enable\n"); + /* * SCSI host template entry points */ @@ -379,6 +385,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, ha->base_qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0; ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q]; INIT_LIST_HEAD(&ha->base_qpair->hints_list); + 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()); @@ -710,7 +717,7 @@ qla2x00_sp_free_dma(void *ptr) } end: - if ((sp->type != SRB_NVME_CMD) && (sp->type != SRB_NVME_LS)) { + if (sp->type != SRB_NVME_CMD && sp->type != SRB_NVME_LS) { CMD_SP(cmd) = NULL; qla2x00_rel_sp(sp); } @@ -735,7 +742,7 @@ qla2x00_sp_compl(void *ptr, int res) if (!atomic_dec_and_test(&sp->ref_count)) return; - qla2x00_sp_free_dma(sp); + sp->free(sp); cmd->scsi_done(cmd); } @@ -807,7 +814,7 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) if (!atomic_dec_and_test(&sp->ref_count)) return; - qla2xxx_qpair_sp_free_dma(sp); + sp->free(sp); cmd->scsi_done(cmd); } @@ -928,7 +935,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) return 0; qc24_host_busy_free_sp: - qla2x00_sp_free_dma(sp); + sp->free(sp); qc24_host_busy: return SCSI_MLQUEUE_HOST_BUSY; @@ -1017,7 +1024,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, return 0; qc24_host_busy_free_sp: - qla2xxx_qpair_sp_free_dma(sp); + sp->free(sp); qc24_host_busy: return SCSI_MLQUEUE_HOST_BUSY; @@ -1134,7 +1141,7 @@ qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha) { qla2x00_mark_all_devices_lost(vha, 0); - wait_event(vha->fcport_waitQ, test_fcport_count(vha)); + wait_event_timeout(vha->fcport_waitQ, test_fcport_count(vha), 10*HZ); } /* @@ -1715,8 +1722,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) if (sp) { req->outstanding_cmds[cnt] = NULL; if (sp->cmd_type == TYPE_SRB) { - if ((sp->type == SRB_NVME_CMD) || - (sp->type == SRB_NVME_LS)) { + if (sp->type == SRB_NVME_CMD || + sp->type == SRB_NVME_LS) { sp_get(sp); spin_unlock_irqrestore( &ha->hardware_lock, flags); @@ -1725,6 +1732,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) &ha->hardware_lock, flags); } else if (GET_CMD_SP(sp) && !ha->flags.eeh_busy && + (!test_bit(ABORT_ISP_ACTIVE, + &vha->dpc_flags)) && (sp->type == SRB_SCSI_CMD)) { /* * Don't abort commands in @@ -2751,6 +2760,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&ha->tgt.sess_lock); spin_lock_init(&ha->tgt.atio_lock); + atomic_set(&ha->nvme_active_aen_cnt, 0); /* Clear our data area */ ha->bars = bars; @@ -3168,7 +3178,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ha->mqenable) { bool mq = false; bool startit = false; - ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); + ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0); if (QLA_TGT_MODE_ENABLED()) { mq = true; @@ -3328,6 +3338,13 @@ skip_dpc: if (test_bit(UNLOADING, &base_vha->dpc_flags)) return -ENODEV; + if (ha->flags.detected_lr_sfp) { + ql_log(ql_log_info, base_vha, 0xffff, + "Reset chip to pick up LR SFP setting\n"); + set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + qla2xxx_wake_dpc(base_vha); + } + return 0; probe_init_failed: @@ -3383,12 +3400,22 @@ qla2x00_shutdown(struct pci_dev *pdev) scsi_qla_host_t *vha; struct qla_hw_data *ha; - if (!atomic_read(&pdev->enable_cnt)) - return; - vha = pci_get_drvdata(pdev); ha = vha->hw; + ql_log(ql_log_info, vha, 0xfffa, + "Adapter shutdown\n"); + + /* + * Prevent future board_disable and wait + * until any pending board_disable has completed. + */ + set_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags); + cancel_work_sync(&ha->board_disable); + + if (!atomic_read(&pdev->enable_cnt)) + return; + /* Notify ISPFX00 firmware */ if (IS_QLAFX00(ha)) qlafx00_driver_shutdown(vha, 20); @@ -3419,8 +3446,9 @@ qla2x00_shutdown(struct pci_dev *pdev) qla2x00_free_fw_dump(ha); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); + ql_log(ql_log_info, vha, 0xfffe, + "Adapter shutdown successfully.\n"); } /* Deletes all the virtual ports for a given ha */ @@ -4006,8 +4034,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, "loop_id_map=%p.\n", ha->loop_id_map); } + ha->sfp_data = dma_alloc_coherent(&ha->pdev->dev, + SFP_DEV_SIZE, &ha->sfp_data_dma, GFP_KERNEL); + if (!ha->sfp_data) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, + "Unable to allocate memory for SFP read-data.\n"); + goto fail_sfp_data; + } + return 0; +fail_sfp_data: + kfree(ha->loop_id_map); fail_loop_id_map: dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); fail_async_pd: @@ -4345,7 +4383,8 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->ct_sns, ha->ct_sns_dma); if (ha->sfp_data) - dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma); + dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data, + ha->sfp_data_dma); if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); @@ -4638,9 +4677,10 @@ static void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) { unsigned long flags; - fc_port_t *fcport = NULL; + fc_port_t *fcport = NULL, *tfcp; struct qlt_plogi_ack_t *pla = (struct qlt_plogi_ack_t *)e->u.new_sess.pla; + uint8_t free_fcport = 0; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1); @@ -4655,6 +4695,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) pla->ref_count--; } } else { + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (fcport) { fcport->d_id = e->u.new_sess.id; @@ -4664,6 +4705,29 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) memcpy(fcport->port_name, e->u.new_sess.port_name, WWN_SIZE); + } else { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %8phC mem alloc fail.\n", + __func__, e->u.new_sess.port_name); + + if (pla) + kmem_cache_free(qla_tgt_plogi_cachep, pla); + return; + } + + spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + /* search again to make sure one else got ahead */ + tfcp = qla2x00_find_fcport_by_wwpn(vha, + e->u.new_sess.port_name, 1); + if (tfcp) { + /* should rarily happen */ + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %8phC found existing fcport b4 add. DS %d LS %d\n", + __func__, tfcp->port_name, tfcp->disc_state, + tfcp->fw_login_state); + + free_fcport = 1; + } else { list_add_tail(&fcport->list, &vha->vp_fcports); if (pla) { @@ -4681,6 +4745,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) else qla24xx_async_gnl(vha, fcport); } + + if (free_fcport) { + qla2x00_free_fcport(fcport); + if (pla) + kmem_cache_free(qla_tgt_plogi_cachep, pla); + } } void @@ -5493,6 +5563,13 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) ql_log(ql_log_warn, base_vha, 0x015b, "Disabling adapter.\n"); + if (!atomic_read(&pdev->enable_cnt)) { + ql_log(ql_log_info, base_vha, 0xfffc, + "PCI device disabled, no action req for PCI error=%lx\n", + base_vha->pci_flags); + return; + } + qla2x00_wait_for_sess_deletion(base_vha); set_bit(UNLOADING, &base_vha->dpc_flags); @@ -5687,6 +5764,16 @@ qla2x00_do_dpc(void *data) } } + if (test_and_clear_bit(DETECT_SFP_CHANGE, + &base_vha->dpc_flags) && + !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { + qla24xx_detect_sfp(base_vha); + + if (ha->flags.detected_lr_sfp != + ha->flags.using_lr_setting) + set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + } + if (test_and_clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { @@ -5828,6 +5915,17 @@ intr_on_check: mutex_unlock(&ha->mq_lock); } + if (test_and_clear_bit(SET_ZIO_THRESHOLD_NEEDED, &base_vha->dpc_flags)) { + ql_log(ql_log_info, base_vha, 0xffffff, + "nvme: SET ZIO Activity exchange threshold to %d.\n", + ha->nvme_last_rptd_aen); + if (qla27xx_set_zio_threshold(base_vha, ha->nvme_last_rptd_aen)) { + ql_log(ql_log_info, base_vha, 0xffffff, + "nvme: Unable to SET ZIO Activity exchange threshold to %d.\n", + ha->nvme_last_rptd_aen); + } + } + if (!IS_QLAFX00(ha)) qla2x00_do_dpc_all_vps(base_vha); @@ -6025,12 +6123,15 @@ qla2x00_timer(scsi_qla_host_t *vha) * FC-NVME * see if the active AEN count has changed from what was last reported. */ - if (atomic_read(&vha->nvme_active_aen_cnt) != vha->nvme_last_rptd_aen) { - vha->nvme_last_rptd_aen = - atomic_read(&vha->nvme_active_aen_cnt); + if (!vha->vp_idx && + atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen && + ha->zio_mode == QLA_ZIO_MODE_6) { ql_log(ql_log_info, vha, 0x3002, - "reporting new aen count of %d to the fw\n", - vha->nvme_last_rptd_aen); + "nvme: Sched: Set ZIO exchange threshold to %d.\n", + ha->nvme_last_rptd_aen); + ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt); + set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags); + start_dpc++; } /* Schedule the DPC routine if needed */ @@ -6181,6 +6282,12 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) ql_dbg(ql_dbg_aer, vha, 0x9000, "PCI error detected, state %x.\n", state); + if (!atomic_read(&pdev->enable_cnt)) { + ql_log(ql_log_info, vha, 0xffff, + "PCI device is disabled,state %x\n", state); + return PCI_ERS_RESULT_NEED_RESET; + } + switch (state) { case pci_channel_io_normal: ha->flags.eeh_busy = 0; @@ -6574,6 +6681,8 @@ qla2x00_module_init(void) strcpy(qla2x00_version_str, QLA2XXX_VERSION); if (ql2xextended_error_logging) strcat(qla2x00_version_str, "-debug"); + if (ql2xextended_error_logging == 1) + ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK; qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); |