diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 241 |
1 files changed, 48 insertions, 193 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 89a3fc0595bb..aef093db597e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -194,7 +194,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) | |||
194 | mwi = 0; | 194 | mwi = 0; |
195 | if (pci_set_mwi(ha->pdev)) | 195 | if (pci_set_mwi(ha->pdev)) |
196 | mwi = PCI_COMMAND_INVALIDATE; | 196 | mwi = PCI_COMMAND_INVALIDATE; |
197 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); | ||
198 | 197 | ||
199 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 198 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
200 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 199 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
@@ -232,7 +231,6 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
232 | mwi = 0; | 231 | mwi = 0; |
233 | if (pci_set_mwi(ha->pdev)) | 232 | if (pci_set_mwi(ha->pdev)) |
234 | mwi = PCI_COMMAND_INVALIDATE; | 233 | mwi = PCI_COMMAND_INVALIDATE; |
235 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); | ||
236 | 234 | ||
237 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 235 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
238 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 236 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
@@ -320,7 +318,6 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
320 | mwi = 0; | 318 | mwi = 0; |
321 | if (pci_set_mwi(ha->pdev)) | 319 | if (pci_set_mwi(ha->pdev)) |
322 | mwi = PCI_COMMAND_INVALIDATE; | 320 | mwi = PCI_COMMAND_INVALIDATE; |
323 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); | ||
324 | 321 | ||
325 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 322 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
326 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 323 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
@@ -386,9 +383,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) | |||
386 | qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); | 383 | qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); |
387 | 384 | ||
388 | /* Verify checksum of loaded RISC code. */ | 385 | /* Verify checksum of loaded RISC code. */ |
389 | rval = qla2x00_verify_checksum(ha, | 386 | rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); |
390 | IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS : | ||
391 | *ha->brd_info->fw_info[0].fwstart); | ||
392 | } | 387 | } |
393 | 388 | ||
394 | if (rval) { | 389 | if (rval) { |
@@ -411,7 +406,6 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) | |||
411 | unsigned long flags = 0; | 406 | unsigned long flags = 0; |
412 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 407 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
413 | uint32_t cnt; | 408 | uint32_t cnt; |
414 | unsigned long mbx_flags = 0; | ||
415 | uint16_t cmd; | 409 | uint16_t cmd; |
416 | 410 | ||
417 | ha->isp_ops.disable_intrs(ha); | 411 | ha->isp_ops.disable_intrs(ha); |
@@ -519,20 +513,8 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) | |||
519 | 513 | ||
520 | if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { | 514 | if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { |
521 | for (cnt = 0; cnt < 30000; cnt++) { | 515 | for (cnt = 0; cnt < 30000; cnt++) { |
522 | if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) | 516 | if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) |
523 | spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); | ||
524 | |||
525 | if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) { | ||
526 | if (!(test_bit(ABORT_ISP_ACTIVE, | ||
527 | &ha->dpc_flags))) | ||
528 | spin_unlock_irqrestore( | ||
529 | &ha->mbx_reg_lock, mbx_flags); | ||
530 | break; | 517 | break; |
531 | } | ||
532 | |||
533 | if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) | ||
534 | spin_unlock_irqrestore(&ha->mbx_reg_lock, | ||
535 | mbx_flags); | ||
536 | 518 | ||
537 | udelay(100); | 519 | udelay(100); |
538 | } | 520 | } |
@@ -791,16 +773,26 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) | |||
791 | static void | 773 | static void |
792 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) | 774 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) |
793 | { | 775 | { |
776 | uint32_t dump_size = 0; | ||
777 | |||
794 | ha->fw_dumped = 0; | 778 | ha->fw_dumped = 0; |
795 | ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump); | 779 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
796 | ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); | 780 | dump_size = sizeof(struct qla2100_fw_dump); |
797 | ha->fw_dump24 = vmalloc(ha->fw_dump24_len); | 781 | } else if (IS_QLA23XX(ha)) { |
798 | if (ha->fw_dump24) | 782 | dump_size = sizeof(struct qla2300_fw_dump); |
783 | dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); | ||
784 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | ||
785 | dump_size = sizeof(struct qla24xx_fw_dump); | ||
786 | dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); | ||
787 | } | ||
788 | |||
789 | ha->fw_dump = vmalloc(dump_size); | ||
790 | if (ha->fw_dump) | ||
799 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " | 791 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " |
800 | "dump...\n", ha->fw_dump24_len / 1024); | 792 | "dump...\n", dump_size / 1024); |
801 | else | 793 | else |
802 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " | 794 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " |
803 | "firmware dump!!!\n", ha->fw_dump24_len / 1024); | 795 | "firmware dump!!!\n", dump_size / 1024); |
804 | } | 796 | } |
805 | 797 | ||
806 | /** | 798 | /** |
@@ -818,13 +810,12 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) | |||
818 | dma_addr_t request_dma; | 810 | dma_addr_t request_dma; |
819 | request_t *request_ring; | 811 | request_t *request_ring; |
820 | 812 | ||
813 | qla2x00_alloc_fw_dump(ha); | ||
814 | |||
821 | /* Valid only on recent ISPs. */ | 815 | /* Valid only on recent ISPs. */ |
822 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 816 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
823 | return; | 817 | return; |
824 | 818 | ||
825 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | ||
826 | qla2x00_alloc_fw_dump(ha); | ||
827 | |||
828 | /* Retrieve IOCB counts available to the firmware. */ | 819 | /* Retrieve IOCB counts available to the firmware. */ |
829 | rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); | 820 | rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); |
830 | if (rval) | 821 | if (rval) |
@@ -1545,6 +1536,12 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1545 | while (cnt--) | 1536 | while (cnt--) |
1546 | *dptr1++ = *dptr2++; | 1537 | *dptr1++ = *dptr2++; |
1547 | 1538 | ||
1539 | /* Use alternate WWN? */ | ||
1540 | if (nv->host_p[1] & BIT_7) { | ||
1541 | memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); | ||
1542 | memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); | ||
1543 | } | ||
1544 | |||
1548 | /* Prepare nodename */ | 1545 | /* Prepare nodename */ |
1549 | if ((icb->firmware_options[1] & BIT_6) == 0) { | 1546 | if ((icb->firmware_options[1] & BIT_6) == 0) { |
1550 | /* | 1547 | /* |
@@ -1682,14 +1679,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1682 | } | 1679 | } |
1683 | 1680 | ||
1684 | static void | 1681 | static void |
1685 | qla2x00_rport_add(void *data) | ||
1686 | { | ||
1687 | fc_port_t *fcport = data; | ||
1688 | |||
1689 | qla2x00_reg_remote_port(fcport->ha, fcport); | ||
1690 | } | ||
1691 | |||
1692 | static void | ||
1693 | qla2x00_rport_del(void *data) | 1682 | qla2x00_rport_del(void *data) |
1694 | { | 1683 | { |
1695 | fc_port_t *fcport = data; | 1684 | fc_port_t *fcport = data; |
@@ -1726,13 +1715,10 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) | |||
1726 | fcport->ha = ha; | 1715 | fcport->ha = ha; |
1727 | fcport->port_type = FCT_UNKNOWN; | 1716 | fcport->port_type = FCT_UNKNOWN; |
1728 | fcport->loop_id = FC_NO_LOOP_ID; | 1717 | fcport->loop_id = FC_NO_LOOP_ID; |
1729 | fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; | ||
1730 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 1718 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
1731 | fcport->flags = FCF_RLC_SUPPORT; | 1719 | fcport->flags = FCF_RLC_SUPPORT; |
1732 | fcport->supported_classes = FC_COS_UNSPECIFIED; | 1720 | fcport->supported_classes = FC_COS_UNSPECIFIED; |
1733 | spin_lock_init(&fcport->rport_lock); | 1721 | spin_lock_init(&fcport->rport_lock); |
1734 | INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); | ||
1735 | INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); | ||
1736 | 1722 | ||
1737 | return (fcport); | 1723 | return (fcport); |
1738 | } | 1724 | } |
@@ -1792,6 +1778,9 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) | |||
1792 | set_bit(RSCN_UPDATE, &flags); | 1778 | set_bit(RSCN_UPDATE, &flags); |
1793 | clear_bit(LOCAL_LOOP_UPDATE, &flags); | 1779 | clear_bit(LOCAL_LOOP_UPDATE, &flags); |
1794 | 1780 | ||
1781 | } else if (ha->current_topology == ISP_CFG_N) { | ||
1782 | clear_bit(RSCN_UPDATE, &flags); | ||
1783 | |||
1795 | } else if (!ha->flags.online || | 1784 | } else if (!ha->flags.online || |
1796 | (test_bit(ABORT_ISP_ACTIVE, &flags))) { | 1785 | (test_bit(ABORT_ISP_ACTIVE, &flags))) { |
1797 | 1786 | ||
@@ -2055,10 +2044,6 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2055 | PORT_RETRY_TIME); | 2044 | PORT_RETRY_TIME); |
2056 | fcport->flags &= ~FCF_LOGIN_NEEDED; | 2045 | fcport->flags &= ~FCF_LOGIN_NEEDED; |
2057 | 2046 | ||
2058 | if (fcport->port_type == FCT_INITIATOR || | ||
2059 | fcport->port_type == FCT_BROADCAST) | ||
2060 | fcport->device_type = TYPE_PROCESSOR; | ||
2061 | |||
2062 | atomic_set(&fcport->state, FCS_ONLINE); | 2047 | atomic_set(&fcport->state, FCS_ONLINE); |
2063 | 2048 | ||
2064 | if (ha->flags.init_done) | 2049 | if (ha->flags.init_done) |
@@ -2587,7 +2572,6 @@ static int | |||
2587 | qla2x00_device_resync(scsi_qla_host_t *ha) | 2572 | qla2x00_device_resync(scsi_qla_host_t *ha) |
2588 | { | 2573 | { |
2589 | int rval; | 2574 | int rval; |
2590 | int rval2; | ||
2591 | uint32_t mask; | 2575 | uint32_t mask; |
2592 | fc_port_t *fcport; | 2576 | fc_port_t *fcport; |
2593 | uint32_t rscn_entry; | 2577 | uint32_t rscn_entry; |
@@ -2643,17 +2627,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
2643 | 2627 | ||
2644 | switch (format) { | 2628 | switch (format) { |
2645 | case 0: | 2629 | case 0: |
2646 | if (ql2xprocessrscn && | ||
2647 | !IS_QLA2100(ha) && !IS_QLA2200(ha) && | ||
2648 | !IS_QLA6312(ha) && !IS_QLA6322(ha) && | ||
2649 | !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && | ||
2650 | ha->flags.init_done) { | ||
2651 | /* Handle port RSCN via asyncronous IOCBs */ | ||
2652 | rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, | ||
2653 | NULL, 0); | ||
2654 | if (rval2 == QLA_SUCCESS) | ||
2655 | continue; | ||
2656 | } | ||
2657 | mask = 0xffffff; | 2630 | mask = 0xffffff; |
2658 | break; | 2631 | break; |
2659 | case 1: | 2632 | case 1: |
@@ -2671,10 +2644,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
2671 | 2644 | ||
2672 | rval = QLA_SUCCESS; | 2645 | rval = QLA_SUCCESS; |
2673 | 2646 | ||
2674 | /* Abort any outstanding IO descriptors. */ | ||
2675 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) | ||
2676 | qla2x00_cancel_io_descriptors(ha); | ||
2677 | |||
2678 | list_for_each_entry(fcport, &ha->fcports, list) { | 2647 | list_for_each_entry(fcport, &ha->fcports, list) { |
2679 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || | 2648 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || |
2680 | (fcport->d_id.b24 & mask) != d_id.b24 || | 2649 | (fcport->d_id.b24 & mask) != d_id.b24 || |
@@ -3383,8 +3352,14 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3383 | } else | 3352 | } else |
3384 | strcpy(ha->model_number, "QLA2462"); | 3353 | strcpy(ha->model_number, "QLA2462"); |
3385 | 3354 | ||
3355 | /* Use alternate WWN? */ | ||
3356 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | ||
3357 | memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); | ||
3358 | memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); | ||
3359 | } | ||
3360 | |||
3386 | /* Prepare nodename */ | 3361 | /* Prepare nodename */ |
3387 | if ((icb->firmware_options_1 & BIT_14) == 0) { | 3362 | if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { |
3388 | /* | 3363 | /* |
3389 | * Firmware will apply the following mask if the nodename was | 3364 | * Firmware will apply the following mask if the nodename was |
3390 | * not provided. | 3365 | * not provided. |
@@ -3400,8 +3375,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3400 | ha->flags.enable_target_reset = 1; | 3375 | ha->flags.enable_target_reset = 1; |
3401 | ha->flags.enable_led_scheme = 0; | 3376 | ha->flags.enable_led_scheme = 0; |
3402 | 3377 | ||
3403 | ha->operating_mode = | 3378 | ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & |
3404 | (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4; | 3379 | (BIT_6 | BIT_5 | BIT_4)) >> 4; |
3405 | 3380 | ||
3406 | memcpy(ha->fw_seriallink_options24, nv->seriallink_options, | 3381 | memcpy(ha->fw_seriallink_options24, nv->seriallink_options, |
3407 | sizeof(ha->fw_seriallink_options24)); | 3382 | sizeof(ha->fw_seriallink_options24)); |
@@ -3498,133 +3473,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3498 | return (rval); | 3473 | return (rval); |
3499 | } | 3474 | } |
3500 | 3475 | ||
3501 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
3502 | |||
3503 | int | ||
3504 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3505 | { | ||
3506 | int rval, num, i; | ||
3507 | uint32_t cnt; | ||
3508 | uint16_t *risc_code; | ||
3509 | uint32_t risc_addr, risc_size; | ||
3510 | uint16_t *req_ring; | ||
3511 | struct qla_fw_info *fw_iter; | ||
3512 | |||
3513 | rval = QLA_SUCCESS; | ||
3514 | |||
3515 | /* Load firmware sequences */ | ||
3516 | fw_iter = ha->brd_info->fw_info; | ||
3517 | *srisc_addr = *ha->brd_info->fw_info->fwstart; | ||
3518 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | ||
3519 | risc_code = fw_iter->fwcode; | ||
3520 | risc_size = *fw_iter->fwlen; | ||
3521 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) | ||
3522 | risc_addr = *fw_iter->fwstart; | ||
3523 | else | ||
3524 | risc_addr = *fw_iter->lfwstart; | ||
3525 | |||
3526 | num = 0; | ||
3527 | rval = 0; | ||
3528 | while (risc_size > 0 && !rval) { | ||
3529 | cnt = (uint16_t)(ha->fw_transfer_size >> 1); | ||
3530 | if (cnt > risc_size) | ||
3531 | cnt = risc_size; | ||
3532 | |||
3533 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | ||
3534 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | ||
3535 | ha->host_no, risc_code, cnt, risc_addr)); | ||
3536 | |||
3537 | req_ring = (uint16_t *)ha->request_ring; | ||
3538 | for (i = 0; i < cnt; i++) | ||
3539 | req_ring[i] = cpu_to_le16(risc_code[i]); | ||
3540 | |||
3541 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, | ||
3542 | cnt); | ||
3543 | if (rval) { | ||
3544 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | ||
3545 | "load segment %d of firmware\n", | ||
3546 | ha->host_no, num)); | ||
3547 | qla_printk(KERN_WARNING, ha, | ||
3548 | "[ERROR] Failed to load segment %d of " | ||
3549 | "firmware\n", num); | ||
3550 | |||
3551 | qla2x00_dump_regs(ha); | ||
3552 | break; | ||
3553 | } | ||
3554 | |||
3555 | risc_code += cnt; | ||
3556 | risc_addr += cnt; | ||
3557 | risc_size -= cnt; | ||
3558 | num++; | ||
3559 | } | ||
3560 | |||
3561 | /* Next firmware sequence */ | ||
3562 | fw_iter++; | ||
3563 | } | ||
3564 | return rval; | ||
3565 | } | ||
3566 | |||
3567 | int | ||
3568 | qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3569 | { | ||
3570 | int rval, num, i; | ||
3571 | uint32_t cnt; | ||
3572 | uint32_t *risc_code; | ||
3573 | uint32_t risc_addr, risc_size; | ||
3574 | uint32_t *req_ring; | ||
3575 | struct qla_fw_info *fw_iter; | ||
3576 | |||
3577 | rval = QLA_SUCCESS; | ||
3578 | |||
3579 | /* Load firmware sequences */ | ||
3580 | fw_iter = ha->brd_info->fw_info; | ||
3581 | *srisc_addr = *((uint32_t *)fw_iter->lfwstart); | ||
3582 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | ||
3583 | risc_code = (uint32_t *)fw_iter->fwcode; | ||
3584 | risc_size = *((uint32_t *)fw_iter->fwlen); | ||
3585 | risc_addr = *((uint32_t *)fw_iter->lfwstart); | ||
3586 | |||
3587 | num = 0; | ||
3588 | rval = 0; | ||
3589 | while (risc_size > 0 && !rval) { | ||
3590 | cnt = (uint32_t)(ha->fw_transfer_size >> 2); | ||
3591 | if (cnt > risc_size) | ||
3592 | cnt = risc_size; | ||
3593 | |||
3594 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | ||
3595 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | ||
3596 | ha->host_no, risc_code, cnt, risc_addr)); | ||
3597 | |||
3598 | req_ring = (uint32_t *)ha->request_ring; | ||
3599 | for (i = 0; i < cnt; i++) | ||
3600 | req_ring[i] = cpu_to_le32(risc_code[i]); | ||
3601 | |||
3602 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, | ||
3603 | cnt); | ||
3604 | if (rval) { | ||
3605 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | ||
3606 | "load segment %d of firmware\n", | ||
3607 | ha->host_no, num)); | ||
3608 | qla_printk(KERN_WARNING, ha, | ||
3609 | "[ERROR] Failed to load segment %d of " | ||
3610 | "firmware\n", num); | ||
3611 | |||
3612 | qla2x00_dump_regs(ha); | ||
3613 | break; | ||
3614 | } | ||
3615 | |||
3616 | risc_code += cnt; | ||
3617 | risc_addr += cnt; | ||
3618 | risc_size -= cnt; | ||
3619 | num++; | ||
3620 | } | ||
3621 | |||
3622 | /* Next firmware sequence */ | ||
3623 | fw_iter++; | ||
3624 | } | ||
3625 | return rval; | ||
3626 | } | ||
3627 | |||
3628 | int | 3476 | int |
3629 | qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3477 | qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
3630 | { | 3478 | { |
@@ -3707,7 +3555,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3707 | return rval; | 3555 | return rval; |
3708 | } | 3556 | } |
3709 | 3557 | ||
3710 | #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ | 3558 | #define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" |
3711 | 3559 | ||
3712 | int | 3560 | int |
3713 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3561 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
@@ -3722,6 +3570,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3722 | blob = qla2x00_request_firmware(ha); | 3570 | blob = qla2x00_request_firmware(ha); |
3723 | if (!blob) { | 3571 | if (!blob) { |
3724 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); | 3572 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); |
3573 | qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " | ||
3574 | "from: " QLA_FW_URL ".\n"); | ||
3725 | return QLA_FUNCTION_FAILED; | 3575 | return QLA_FUNCTION_FAILED; |
3726 | } | 3576 | } |
3727 | 3577 | ||
@@ -3823,7 +3673,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3823 | blob = qla2x00_request_firmware(ha); | 3673 | blob = qla2x00_request_firmware(ha); |
3824 | if (!blob) { | 3674 | if (!blob) { |
3825 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); | 3675 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); |
3826 | return QLA_FUNCTION_FAILED; | 3676 | qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " |
3677 | "from: " QLA_FW_URL ".\n"); | ||
3678 | |||
3679 | /* Try to load RISC code from flash. */ | ||
3680 | qla_printk(KERN_ERR, ha, "Attempting to load (potentially " | ||
3681 | "outdated) firmware from flash.\n"); | ||
3682 | return qla24xx_load_risc_flash(ha, srisc_addr); | ||
3827 | } | 3683 | } |
3828 | 3684 | ||
3829 | rval = QLA_SUCCESS; | 3685 | rval = QLA_SUCCESS; |
@@ -3909,4 +3765,3 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3909 | fail_fw_integrity: | 3765 | fail_fw_integrity: |
3910 | return QLA_FUNCTION_FAILED; | 3766 | return QLA_FUNCTION_FAILED; |
3911 | } | 3767 | } |
3912 | #endif | ||