diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 237 |
1 files changed, 106 insertions, 131 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 98e60a34afd9..73db01e3b4e4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -69,7 +69,7 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice, "a Fabric scan. This is needed for several broken switches. " "Default is 0 - no PLOGI. 1 - perform PLOGI."); -int ql2xloginretrycount = 0; +int ql2xloginretrycount; module_param(ql2xloginretrycount, int, S_IRUGO); MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); @@ -234,7 +234,7 @@ MODULE_PARM_DESC(ql2xmdenable, "0 - MiniDump disabled. " "1 (Default) - MiniDump enabled."); -int ql2xexlogins = 0; +int ql2xexlogins; module_param(ql2xexlogins, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xexlogins, "Number of extended Logins. " @@ -250,7 +250,7 @@ module_param(ql2xiniexchg, uint, 0644); MODULE_PARM_DESC(ql2xiniexchg, "Number of initiator exchanges."); -int ql2xfwholdabts = 0; +int ql2xfwholdabts; module_param(ql2xfwholdabts, int, S_IRUGO); MODULE_PARM_DESC(ql2xfwholdabts, "Allow FW to hold status IOCB until ABTS rsp received. " @@ -536,80 +536,70 @@ static void qla2x00_free_queues(struct qla_hw_data *ha) } static char * -qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str) +qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) { struct qla_hw_data *ha = vha->hw; - static char *pci_bus_modes[] = { + static const char *const pci_bus_modes[] = { "33", "66", "100", "133", }; uint16_t pci_bus; - strcpy(str, "PCI"); pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9; if (pci_bus) { - strcat(str, "-X ("); - strcat(str, pci_bus_modes[pci_bus]); + snprintf(str, str_len, "PCI-X (%s MHz)", + pci_bus_modes[pci_bus]); } else { pci_bus = (ha->pci_attr & BIT_8) >> 8; - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus]); + snprintf(str, str_len, "PCI (%s MHz)", pci_bus_modes[pci_bus]); } - strcat(str, " MHz)"); - return (str); + return str; } static char * -qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str) +qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) { - static char *pci_bus_modes[] = { "33", "66", "100", "133", }; + static const char *const pci_bus_modes[] = { + "33", "66", "100", "133", + }; struct qla_hw_data *ha = vha->hw; uint32_t pci_bus; if (pci_is_pcie(ha->pdev)) { - char lwstr[6]; uint32_t lstat, lspeed, lwidth; + const char *speed_str; pcie_capability_read_dword(ha->pdev, PCI_EXP_LNKCAP, &lstat); lspeed = lstat & PCI_EXP_LNKCAP_SLS; lwidth = (lstat & PCI_EXP_LNKCAP_MLW) >> 4; - strcpy(str, "PCIe ("); switch (lspeed) { case 1: - strcat(str, "2.5GT/s "); + speed_str = "2.5GT/s"; break; case 2: - strcat(str, "5.0GT/s "); + speed_str = "5.0GT/s"; break; case 3: - strcat(str, "8.0GT/s "); + speed_str = "8.0GT/s"; break; default: - strcat(str, "<unknown> "); + speed_str = "<unknown>"; break; } - snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth); - strcat(str, lwstr); + snprintf(str, str_len, "PCIe (%s x%d)", speed_str, lwidth); return str; } - strcpy(str, "PCI"); pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8; - if (pci_bus == 0 || pci_bus == 8) { - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus >> 3]); - } else { - strcat(str, "-X "); - if (pci_bus & BIT_2) - strcat(str, "Mode 2"); - else - strcat(str, "Mode 1"); - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus & ~BIT_2]); - } - strcat(str, " MHz)"); + if (pci_bus == 0 || pci_bus == 8) + snprintf(str, str_len, "PCI (%s MHz)", + pci_bus_modes[pci_bus >> 3]); + else + snprintf(str, str_len, "PCI-X Mode %d (%s MHz)", + pci_bus & 4 ? 2 : 1, + pci_bus_modes[pci_bus & 3]); return str; } @@ -662,13 +652,10 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size) return str; } -void -qla2x00_sp_free_dma(void *ptr) +void qla2x00_sp_free_dma(srb_t *sp) { - srb_t *sp = ptr; struct qla_hw_data *ha = sp->vha->hw; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - void *ctx = GET_CMD_CTX_SP(sp); if (sp->flags & SRB_DMA_VALID) { scsi_dma_unmap(cmd); @@ -681,24 +668,21 @@ qla2x00_sp_free_dma(void *ptr) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } - if (!ctx) - return; - if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, ctx); + qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - struct crc_context *ctx0 = ctx; + struct crc_context *ctx0 = sp->u.scmd.crc_ctx; dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = ctx; + struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); @@ -709,10 +693,8 @@ qla2x00_sp_free_dma(void *ptr) } } -void -qla2x00_sp_compl(void *ptr, int res) +void qla2x00_sp_compl(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct completion *comp = sp->comp; @@ -727,16 +709,12 @@ qla2x00_sp_compl(void *ptr, int res) cmd->scsi_done(cmd); if (comp) complete(comp); - qla2x00_rel_sp(sp); } -void -qla2xxx_qpair_sp_free_dma(void *ptr) +void qla2xxx_qpair_sp_free_dma(srb_t *sp) { - srb_t *sp = (srb_t *)ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct qla_hw_data *ha = sp->fcport->vha->hw; - void *ctx = GET_CMD_CTX_SP(sp); if (sp->flags & SRB_DMA_VALID) { scsi_dma_unmap(cmd); @@ -749,17 +727,14 @@ qla2xxx_qpair_sp_free_dma(void *ptr) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } - if (!ctx) - return; - if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, ctx); + qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) { - struct crc_context *difctx = ctx; + struct crc_context *difctx = sp->u.scmd.crc_ctx; struct dsd_dma *dif_dsd, *nxt_dsd; list_for_each_entry_safe(dif_dsd, nxt_dsd, @@ -795,7 +770,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = ctx; + struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); @@ -807,17 +782,15 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - struct crc_context *ctx0 = ctx; + struct crc_context *ctx0 = sp->u.scmd.crc_ctx; - dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma); + dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } } -void -qla2xxx_qpair_sp_compl(void *ptr, int res) +void qla2xxx_qpair_sp_compl(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct completion *comp = sp->comp; @@ -832,7 +805,6 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) cmd->scsi_done(cmd); if (comp) complete(comp); - qla2xxx_rel_qpair_sp(sp->qpair, sp); } static int @@ -845,9 +817,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); srb_t *sp; int rval; - struct qla_qpair *qpair = NULL; - uint32_t tag; - uint16_t hwq; if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)) || WARN_ON_ONCE(!rport)) { @@ -856,6 +825,10 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) } if (ha->mqenable) { + uint32_t tag; + uint16_t hwq; + struct qla_qpair *qpair = NULL; + tag = blk_mq_unique_tag(cmd->request); hwq = blk_mq_unique_tag_to_hwq(tag); qpair = ha->queue_pair_map[hwq]; @@ -925,9 +898,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) else goto qc24_target_busy; - sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); - if (!sp) - goto qc24_host_busy; + sp = scsi_cmd_priv(cmd); + qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport); sp->u.scmd.cmd = cmd; sp->type = SRB_SCSI_CMD; @@ -948,9 +920,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) qc24_host_busy_free_sp: sp->free(sp); -qc24_host_busy: - return SCSI_MLQUEUE_HOST_BUSY; - qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; @@ -1011,9 +980,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, else goto qc24_target_busy; - sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, GFP_ATOMIC); - if (!sp) - goto qc24_host_busy; + sp = scsi_cmd_priv(cmd); + qla2xxx_init_sp(sp, vha, qpair, fcport); sp->u.scmd.cmd = cmd; sp->type = SRB_SCSI_CMD; @@ -1037,9 +1005,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, qc24_host_busy_free_sp: sp->free(sp); -qc24_host_busy: - return SCSI_MLQUEUE_HOST_BUSY; - qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; @@ -1058,8 +1023,8 @@ qc24_fail_command: * cmd = Scsi Command to wait on. * * Return: - * Not Found : 0 - * Found : 1 + * Completed in time : QLA_SUCCESS + * Did not complete in time : QLA_FUNCTION_FAILED */ static int qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) @@ -1269,14 +1234,13 @@ static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *vha = shost_priv(cmd->device->host); + DECLARE_COMPLETION_ONSTACK(comp); srb_t *sp; int ret; unsigned int id; uint64_t lun; - unsigned long flags; int rval; struct qla_hw_data *ha = vha->hw; - struct qla_qpair *qpair; if (qla2x00_isp_reg_stat(ha)) { ql_log(ql_log_info, vha, 0x8042, @@ -1288,28 +1252,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (ret != 0) return ret; - sp = (srb_t *) CMD_SP(cmd); - if (!sp) - return SUCCESS; - - qpair = sp->qpair; - if (!qpair) - return SUCCESS; + sp = scsi_cmd_priv(cmd); - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { - /* there's a chance an interrupt could clear - the ptr as part of done & free */ - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + if (sp->fcport && sp->fcport->deleted) return SUCCESS; - } - if (sp_get(sp)){ - /* ref_count is already 0 */ - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + /* Return if the command has already finished. */ + if (sp_get(sp)) return SUCCESS; - } - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); id = cmd->device->id; lun = cmd->device->lun; @@ -1331,6 +1281,23 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) sp->done(sp, DID_ABORT << 16); ret = SUCCESS; break; + case QLA_FUNCTION_PARAMETER_ERROR: { + /* Wait for the command completion. */ + uint32_t ratov = ha->r_a_tov/10; + uint32_t ratov_j = msecs_to_jiffies(4 * ratov * 1000); + + WARN_ON_ONCE(sp->comp); + sp->comp = ∁ + if (!wait_for_completion_timeout(&comp, ratov_j)) { + ql_dbg(ql_dbg_taskm, vha, 0xffff, + "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", + __func__, ha->r_a_tov); + ret = FAILED; + } else { + ret = SUCCESS; + } + break; + } default: /* * Either abort failed or abort and completion raced. Let @@ -1340,6 +1307,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) break; } + sp->comp = NULL; + atomic_dec(&sp->ref_count); ql_log(ql_log_info, vha, 0x801c, "Abort command issued nexus=%ld:%d:%llu -- %x.\n", vha->host_no, id, lun, ret); @@ -1347,6 +1316,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } +/* + * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. + */ int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, uint64_t l, enum nexus_wait_type type) @@ -1420,6 +1392,9 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, if (err != 0) return err; + if (fcport->deleted) + return SUCCESS; + ql_log(ql_log_info, vha, 0x8009, "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); @@ -1534,6 +1509,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) return ret; ret = FAILED; + if (qla2x00_chip_is_down(vha)) + return ret; + ql_log(ql_log_info, vha, 0x8012, "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); @@ -1746,6 +1724,8 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, spin_lock_irqsave(qp->qp_lock_ptr, *flags); sp->comp = NULL; } + + atomic_dec(&sp->ref_count); } static void @@ -1800,8 +1780,13 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) int que; struct qla_hw_data *ha = vha->hw; + /* Continue only if initialization complete. */ + if (!ha->base_qpair) + return; __qla2x00_abort_all_cmds(ha->base_qpair, res); + if (!ha->queue_pair_map) + return; for (que = 0; que < ha->max_qpairs; que++) { if (!ha->queue_pair_map[que]) continue; @@ -2477,7 +2462,7 @@ static struct isp_operations qla27xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -3154,6 +3139,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_log(ql_log_fatal, base_vha, 0x003d, "Failed to allocate memory for queue pointers..." "aborting.\n"); + ret = -ENODEV; goto probe_failed; } @@ -3418,7 +3404,8 @@ skip_dpc: "QLogic %s - %s.\n", ha->model_number, ha->model_desc); ql_log(ql_log_info, base_vha, 0x00fc, "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n", - pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info), + pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info, + sizeof(pci_info)), pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no, ha->isp_ops->fw_version_str(base_vha, fw_str, sizeof(fw_str))); @@ -4598,6 +4585,7 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) ha->fce = NULL; ha->fce_dma = 0; + ha->flags.fce_enabled = 0; ha->eft = NULL; ha->eft_dma = 0; ha->fw_dumped = 0; @@ -4716,7 +4704,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) mempool_destroy(ha->ctx_mempool); ha->ctx_mempool = NULL; - if (ql2xenabledif) { + if (ql2xenabledif && ha->dif_bundl_pool) { struct dsd_dma *dsd, *nxt; list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head, @@ -4739,8 +4727,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) } } - if (ha->dif_bundl_pool) - dma_pool_destroy(ha->dif_bundl_pool); + dma_pool_destroy(ha->dif_bundl_pool); ha->dif_bundl_pool = NULL; qlt_mem_free(ha); @@ -4812,7 +4799,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, if (!vha->gnl.l) { ql_log(ql_log_fatal, vha, 0xd04a, "Alloc failed for name list.\n"); - scsi_remove_host(vha->host); + scsi_host_put(vha->host); return NULL; } @@ -4825,7 +4812,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); vha->gnl.l = NULL; - scsi_remove_host(vha->host); + scsi_host_put(vha->host); return NULL; } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); @@ -5054,8 +5041,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) "%s %8phC mem alloc fail.\n", __func__, e->u.new_sess.port_name); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } return; } @@ -5086,6 +5075,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (fcport) { fcport->id_changed = 1; fcport->scan_state = QLA_FCPORT_FOUND; + fcport->chip_reset = vha->hw->base_qpair->chip_reset; memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE); if (pla) { @@ -5165,8 +5155,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (free_fcport) { qla2x00_free_fcport(fcport); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } } } @@ -5346,9 +5338,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha) } else { if (vha->hw->current_topology != ISP_CFG_NL) { memset(&ea, 0, sizeof(ea)); - ea.event = FCME_RELOGIN; ea.fcport = fcport; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_relogin_event(vha, &ea); } else if (vha->hw->current_topology == ISP_CFG_NL) { fcport->login_retry--; @@ -5686,7 +5677,6 @@ exit: void qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id) { - uint16_t options = (requester_id << 15) | BIT_6; uint32_t data; uint32_t lock_owner; struct qla_hw_data *ha = base_vha->hw; @@ -5719,22 +5709,6 @@ retry_lock: } return; - - /* XXX: IDC-lock implementation using access-control mbx */ -retry_lock2: - if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) { - ql_dbg(ql_dbg_p3p, base_vha, 0xb072, - "Failed to acquire IDC lock. retrying...\n"); - /* Retry/Perform IDC-Lock recovery */ - if (qla83xx_idc_lock_recovery(base_vha) == QLA_SUCCESS) { - qla83xx_wait_logic(); - goto retry_lock2; - } else - ql_log(ql_log_warn, base_vha, 0xb076, - "IDC Lock recovery FAILED.\n"); - } - - return; } void @@ -7156,6 +7130,7 @@ struct scsi_host_template qla2xxx_driver_template = { .supported_mode = MODE_INITIATOR, .track_queue_depth = 1, + .cmd_size = sizeof(srb_t), }; static const struct pci_error_handlers qla2xxx_err_handler = { |