diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 212 |
1 files changed, 200 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ccb5e6404d09..5307bf86d5e0 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -47,6 +47,7 @@ MODULE_PARM_DESC(ql2xenableclass2, "Specify if Class 2 operations are supported from the very " "beginning. Default is 0 - class 2 not supported."); + int ql2xlogintimeout = 20; module_param(ql2xlogintimeout, int, S_IRUGO); MODULE_PARM_DESC(ql2xlogintimeout, @@ -354,7 +355,12 @@ fail_req_map: static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) { - if (req && req->ring) + if (IS_QLAFX00(ha)) { + if (req && req->ring_fx00) + dma_free_coherent(&ha->pdev->dev, + (req->length_fx00 + 1) * sizeof(request_t), + req->ring_fx00, req->dma_fx00); + } else if (req && req->ring) dma_free_coherent(&ha->pdev->dev, (req->length + 1) * sizeof(request_t), req->ring, req->dma); @@ -368,11 +374,16 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp) { - if (rsp && rsp->ring) + if (IS_QLAFX00(ha)) { + if (rsp && rsp->ring) + dma_free_coherent(&ha->pdev->dev, + (rsp->length_fx00 + 1) * sizeof(request_t), + rsp->ring_fx00, rsp->dma_fx00); + } else if (rsp && rsp->ring) { dma_free_coherent(&ha->pdev->dev, (rsp->length + 1) * sizeof(response_t), rsp->ring, rsp->dma); - + } kfree(rsp); rsp = NULL; } @@ -633,7 +644,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr) qla2x00_rel_sp(sp->fcport->vha, sp); } -static void +void qla2x00_sp_compl(void *data, void *ptr, int res) { struct qla_hw_data *ha = (struct qla_hw_data *)data; @@ -657,6 +668,9 @@ qla2x00_sp_compl(void *data, void *ptr, int res) cmd->scsi_done(cmd); } +/* If we are SP1 here, we need to still take and release the host_lock as SP1 + * does not have the changes necessary to avoid taking host->host_lock. + */ static int qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) { @@ -1304,6 +1318,9 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) } } + if (IS_QLAFX00(ha)) + return QLA_SUCCESS; + if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) { atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); @@ -1858,6 +1875,7 @@ static struct isp_operations qla2100_isp_ops = { .start_scsi = qla2x00_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla2x00_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla2300_isp_ops = { @@ -1895,6 +1913,7 @@ static struct isp_operations qla2300_isp_ops = { .start_scsi = qla2x00_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla2x00_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla24xx_isp_ops = { @@ -1932,6 +1951,7 @@ static struct isp_operations qla24xx_isp_ops = { .start_scsi = qla24xx_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla2x00_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla25xx_isp_ops = { @@ -1969,6 +1989,7 @@ static struct isp_operations qla25xx_isp_ops = { .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla2x00_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla81xx_isp_ops = { @@ -2006,6 +2027,7 @@ static struct isp_operations qla81xx_isp_ops = { .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla2x00_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla82xx_isp_ops = { @@ -2043,6 +2065,7 @@ static struct isp_operations qla82xx_isp_ops = { .start_scsi = qla82xx_start_scsi, .abort_isp = qla82xx_abort_isp, .iospace_config = qla82xx_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, }; static struct isp_operations qla83xx_isp_ops = { @@ -2080,6 +2103,45 @@ static struct isp_operations qla83xx_isp_ops = { .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, .iospace_config = qla83xx_iospace_config, + .initialize_adapter = qla2x00_initialize_adapter, +}; + +static struct isp_operations qlafx00_isp_ops = { + .pci_config = qlafx00_pci_config, + .reset_chip = qlafx00_soft_reset, + .chip_diag = qlafx00_chip_diag, + .config_rings = qlafx00_config_rings, + .reset_adapter = qlafx00_soft_reset, + .nvram_config = NULL, + .update_fw_options = NULL, + .load_risc = NULL, + .pci_info_str = qlafx00_pci_info_str, + .fw_version_str = qlafx00_fw_version_str, + .intr_handler = qlafx00_intr_handler, + .enable_intrs = qlafx00_enable_intrs, + .disable_intrs = qlafx00_disable_intrs, + .abort_command = qlafx00_abort_command, + .target_reset = qlafx00_abort_target, + .lun_reset = qlafx00_lun_reset, + .fabric_login = NULL, + .fabric_logout = NULL, + .calc_req_entries = NULL, + .build_iocbs = NULL, + .prep_ms_iocb = qla24xx_prep_ms_iocb, + .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, + .read_nvram = qla24xx_read_nvram_data, + .write_nvram = qla24xx_write_nvram_data, + .fw_dump = NULL, + .beacon_on = qla24xx_beacon_on, + .beacon_off = qla24xx_beacon_off, + .beacon_blink = NULL, + .read_optrom = qla24xx_read_optrom_data, + .write_optrom = qla24xx_write_optrom_data, + .get_flash_version = qla24xx_get_flash_version, + .start_scsi = qlafx00_start_scsi, + .abort_isp = qlafx00_abort_isp, + .iospace_config = qlafx00_iospace_config, + .initialize_adapter = qlafx00_initialize_adapter, }; static inline void @@ -2192,6 +2254,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; + case PCI_DEVICE_ID_QLOGIC_ISPF001: + ha->device_type |= DT_ISPFX00; + break; } if (IS_QLA82XX(ha)) @@ -2265,7 +2330,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 || - pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031) { + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001) { bars = pci_select_bars(pdev, IORESOURCE_MEM); mem_only = 1; ql_dbg_pci(ql_dbg_init, pdev, 0x0007, @@ -2436,6 +2502,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; ha->nvram_conf_off = ~0; ha->nvram_data_off = ~0; + } else if (IS_QLAFX00(ha)) { + ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00; + ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00; + ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00; + req_length = REQUEST_ENTRY_CNT_FX00; + rsp_length = RESPONSE_ENTRY_CNT_FX00; + ha->init_cb_size = sizeof(struct init_cb_fx); + ha->isp_ops = &qlafx00_isp_ops; + ha->port_down_retry_count = 30; /* default value */ + ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL; + ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; + ha->mr.fw_hbt_en = 1; } ql_dbg_pci(ql_dbg_init, pdev, 0x001e, @@ -2500,13 +2578,24 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host = base_vha->host; base_vha->req = req; - host->can_queue = req->length + 128; + if (IS_QLAFX00(ha)) + host->can_queue = 1024; + else + host->can_queue = req->length + 128; if (IS_QLA2XXX_MIDTYPE(ha)) base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx; else base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER + base_vha->vp_idx; + /* Setup fcport template structure. */ + ha->mr.fcport.vha = base_vha; + ha->mr.fcport.port_type = FCT_UNKNOWN; + ha->mr.fcport.loop_id = FC_NO_LOOP_ID; + qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED); + ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED; + ha->mr.fcport.scan_state = 1; + /* Set the SG table size based on ISP type */ if (!IS_FWI2_CAPABLE(ha)) { if (IS_QLA2100(ha)) @@ -2562,6 +2651,13 @@ que_init: rsp->req = req; req->rsp = rsp; + if (IS_QLAFX00(ha)) { + ha->rsp_q_map[0] = rsp; + ha->req_q_map[0] = req; + set_bit(0, ha->req_qid_map); + set_bit(0, ha->rsp_qid_map); + } + /* FWI2-capable only. */ req->req_q_in = &ha->iobase->isp24.req_q_in; req->req_q_out = &ha->iobase->isp24.req_q_out; @@ -2574,6 +2670,13 @@ que_init: rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out; } + if (IS_QLAFX00(ha)) { + req->req_q_in = &ha->iobase->ispfx00.req_q_in; + req->req_q_out = &ha->iobase->ispfx00.req_q_out; + rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in; + rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out; + } + if (IS_QLA82XX(ha)) { req->req_q_out = &ha->iobase->isp82.req_q_out[0]; rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0]; @@ -2595,7 +2698,7 @@ que_init: "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); - if (qla2x00_initialize_adapter(base_vha)) { + if (ha->isp_ops->initialize_adapter(base_vha)) { ql_log(ql_log_fatal, base_vha, 0x00d6, "Failed to initialize adapter - Adapter flags %x.\n", base_vha->device_flags); @@ -2720,6 +2823,18 @@ skip_dpc: qla2x00_alloc_sysfs_attr(base_vha); + if (IS_QLAFX00(ha)) { + ret = qlafx00_fx_disc(base_vha, + &base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO); + + ret = qlafx00_fx_disc(base_vha, + &base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO); + + /* Register system information */ + ret = qlafx00_fx_disc(base_vha, + &base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO); + } + qla2x00_init_host_attr(base_vha); qla2x00_dfs_setup(base_vha); @@ -2777,6 +2892,8 @@ iospace_config_failed: } else { if (ha->iobase) iounmap(ha->iobase); + if (ha->cregbase) + iounmap(ha->cregbase); } pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); @@ -2960,6 +3077,9 @@ qla2x00_remove_one(struct pci_dev *pdev) if (ha->iobase) iounmap(ha->iobase); + if (ha->cregbase) + iounmap(ha->cregbase); + if (ha->mqiobase) iounmap(ha->mqiobase); @@ -3068,6 +3188,12 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, int do_login, int defer) { + if (IS_QLAFX00(vha->hw)) { + qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); + qla2x00_schedule_rport_del(vha, fcport, defer); + return; + } + if (atomic_read(&fcport->state) == FCS_ONLINE && vha->vp_idx == fcport->vha->vp_idx) { qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); @@ -3710,6 +3836,22 @@ qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code) kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp); } +int +qlafx00_post_aenfx_work(struct scsi_qla_host *vha, uint32_t evtcode, + uint32_t *data, int cnt) +{ + struct qla_work_evt *e; + + e = qla2x00_alloc_work(vha, QLA_EVT_AENFX); + if (!e) + return QLA_FUNCTION_FAILED; + + e->u.aenfx.evtcode = evtcode; + e->u.aenfx.count = cnt; + memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt); + return qla2x00_post_work(vha, e); +} + void qla2x00_do_work(struct scsi_qla_host *vha) { @@ -3758,6 +3900,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) case QLA_EVT_UEVENT: qla2x00_uevent_emit(vha, e->u.uevent.code); break; + case QLA_EVT_AENFX: + qlafx00_process_aen(vha, e); + break; } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); @@ -4592,6 +4737,38 @@ qla2x00_do_dpc(void *data) ql_dbg(ql_dbg_dpc, base_vha, 0x4006, "FCoE context reset end.\n"); } + } else if (IS_QLAFX00(ha)) { + if (test_and_clear_bit(ISP_UNRECOVERABLE, + &base_vha->dpc_flags)) { + ql_dbg(ql_dbg_dpc, base_vha, 0x4020, + "Firmware Reset Recovery\n"); + if (qlafx00_reset_initialize(base_vha)) { + /* Failed. Abort isp later. */ + if (!test_bit(UNLOADING, + &base_vha->dpc_flags)) + set_bit(ISP_UNRECOVERABLE, + &base_vha->dpc_flags); + ql_dbg(ql_dbg_dpc, base_vha, + 0x4021, + "Reset Recovery Failed\n"); + } + } + + if (test_and_clear_bit(FX00_TARGET_SCAN, + &base_vha->dpc_flags)) { + ql_dbg(ql_dbg_dpc, base_vha, 0x4022, + "ISPFx00 Target Scan scheduled\n"); + if (qlafx00_rescan_isp(base_vha)) { + if (!test_bit(UNLOADING, + &base_vha->dpc_flags)) + set_bit(ISP_UNRECOVERABLE, + &base_vha->dpc_flags); + ql_dbg(ql_dbg_dpc, base_vha, 0x401e, + "ISPFx00 Target Scan Failed\n"); + } + ql_dbg(ql_dbg_dpc, base_vha, 0x401f, + "ISPFx00 Target Scan End\n"); + } } if (test_and_clear_bit(ISP_ABORT_NEEDED, @@ -4630,6 +4807,9 @@ qla2x00_do_dpc(void *data) clear_bit(SCR_PENDING, &base_vha->dpc_flags); } + if (IS_QLAFX00(ha)) + goto loop_resync_check; + if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, base_vha, 0x4009, "Quiescence mode scheduled.\n"); @@ -4654,7 +4834,7 @@ qla2x00_do_dpc(void *data) } if (test_and_clear_bit(RESET_MARKER_NEEDED, - &base_vha->dpc_flags) && + &base_vha->dpc_flags) && (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) { ql_dbg(ql_dbg_dpc, base_vha, 0x400b, @@ -4677,9 +4857,9 @@ qla2x00_do_dpc(void *data) ql_dbg(ql_dbg_dpc, base_vha, 0x400e, "Relogin end.\n"); } - +loop_resync_check: if (test_and_clear_bit(LOOP_RESYNC_NEEDED, - &base_vha->dpc_flags)) { + &base_vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, base_vha, 0x400f, "Loop resync scheduled.\n"); @@ -4697,6 +4877,9 @@ qla2x00_do_dpc(void *data) "Loop resync end.\n"); } + if (IS_QLAFX00(ha)) + goto intr_on_check; + if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) && atomic_read(&base_vha->loop_state) == LOOP_READY) { clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags); @@ -4714,7 +4897,7 @@ qla2x00_do_dpc(void *data) if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH, &base_vha->dpc_flags)) qla2x00_host_ramp_up_queuedepth(base_vha); - +intr_on_check: if (!ha->interrupts_on) ha->isp_ops->enable_intrs(ha); @@ -4722,7 +4905,8 @@ qla2x00_do_dpc(void *data) &base_vha->dpc_flags)) ha->isp_ops->beacon_blink(base_vha); - qla2x00_do_dpc_all_vps(base_vha); + if (!IS_QLAFX00(ha)) + qla2x00_do_dpc_all_vps(base_vha); ha->dpc_active = 0; end_loop: @@ -4818,6 +5002,9 @@ qla2x00_timer(scsi_qla_host_t *vha) qla82xx_watchdog(vha); } + if (!vha->vp_idx && IS_QLAFX00(ha)) + qlafx00_timer_routine(vha); + /* Loop down handler. */ if (atomic_read(&vha->loop_down_timer) > 0 && !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) && @@ -5335,6 +5522,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); |