diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 143 |
1 files changed, 117 insertions, 26 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3d4487eac9b7..9758dba95542 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -39,6 +39,8 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *, | |||
39 | 39 | ||
40 | static int qla2x00_restart_isp(scsi_qla_host_t *); | 40 | static int qla2x00_restart_isp(scsi_qla_host_t *); |
41 | 41 | ||
42 | static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev); | ||
43 | |||
42 | /****************************************************************************/ | 44 | /****************************************************************************/ |
43 | /* QLogic ISP2x00 Hardware Support Functions. */ | 45 | /* QLogic ISP2x00 Hardware Support Functions. */ |
44 | /****************************************************************************/ | 46 | /****************************************************************************/ |
@@ -89,6 +91,17 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
89 | 91 | ||
90 | ha->isp_ops.nvram_config(ha); | 92 | ha->isp_ops.nvram_config(ha); |
91 | 93 | ||
94 | if (ha->flags.disable_serdes) { | ||
95 | /* Mask HBA via NVRAM settings? */ | ||
96 | qla_printk(KERN_INFO, ha, "Masking HBA WWPN " | ||
97 | "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n", | ||
98 | ha->port_name[0], ha->port_name[1], | ||
99 | ha->port_name[2], ha->port_name[3], | ||
100 | ha->port_name[4], ha->port_name[5], | ||
101 | ha->port_name[6], ha->port_name[7]); | ||
102 | return QLA_FUNCTION_FAILED; | ||
103 | } | ||
104 | |||
92 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); | 105 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); |
93 | 106 | ||
94 | retry = 10; | 107 | retry = 10; |
@@ -770,29 +783,104 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) | |||
770 | return rval; | 783 | return rval; |
771 | } | 784 | } |
772 | 785 | ||
773 | static void | 786 | void |
774 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) | 787 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) |
775 | { | 788 | { |
776 | uint32_t dump_size = 0; | 789 | int rval; |
790 | uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, | ||
791 | eft_size; | ||
792 | dma_addr_t eft_dma; | ||
793 | void *eft; | ||
794 | |||
795 | if (ha->fw_dump) { | ||
796 | qla_printk(KERN_WARNING, ha, | ||
797 | "Firmware dump previously allocated.\n"); | ||
798 | return; | ||
799 | } | ||
777 | 800 | ||
778 | ha->fw_dumped = 0; | 801 | ha->fw_dumped = 0; |
802 | fixed_size = mem_size = eft_size = 0; | ||
779 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 803 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
780 | dump_size = sizeof(struct qla2100_fw_dump); | 804 | fixed_size = sizeof(struct qla2100_fw_dump); |
781 | } else if (IS_QLA23XX(ha)) { | 805 | } else if (IS_QLA23XX(ha)) { |
782 | dump_size = sizeof(struct qla2300_fw_dump); | 806 | fixed_size = offsetof(struct qla2300_fw_dump, data_ram); |
783 | dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); | 807 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * |
784 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 808 | sizeof(uint16_t); |
785 | dump_size = sizeof(struct qla24xx_fw_dump); | 809 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
786 | dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); | 810 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); |
811 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | ||
812 | sizeof(uint32_t); | ||
813 | |||
814 | /* Allocate memory for Extended Trace Buffer. */ | ||
815 | eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma, | ||
816 | GFP_KERNEL); | ||
817 | if (!eft) { | ||
818 | qla_printk(KERN_WARNING, ha, "Unable to allocate " | ||
819 | "(%d KB) for EFT.\n", EFT_SIZE / 1024); | ||
820 | goto cont_alloc; | ||
821 | } | ||
822 | |||
823 | rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma, | ||
824 | EFT_NUM_BUFFERS); | ||
825 | if (rval) { | ||
826 | qla_printk(KERN_WARNING, ha, "Unable to initialize " | ||
827 | "EFT (%d).\n", rval); | ||
828 | dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft, | ||
829 | eft_dma); | ||
830 | goto cont_alloc; | ||
831 | } | ||
832 | |||
833 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n", | ||
834 | EFT_SIZE / 1024); | ||
835 | |||
836 | eft_size = EFT_SIZE; | ||
837 | memset(eft, 0, eft_size); | ||
838 | ha->eft_dma = eft_dma; | ||
839 | ha->eft = eft; | ||
787 | } | 840 | } |
841 | cont_alloc: | ||
842 | req_q_size = ha->request_q_length * sizeof(request_t); | ||
843 | rsp_q_size = ha->response_q_length * sizeof(response_t); | ||
844 | |||
845 | dump_size = offsetof(struct qla2xxx_fw_dump, isp); | ||
846 | dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + | ||
847 | eft_size; | ||
788 | 848 | ||
789 | ha->fw_dump = vmalloc(dump_size); | 849 | ha->fw_dump = vmalloc(dump_size); |
790 | if (ha->fw_dump) | 850 | if (!ha->fw_dump) { |
791 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " | ||
792 | "dump...\n", dump_size / 1024); | ||
793 | else | ||
794 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " | 851 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " |
795 | "firmware dump!!!\n", dump_size / 1024); | 852 | "firmware dump!!!\n", dump_size / 1024); |
853 | |||
854 | if (ha->eft) { | ||
855 | dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft, | ||
856 | ha->eft_dma); | ||
857 | ha->eft = NULL; | ||
858 | ha->eft_dma = 0; | ||
859 | } | ||
860 | return; | ||
861 | } | ||
862 | |||
863 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n", | ||
864 | dump_size / 1024); | ||
865 | |||
866 | ha->fw_dump_len = dump_size; | ||
867 | ha->fw_dump->signature[0] = 'Q'; | ||
868 | ha->fw_dump->signature[1] = 'L'; | ||
869 | ha->fw_dump->signature[2] = 'G'; | ||
870 | ha->fw_dump->signature[3] = 'C'; | ||
871 | ha->fw_dump->version = __constant_htonl(1); | ||
872 | |||
873 | ha->fw_dump->fixed_size = htonl(fixed_size); | ||
874 | ha->fw_dump->mem_size = htonl(mem_size); | ||
875 | ha->fw_dump->req_q_size = htonl(req_q_size); | ||
876 | ha->fw_dump->rsp_q_size = htonl(rsp_q_size); | ||
877 | |||
878 | ha->fw_dump->eft_size = htonl(eft_size); | ||
879 | ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); | ||
880 | ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); | ||
881 | |||
882 | ha->fw_dump->header_size = | ||
883 | htonl(offsetof(struct qla2xxx_fw_dump, isp)); | ||
796 | } | 884 | } |
797 | 885 | ||
798 | /** | 886 | /** |
@@ -810,8 +898,6 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) | |||
810 | dma_addr_t request_dma; | 898 | dma_addr_t request_dma; |
811 | request_t *request_ring; | 899 | request_t *request_ring; |
812 | 900 | ||
813 | qla2x00_alloc_fw_dump(ha); | ||
814 | |||
815 | /* Valid only on recent ISPs. */ | 901 | /* Valid only on recent ISPs. */ |
816 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 902 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
817 | return; | 903 | return; |
@@ -883,6 +969,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
883 | &ha->fw_subminor_version, | 969 | &ha->fw_subminor_version, |
884 | &ha->fw_attributes, &ha->fw_memory_size); | 970 | &ha->fw_attributes, &ha->fw_memory_size); |
885 | qla2x00_resize_request_q(ha); | 971 | qla2x00_resize_request_q(ha); |
972 | |||
973 | if (ql2xallocfwdump) | ||
974 | qla2x00_alloc_fw_dump(ha); | ||
886 | } | 975 | } |
887 | } else { | 976 | } else { |
888 | DEBUG2(printk(KERN_INFO | 977 | DEBUG2(printk(KERN_INFO |
@@ -1186,8 +1275,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) | |||
1186 | rval = QLA_FUNCTION_FAILED; | 1275 | rval = QLA_FUNCTION_FAILED; |
1187 | 1276 | ||
1188 | if (atomic_read(&ha->loop_down_timer) && | 1277 | if (atomic_read(&ha->loop_down_timer) && |
1189 | (fw_state >= FSTATE_LOSS_OF_SYNC || | 1278 | fw_state != FSTATE_READY) { |
1190 | fw_state == FSTATE_WAIT_AL_PA)) { | ||
1191 | /* Loop down. Timeout on min_wait for states | 1279 | /* Loop down. Timeout on min_wait for states |
1192 | * other than Wait for Login. | 1280 | * other than Wait for Login. |
1193 | */ | 1281 | */ |
@@ -1555,6 +1643,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1555 | /* | 1643 | /* |
1556 | * Set host adapter parameters. | 1644 | * Set host adapter parameters. |
1557 | */ | 1645 | */ |
1646 | if (nv->host_p[0] & BIT_7) | ||
1647 | extended_error_logging = 1; | ||
1558 | ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); | 1648 | ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); |
1559 | /* Always load RISC code on non ISP2[12]00 chips. */ | 1649 | /* Always load RISC code on non ISP2[12]00 chips. */ |
1560 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) | 1650 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) |
@@ -1563,6 +1653,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1563 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); | 1653 | ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); |
1564 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); | 1654 | ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); |
1565 | ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0; | 1655 | ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0; |
1656 | ha->flags.disable_serdes = 0; | ||
1566 | 1657 | ||
1567 | ha->operating_mode = | 1658 | ha->operating_mode = |
1568 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; | 1659 | (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; |
@@ -1701,7 +1792,7 @@ qla2x00_rport_del(void *data) | |||
1701 | * | 1792 | * |
1702 | * Returns a pointer to the allocated fcport, or NULL, if none available. | 1793 | * Returns a pointer to the allocated fcport, or NULL, if none available. |
1703 | */ | 1794 | */ |
1704 | fc_port_t * | 1795 | static fc_port_t * |
1705 | qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) | 1796 | qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) |
1706 | { | 1797 | { |
1707 | fc_port_t *fcport; | 1798 | fc_port_t *fcport; |
@@ -2497,7 +2588,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2497 | * Context: | 2588 | * Context: |
2498 | * Kernel context. | 2589 | * Kernel context. |
2499 | */ | 2590 | */ |
2500 | int | 2591 | static int |
2501 | qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) | 2592 | qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) |
2502 | { | 2593 | { |
2503 | int rval; | 2594 | int rval; |
@@ -3048,14 +3139,14 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
3048 | ha->isp_abort_cnt--; | 3139 | ha->isp_abort_cnt--; |
3049 | DEBUG(printk("qla%ld: ISP abort - " | 3140 | DEBUG(printk("qla%ld: ISP abort - " |
3050 | "retry remaining %d\n", | 3141 | "retry remaining %d\n", |
3051 | ha->host_no, ha->isp_abort_cnt);) | 3142 | ha->host_no, ha->isp_abort_cnt)); |
3052 | status = 1; | 3143 | status = 1; |
3053 | } | 3144 | } |
3054 | } else { | 3145 | } else { |
3055 | ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; | 3146 | ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; |
3056 | DEBUG(printk("qla2x00(%ld): ISP error recovery " | 3147 | DEBUG(printk("qla2x00(%ld): ISP error recovery " |
3057 | "- retrying (%d) more times\n", | 3148 | "- retrying (%d) more times\n", |
3058 | ha->host_no, ha->isp_abort_cnt);) | 3149 | ha->host_no, ha->isp_abort_cnt)); |
3059 | set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); | 3150 | set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); |
3060 | status = 1; | 3151 | status = 1; |
3061 | } | 3152 | } |
@@ -3069,7 +3160,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
3069 | } else { | 3160 | } else { |
3070 | DEBUG(printk(KERN_INFO | 3161 | DEBUG(printk(KERN_INFO |
3071 | "qla2x00_abort_isp(%ld): exiting.\n", | 3162 | "qla2x00_abort_isp(%ld): exiting.\n", |
3072 | ha->host_no);) | 3163 | ha->host_no)); |
3073 | } | 3164 | } |
3074 | 3165 | ||
3075 | return(status); | 3166 | return(status); |
@@ -3145,7 +3236,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
3145 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 3236 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
3146 | if (!(status = qla2x00_fw_ready(ha))) { | 3237 | if (!(status = qla2x00_fw_ready(ha))) { |
3147 | DEBUG(printk("%s(): Start configure loop, " | 3238 | DEBUG(printk("%s(): Start configure loop, " |
3148 | "status = %d\n", __func__, status);) | 3239 | "status = %d\n", __func__, status)); |
3149 | 3240 | ||
3150 | /* Issue a marker after FW becomes ready. */ | 3241 | /* Issue a marker after FW becomes ready. */ |
3151 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | 3242 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); |
@@ -3169,7 +3260,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
3169 | 3260 | ||
3170 | DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", | 3261 | DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", |
3171 | __func__, | 3262 | __func__, |
3172 | status);) | 3263 | status)); |
3173 | } | 3264 | } |
3174 | return (status); | 3265 | return (status); |
3175 | } | 3266 | } |
@@ -3289,7 +3380,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3289 | nv->node_name[6] = 0x55; | 3380 | nv->node_name[6] = 0x55; |
3290 | nv->node_name[7] = 0x86; | 3381 | nv->node_name[7] = 0x86; |
3291 | nv->login_retry_count = __constant_cpu_to_le16(8); | 3382 | nv->login_retry_count = __constant_cpu_to_le16(8); |
3292 | nv->link_down_timeout = __constant_cpu_to_le16(200); | ||
3293 | nv->interrupt_delay_timer = __constant_cpu_to_le16(0); | 3383 | nv->interrupt_delay_timer = __constant_cpu_to_le16(0); |
3294 | nv->login_timeout = __constant_cpu_to_le16(0); | 3384 | nv->login_timeout = __constant_cpu_to_le16(0); |
3295 | nv->firmware_options_1 = | 3385 | nv->firmware_options_1 = |
@@ -3318,7 +3408,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3318 | *dptr1++ = *dptr2++; | 3408 | *dptr1++ = *dptr2++; |
3319 | 3409 | ||
3320 | icb->login_retry_count = nv->login_retry_count; | 3410 | icb->login_retry_count = nv->login_retry_count; |
3321 | icb->link_down_timeout = nv->link_down_timeout; | 3411 | icb->link_down_on_nos = nv->link_down_on_nos; |
3322 | 3412 | ||
3323 | /* Copy 2nd segment. */ | 3413 | /* Copy 2nd segment. */ |
3324 | dptr1 = (uint8_t *)&icb->interrupt_delay_timer; | 3414 | dptr1 = (uint8_t *)&icb->interrupt_delay_timer; |
@@ -3373,6 +3463,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3373 | ha->flags.enable_lip_full_login = 1; | 3463 | ha->flags.enable_lip_full_login = 1; |
3374 | ha->flags.enable_target_reset = 1; | 3464 | ha->flags.enable_target_reset = 1; |
3375 | ha->flags.enable_led_scheme = 0; | 3465 | ha->flags.enable_led_scheme = 0; |
3466 | ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0; | ||
3376 | 3467 | ||
3377 | ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & | 3468 | ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & |
3378 | (BIT_6 | BIT_5 | BIT_4)) >> 4; | 3469 | (BIT_6 | BIT_5 | BIT_4)) >> 4; |
@@ -3472,7 +3563,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3472 | return (rval); | 3563 | return (rval); |
3473 | } | 3564 | } |
3474 | 3565 | ||
3475 | int | 3566 | static int |
3476 | qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3567 | qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
3477 | { | 3568 | { |
3478 | int rval; | 3569 | int rval; |