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; |
