diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 200 |
1 files changed, 147 insertions, 53 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 563eee3fa924..edf4d14a1335 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2012 QLogic Corporation + * Copyright (c) 2003-2013 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ @@ -70,9 +70,7 @@ qla2x00_sp_free(void *data, void *ptr) struct scsi_qla_host *vha = (scsi_qla_host_t *)data; del_timer(&iocb->timer); - mempool_free(sp, vha->hw->srb_mempool); - - QLA_VHA_MARK_NOT_BUSY(vha); + qla2x00_rel_sp(vha, sp); } /* Asynchronous Login/Logout Routines -------------------------------------- */ @@ -525,7 +523,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) vha->flags.reset_active = 0; ha->flags.pci_channel_io_perm_failure = 0; ha->flags.eeh_busy = 0; - ha->flags.thermal_supported = 1; + ha->thermal_support = THERMAL_SUPPORT_I2C|THERMAL_SUPPORT_ISP; atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&vha->loop_state, LOOP_DOWN); vha->device_flags = DFLG_NO_CABLE; @@ -621,6 +619,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) qla24xx_read_fcp_prio_cfg(vha); + qla2x00_set_driver_version(vha, QLA2XXX_VERSION); + return (rval); } @@ -1559,6 +1559,47 @@ done: return rval; } +int +qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req) +{ + /* Don't try to reallocate the array */ + if (req->outstanding_cmds) + return QLA_SUCCESS; + + if (!IS_FWI2_CAPABLE(ha) || (ha->mqiobase && + (ql2xmultique_tag || ql2xmaxqueues > 1))) + req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS; + else { + if (ha->fw_xcb_count <= ha->fw_iocb_count) + req->num_outstanding_cmds = ha->fw_xcb_count; + else + req->num_outstanding_cmds = ha->fw_iocb_count; + } + + req->outstanding_cmds = kzalloc(sizeof(srb_t *) * + req->num_outstanding_cmds, GFP_KERNEL); + + if (!req->outstanding_cmds) { + /* + * Try to allocate a minimal size just so we can get through + * initialization. + */ + req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS; + req->outstanding_cmds = kzalloc(sizeof(srb_t *) * + req->num_outstanding_cmds, GFP_KERNEL); + + if (!req->outstanding_cmds) { + ql_log(ql_log_fatal, NULL, 0x0126, + "Failed to allocate memory for " + "outstanding_cmds for req_que %p.\n", req); + req->num_outstanding_cmds = 0; + return QLA_FUNCTION_FAILED; + } + } + + return QLA_SUCCESS; +} + /** * qla2x00_setup_chip() - Load and start RISC firmware. * @ha: HA context @@ -1628,9 +1669,18 @@ enable_82xx_npiv: MIN_MULTI_ID_FABRIC - 1; } qla2x00_get_resource_cnts(vha, NULL, - &ha->fw_xcb_count, NULL, NULL, + &ha->fw_xcb_count, NULL, &ha->fw_iocb_count, &ha->max_npiv_vports, NULL); + /* + * Allocate the array of outstanding commands + * now that we know the firmware resources. + */ + rval = qla2x00_alloc_outstanding_cmds(ha, + vha->req); + if (rval != QLA_SUCCESS) + goto failed; + if (!fw_major_version && ql2xallocfwdump && !IS_QLA82XX(ha)) qla2x00_alloc_fw_dump(vha); @@ -1914,7 +1964,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha) WRT_REG_DWORD(®->isp24.rsp_q_in, 0); WRT_REG_DWORD(®->isp24.rsp_q_out, 0); } - qlt_24xx_config_rings(vha, reg); + qlt_24xx_config_rings(vha); /* PCI posting */ RD_REG_DWORD(&ioreg->hccr); @@ -1948,7 +1998,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha) req = ha->req_q_map[que]; if (!req) continue; - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) req->outstanding_cmds[cnt] = NULL; req->current_outstanding_cmd = 1; @@ -2157,6 +2207,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) char connect_type[22]; struct qla_hw_data *ha = vha->hw; unsigned long flags; + scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); /* Get host addresses. */ rval = qla2x00_get_adapter_id(vha, @@ -2170,6 +2221,13 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) } else { ql_log(ql_log_warn, vha, 0x2009, "Unable to get host loop ID.\n"); + if (IS_FWI2_CAPABLE(ha) && (vha == base_vha) && + (rval == QLA_COMMAND_ERROR && loop_id == 0x1b)) { + ql_log(ql_log_warn, vha, 0x1151, + "Doing link init.\n"); + if (qla24xx_link_initialize(vha) == QLA_SUCCESS) + return rval; + } set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } return (rval); @@ -2690,7 +2748,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) fcport->loop_id = FC_NO_LOOP_ID; qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); fcport->supported_classes = FC_COS_UNSPECIFIED; - fcport->scan_state = QLA_FCPORT_SCAN_NONE; return fcport; } @@ -3103,7 +3160,7 @@ static int qla2x00_configure_fabric(scsi_qla_host_t *vha) { int rval; - fc_port_t *fcport; + fc_port_t *fcport, *fcptemp; uint16_t next_loopid; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; @@ -3141,7 +3198,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) 0xfc, mb, BIT_1|BIT_0); if (rval != QLA_SUCCESS) { set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - break; + return rval; } if (mb[0] != MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_disc, vha, 0x2042, @@ -3173,16 +3230,21 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) } } +#define QLA_FCPORT_SCAN 1 +#define QLA_FCPORT_FOUND 2 + + list_for_each_entry(fcport, &vha->vp_fcports, list) { + fcport->scan_state = QLA_FCPORT_SCAN; + } + rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); if (rval != QLA_SUCCESS) break; - /* Add new ports to existing port list */ - list_splice_tail_init(&new_fcports, &vha->vp_fcports); - - /* Starting free loop ID. */ - next_loopid = ha->min_external_loopid; - + /* + * Logout all previous fabric devices marked lost, except + * FCP2 devices. + */ list_for_each_entry(fcport, &vha->vp_fcports, list) { if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; @@ -3190,8 +3252,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) continue; - /* Logout lost/gone fabric devices (non-FCP2) */ - if (fcport->scan_state != QLA_FCPORT_SCAN_FOUND && + if (fcport->scan_state == QLA_FCPORT_SCAN && atomic_read(&fcport->state) == FCS_ONLINE) { qla2x00_mark_device_lost(vha, fcport, ql2xplogiabsentdevice, 0); @@ -3204,30 +3265,74 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); + fcport->loop_id = FC_NO_LOOP_ID; } - continue; } - fcport->scan_state = QLA_FCPORT_SCAN_NONE; - - /* Login fabric devices that need a login */ - if ((fcport->flags & FCF_LOGIN_NEEDED) != 0 && - atomic_read(&vha->loop_down_timer) == 0) { - if (fcport->loop_id == FC_NO_LOOP_ID) { - fcport->loop_id = next_loopid; - rval = qla2x00_find_new_loop_id( - base_vha, fcport); - if (rval != QLA_SUCCESS) { - /* Ran out of IDs to use */ - continue; - } + } + + /* Starting free loop ID. */ + next_loopid = ha->min_external_loopid; + + /* + * Scan through our port list and login entries that need to be + * logged in. + */ + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) + break; + + if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || + (fcport->flags & FCF_LOGIN_NEEDED) == 0) + continue; + + if (fcport->loop_id == FC_NO_LOOP_ID) { + fcport->loop_id = next_loopid; + rval = qla2x00_find_new_loop_id( + base_vha, fcport); + if (rval != QLA_SUCCESS) { + /* Ran out of IDs to use */ + break; } } + /* Login and update database */ + qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + } + + /* Exit if out of loop IDs. */ + if (rval != QLA_SUCCESS) { + break; + } + + /* + * Login and add the new devices to our port list. + */ + list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) + break; + + /* Find a new loop ID to use. */ + fcport->loop_id = next_loopid; + rval = qla2x00_find_new_loop_id(base_vha, fcport); + if (rval != QLA_SUCCESS) { + /* Ran out of IDs to use */ + break; + } /* Login and update database */ qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + + list_move_tail(&fcport->list, &vha->vp_fcports); } } while (0); + /* Free all new device structures not processed. */ + list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { + list_del(&fcport->list); + kfree(fcport); + } + if (rval) { ql_dbg(ql_dbg_disc, vha, 0x2068, "Configure fabric error exit rval=%d.\n", rval); @@ -3263,8 +3368,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, int first_dev, last_dev; port_id_t wrap = {}, nxt_d_id; struct qla_hw_data *ha = vha->hw; - struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); - struct scsi_qla_host *tvp; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); rval = QLA_SUCCESS; @@ -3377,22 +3481,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, continue; /* Bypass virtual ports of the same host. */ - found = 0; - if (ha->num_vhosts) { - unsigned long flags; - - spin_lock_irqsave(&ha->vport_slock, flags); - list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { - if (new_fcport->d_id.b24 == vp->d_id.b24) { - found = 1; - break; - } - } - spin_unlock_irqrestore(&ha->vport_slock, flags); - - if (found) - continue; - } + if (qla2x00_is_a_vp_did(vha, new_fcport->d_id.b24)) + continue; /* Bypass if same domain and area of adapter. */ if (((new_fcport->d_id.b24 & 0xffff00) == @@ -3417,7 +3507,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, WWN_SIZE)) continue; - fcport->scan_state = QLA_FCPORT_SCAN_FOUND; + fcport->scan_state = QLA_FCPORT_FOUND; found++; @@ -5004,7 +5094,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, return rval; } -#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" +#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/" int qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) @@ -5529,6 +5619,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (IS_T10_PI_CAPABLE(ha)) nv->frame_payload_size &= ~7; + qlt_81xx_config_nvram_stage1(vha, nv); + /* Reset Initialization control block */ memset(icb, 0, ha->init_cb_size); @@ -5569,6 +5661,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), "QLE8XXX"); + qlt_81xx_config_nvram_stage2(vha, icb); + /* Use alternate WWN? */ if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); |