diff options
author | Giridhar Malavali <giridhar.malavali@qlogic.com> | 2010-04-12 20:59:55 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-05-01 15:11:17 -0400 |
commit | a9083016a5314b3aeba6e0d2e814872e72168c08 (patch) | |
tree | 5b8dbdfe6abfe1c452dc6684ed81eea65edc1a28 /drivers/scsi/qla2xxx/qla_init.c | |
parent | c446c1f9907e84d014edb0bf3501f30cb512e06a (diff) |
[SCSI] qla2xxx: Add ISP82XX support.
Enhanced the driver to support new FCoE host bus adapter.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 233 |
1 files changed, 207 insertions, 26 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 8517aa49744a..55540d2d4e38 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -328,6 +328,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
328 | if (rval) | 328 | if (rval) |
329 | return (rval); | 329 | return (rval); |
330 | } | 330 | } |
331 | |||
331 | if (IS_QLA84XX(ha)) { | 332 | if (IS_QLA84XX(ha)) { |
332 | ha->cs84xx = qla84xx_get_chip(vha); | 333 | ha->cs84xx = qla84xx_get_chip(vha); |
333 | if (!ha->cs84xx) { | 334 | if (!ha->cs84xx) { |
@@ -961,6 +962,9 @@ qla24xx_chip_diag(scsi_qla_host_t *vha) | |||
961 | struct qla_hw_data *ha = vha->hw; | 962 | struct qla_hw_data *ha = vha->hw; |
962 | struct req_que *req = ha->req_q_map[0]; | 963 | struct req_que *req = ha->req_q_map[0]; |
963 | 964 | ||
965 | if (IS_QLA82XX(ha)) | ||
966 | return QLA_SUCCESS; | ||
967 | |||
964 | ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; | 968 | ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; |
965 | 969 | ||
966 | rval = qla2x00_mbx_reg_test(vha); | 970 | rval = qla2x00_mbx_reg_test(vha); |
@@ -1183,6 +1187,12 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1183 | unsigned long flags; | 1187 | unsigned long flags; |
1184 | uint16_t fw_major_version; | 1188 | uint16_t fw_major_version; |
1185 | 1189 | ||
1190 | if (IS_QLA82XX(ha)) { | ||
1191 | rval = ha->isp_ops->load_risc(vha, &srisc_address); | ||
1192 | if (rval == QLA_SUCCESS) | ||
1193 | goto enable_82xx_npiv; | ||
1194 | } | ||
1195 | |||
1186 | if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { | 1196 | if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { |
1187 | /* Disable SRAM, Instruction RAM and GP RAM parity. */ | 1197 | /* Disable SRAM, Instruction RAM and GP RAM parity. */ |
1188 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1198 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -1208,6 +1218,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1208 | rval = qla2x00_execute_fw(vha, srisc_address); | 1218 | rval = qla2x00_execute_fw(vha, srisc_address); |
1209 | /* Retrieve firmware information. */ | 1219 | /* Retrieve firmware information. */ |
1210 | if (rval == QLA_SUCCESS) { | 1220 | if (rval == QLA_SUCCESS) { |
1221 | enable_82xx_npiv: | ||
1211 | fw_major_version = ha->fw_major_version; | 1222 | fw_major_version = ha->fw_major_version; |
1212 | rval = qla2x00_get_fw_version(vha, | 1223 | rval = qla2x00_get_fw_version(vha, |
1213 | &ha->fw_major_version, | 1224 | &ha->fw_major_version, |
@@ -1232,8 +1243,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1232 | &ha->fw_xcb_count, NULL, NULL, | 1243 | &ha->fw_xcb_count, NULL, NULL, |
1233 | &ha->max_npiv_vports, NULL); | 1244 | &ha->max_npiv_vports, NULL); |
1234 | 1245 | ||
1235 | if (!fw_major_version && ql2xallocfwdump) | 1246 | if (!fw_major_version && ql2xallocfwdump) { |
1236 | qla2x00_alloc_fw_dump(vha); | 1247 | if (!IS_QLA82XX(ha)) |
1248 | qla2x00_alloc_fw_dump(vha); | ||
1249 | } | ||
1237 | } | 1250 | } |
1238 | } else { | 1251 | } else { |
1239 | DEBUG2(printk(KERN_INFO | 1252 | DEBUG2(printk(KERN_INFO |
@@ -1390,6 +1403,9 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) | |||
1390 | int rval; | 1403 | int rval; |
1391 | struct qla_hw_data *ha = vha->hw; | 1404 | struct qla_hw_data *ha = vha->hw; |
1392 | 1405 | ||
1406 | if (IS_QLA82XX(ha)) | ||
1407 | return; | ||
1408 | |||
1393 | /* Update Serial Link options. */ | 1409 | /* Update Serial Link options. */ |
1394 | if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) | 1410 | if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) |
1395 | return; | 1411 | return; |
@@ -1824,7 +1840,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) | |||
1824 | return(rval); | 1840 | return(rval); |
1825 | } | 1841 | } |
1826 | 1842 | ||
1827 | static inline void | 1843 | inline void |
1828 | qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, | 1844 | qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, |
1829 | char *def) | 1845 | char *def) |
1830 | { | 1846 | { |
@@ -1832,7 +1848,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, | |||
1832 | uint16_t index; | 1848 | uint16_t index; |
1833 | struct qla_hw_data *ha = vha->hw; | 1849 | struct qla_hw_data *ha = vha->hw; |
1834 | int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && | 1850 | int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && |
1835 | !IS_QLA81XX(ha); | 1851 | !IS_QLA8XXX_TYPE(ha); |
1836 | 1852 | ||
1837 | if (memcmp(model, BINZERO, len) != 0) { | 1853 | if (memcmp(model, BINZERO, len) != 0) { |
1838 | strncpy(ha->model_number, model, len); | 1854 | strncpy(ha->model_number, model, len); |
@@ -3552,6 +3568,45 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) | |||
3552 | qla2x00_rport_del(fcport); | 3568 | qla2x00_rport_del(fcport); |
3553 | } | 3569 | } |
3554 | 3570 | ||
3571 | void | ||
3572 | qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | ||
3573 | { | ||
3574 | struct qla_hw_data *ha = vha->hw; | ||
3575 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); | ||
3576 | struct scsi_qla_host *tvp; | ||
3577 | |||
3578 | vha->flags.online = 0; | ||
3579 | ha->flags.chip_reset_done = 0; | ||
3580 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3581 | ha->qla_stats.total_isp_aborts++; | ||
3582 | |||
3583 | qla_printk(KERN_INFO, ha, | ||
3584 | "Performing ISP error recovery - ha= %p.\n", ha); | ||
3585 | |||
3586 | /* Chip reset does not apply to 82XX */ | ||
3587 | if (!IS_QLA82XX(ha)) | ||
3588 | ha->isp_ops->reset_chip(vha); | ||
3589 | |||
3590 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
3591 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
3592 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
3593 | qla2x00_mark_all_devices_lost(vha, 0); | ||
3594 | list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list) | ||
3595 | qla2x00_mark_all_devices_lost(vp, 0); | ||
3596 | } else { | ||
3597 | if (!atomic_read(&vha->loop_down_timer)) | ||
3598 | atomic_set(&vha->loop_down_timer, | ||
3599 | LOOP_DOWN_TIME); | ||
3600 | } | ||
3601 | |||
3602 | /* Make sure for ISP 82XX IO DMA is complete */ | ||
3603 | if (IS_QLA82XX(ha)) | ||
3604 | qla82xx_wait_for_pending_commands(vha); | ||
3605 | |||
3606 | /* Requeue all commands in outstanding command list. */ | ||
3607 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); | ||
3608 | } | ||
3609 | |||
3555 | /* | 3610 | /* |
3556 | * qla2x00_abort_isp | 3611 | * qla2x00_abort_isp |
3557 | * Resets ISP and aborts all outstanding commands. | 3612 | * Resets ISP and aborts all outstanding commands. |
@@ -3573,27 +3628,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3573 | struct req_que *req = ha->req_q_map[0]; | 3628 | struct req_que *req = ha->req_q_map[0]; |
3574 | 3629 | ||
3575 | if (vha->flags.online) { | 3630 | if (vha->flags.online) { |
3576 | vha->flags.online = 0; | 3631 | qla2x00_abort_isp_cleanup(vha); |
3577 | ha->flags.chip_reset_done = 0; | ||
3578 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3579 | ha->qla_stats.total_isp_aborts++; | ||
3580 | |||
3581 | qla_printk(KERN_INFO, ha, | ||
3582 | "Performing ISP error recovery - ha= %p.\n", ha); | ||
3583 | ha->isp_ops->reset_chip(vha); | ||
3584 | |||
3585 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
3586 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
3587 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
3588 | qla2x00_mark_all_devices_lost(vha, 0); | ||
3589 | } else { | ||
3590 | if (!atomic_read(&vha->loop_down_timer)) | ||
3591 | atomic_set(&vha->loop_down_timer, | ||
3592 | LOOP_DOWN_TIME); | ||
3593 | } | ||
3594 | |||
3595 | /* Requeue all commands in outstanding command list. */ | ||
3596 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); | ||
3597 | 3632 | ||
3598 | if (unlikely(pci_channel_offline(ha->pdev) && | 3633 | if (unlikely(pci_channel_offline(ha->pdev) && |
3599 | ha->flags.pci_channel_io_perm_failure)) { | 3634 | ha->flags.pci_channel_io_perm_failure)) { |
@@ -3849,6 +3884,9 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha) | |||
3849 | struct qla_hw_data *ha = vha->hw; | 3884 | struct qla_hw_data *ha = vha->hw; |
3850 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 3885 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
3851 | 3886 | ||
3887 | if (IS_QLA82XX(ha)) | ||
3888 | return; | ||
3889 | |||
3852 | vha->flags.online = 0; | 3890 | vha->flags.online = 0; |
3853 | ha->isp_ops->disable_intrs(ha); | 3891 | ha->isp_ops->disable_intrs(ha); |
3854 | 3892 | ||
@@ -3912,6 +3950,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
3912 | } | 3950 | } |
3913 | ha->nvram_size = sizeof(struct nvram_24xx); | 3951 | ha->nvram_size = sizeof(struct nvram_24xx); |
3914 | ha->vpd_size = FA_NVRAM_VPD_SIZE; | 3952 | ha->vpd_size = FA_NVRAM_VPD_SIZE; |
3953 | if (IS_QLA82XX(ha)) | ||
3954 | ha->vpd_size = FA_VPD_SIZE_82XX; | ||
3915 | 3955 | ||
3916 | /* Get VPD data into cache */ | 3956 | /* Get VPD data into cache */ |
3917 | ha->vpd = ha->nvram + VPD_OFFSET; | 3957 | ha->vpd = ha->nvram + VPD_OFFSET; |
@@ -4775,7 +4815,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
4775 | * Setup driver NVRAM options. | 4815 | * Setup driver NVRAM options. |
4776 | */ | 4816 | */ |
4777 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), | 4817 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), |
4778 | "QLE81XX"); | 4818 | "QLE8XXX"); |
4779 | 4819 | ||
4780 | /* Use alternate WWN? */ | 4820 | /* Use alternate WWN? */ |
4781 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | 4821 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { |
@@ -4898,6 +4938,147 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
4898 | return (rval); | 4938 | return (rval); |
4899 | } | 4939 | } |
4900 | 4940 | ||
4941 | int | ||
4942 | qla82xx_restart_isp(scsi_qla_host_t *vha) | ||
4943 | { | ||
4944 | int status, rval; | ||
4945 | uint32_t wait_time; | ||
4946 | struct qla_hw_data *ha = vha->hw; | ||
4947 | struct req_que *req = ha->req_q_map[0]; | ||
4948 | struct rsp_que *rsp = ha->rsp_q_map[0]; | ||
4949 | struct scsi_qla_host *vp; | ||
4950 | struct scsi_qla_host *tvp; | ||
4951 | |||
4952 | status = qla2x00_init_rings(vha); | ||
4953 | if (!status) { | ||
4954 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); | ||
4955 | ha->flags.chip_reset_done = 1; | ||
4956 | |||
4957 | status = qla2x00_fw_ready(vha); | ||
4958 | if (!status) { | ||
4959 | qla_printk(KERN_INFO, ha, | ||
4960 | "%s(): Start configure loop, " | ||
4961 | "status = %d\n", __func__, status); | ||
4962 | |||
4963 | /* Issue a marker after FW becomes ready. */ | ||
4964 | qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); | ||
4965 | |||
4966 | vha->flags.online = 1; | ||
4967 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ | ||
4968 | wait_time = 256; | ||
4969 | do { | ||
4970 | clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | ||
4971 | qla2x00_configure_loop(vha); | ||
4972 | wait_time--; | ||
4973 | } while (!atomic_read(&vha->loop_down_timer) && | ||
4974 | !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) && | ||
4975 | wait_time && | ||
4976 | (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))); | ||
4977 | } | ||
4978 | |||
4979 | /* if no cable then assume it's good */ | ||
4980 | if ((vha->device_flags & DFLG_NO_CABLE)) | ||
4981 | status = 0; | ||
4982 | |||
4983 | qla_printk(KERN_INFO, ha, | ||
4984 | "%s(): Configure loop done, status = 0x%x\n", | ||
4985 | __func__, status); | ||
4986 | } | ||
4987 | |||
4988 | if (!status) { | ||
4989 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); | ||
4990 | |||
4991 | if (!atomic_read(&vha->loop_down_timer)) { | ||
4992 | /* | ||
4993 | * Issue marker command only when we are going | ||
4994 | * to start the I/O . | ||
4995 | */ | ||
4996 | vha->marker_needed = 1; | ||
4997 | } | ||
4998 | |||
4999 | vha->flags.online = 1; | ||
5000 | |||
5001 | ha->isp_ops->enable_intrs(ha); | ||
5002 | |||
5003 | ha->isp_abort_cnt = 0; | ||
5004 | clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
5005 | |||
5006 | if (ha->fce) { | ||
5007 | ha->flags.fce_enabled = 1; | ||
5008 | memset(ha->fce, 0, | ||
5009 | fce_calc_size(ha->fce_bufs)); | ||
5010 | rval = qla2x00_enable_fce_trace(vha, | ||
5011 | ha->fce_dma, ha->fce_bufs, ha->fce_mb, | ||
5012 | &ha->fce_bufs); | ||
5013 | if (rval) { | ||
5014 | qla_printk(KERN_WARNING, ha, | ||
5015 | "Unable to reinitialize FCE " | ||
5016 | "(%d).\n", rval); | ||
5017 | ha->flags.fce_enabled = 0; | ||
5018 | } | ||
5019 | } | ||
5020 | |||
5021 | if (ha->eft) { | ||
5022 | memset(ha->eft, 0, EFT_SIZE); | ||
5023 | rval = qla2x00_enable_eft_trace(vha, | ||
5024 | ha->eft_dma, EFT_NUM_BUFFERS); | ||
5025 | if (rval) { | ||
5026 | qla_printk(KERN_WARNING, ha, | ||
5027 | "Unable to reinitialize EFT " | ||
5028 | "(%d).\n", rval); | ||
5029 | } | ||
5030 | } | ||
5031 | } else { /* failed the ISP abort */ | ||
5032 | vha->flags.online = 1; | ||
5033 | if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
5034 | if (ha->isp_abort_cnt == 0) { | ||
5035 | qla_printk(KERN_WARNING, ha, | ||
5036 | "ISP error recovery failed - " | ||
5037 | "board disabled\n"); | ||
5038 | /* | ||
5039 | * The next call disables the board | ||
5040 | * completely. | ||
5041 | */ | ||
5042 | ha->isp_ops->reset_adapter(vha); | ||
5043 | vha->flags.online = 0; | ||
5044 | clear_bit(ISP_ABORT_RETRY, | ||
5045 | &vha->dpc_flags); | ||
5046 | status = 0; | ||
5047 | } else { /* schedule another ISP abort */ | ||
5048 | ha->isp_abort_cnt--; | ||
5049 | qla_printk(KERN_INFO, ha, | ||
5050 | "qla%ld: ISP abort - " | ||
5051 | "retry remaining %d\n", | ||
5052 | vha->host_no, ha->isp_abort_cnt); | ||
5053 | status = 1; | ||
5054 | } | ||
5055 | } else { | ||
5056 | ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; | ||
5057 | qla_printk(KERN_INFO, ha, | ||
5058 | "(%ld): ISP error recovery " | ||
5059 | "- retrying (%d) more times\n", | ||
5060 | vha->host_no, ha->isp_abort_cnt); | ||
5061 | set_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
5062 | status = 1; | ||
5063 | } | ||
5064 | } | ||
5065 | |||
5066 | if (!status) { | ||
5067 | DEBUG(printk(KERN_INFO | ||
5068 | "qla82xx_restart_isp(%ld): succeeded.\n", | ||
5069 | vha->host_no)); | ||
5070 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | ||
5071 | if (vp->vp_idx) | ||
5072 | qla2x00_vp_abort_isp(vp); | ||
5073 | } | ||
5074 | } else { | ||
5075 | qla_printk(KERN_INFO, ha, | ||
5076 | "qla82xx_restart_isp: **** FAILED ****\n"); | ||
5077 | } | ||
5078 | |||
5079 | return status; | ||
5080 | } | ||
5081 | |||
4901 | void | 5082 | void |
4902 | qla81xx_update_fw_options(scsi_qla_host_t *vha) | 5083 | qla81xx_update_fw_options(scsi_qla_host_t *vha) |
4903 | { | 5084 | { |