diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2005-11-09 18:49:04 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-12-13 20:11:16 -0500 |
commit | 5433383ef33ed40c9c8a86a4355da344234af2a5 (patch) | |
tree | 8d82c620fe6faadfa805fb465d5beb67946133c7 /drivers/scsi/qla2xxx/qla_os.c | |
parent | 26a68019c86e1d1782984a7a5babff762cde1501 (diff) |
[SCSI] qla2xxx: Add full firmware(-request) hotplug support for all ISPs.
Transition driver to exclusively use the request_firmware()
interfaces to retrieve firmware-blobs from user-space. This
will be the default behaviour going forward until the
embedded firmware-binary images are removed from the
upstream kernel.
Upon request, the driver caches the firmware image until the
driver is unloaded.
NOTE: The option is present to allow the user to continue to
use the firmware-loader modules, but, should be considered
deprecated.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Rejections fixed up and
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 156 |
1 files changed, 140 insertions, 16 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c58c9d97b041..47db029b2fce 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -54,11 +54,6 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); | |||
54 | MODULE_PARM_DESC(ql2xloginretrycount, | 54 | MODULE_PARM_DESC(ql2xloginretrycount, |
55 | "Specify an alternate value for the NVRAM login retry count."); | 55 | "Specify an alternate value for the NVRAM login retry count."); |
56 | 56 | ||
57 | int ql2xfwloadbin=1; | ||
58 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); | ||
59 | MODULE_PARM_DESC(ql2xfwloadbin, | ||
60 | "Load ISP2xxx firmware image via hotplug."); | ||
61 | |||
62 | static void qla2x00_free_device(scsi_qla_host_t *); | 57 | static void qla2x00_free_device(scsi_qla_host_t *); |
63 | 58 | ||
64 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); | 59 | static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); |
@@ -1261,12 +1256,16 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1261 | char pci_info[20]; | 1256 | char pci_info[20]; |
1262 | char fw_str[30]; | 1257 | char fw_str[30]; |
1263 | fc_port_t *fcport; | 1258 | fc_port_t *fcport; |
1259 | struct scsi_host_template *sht; | ||
1264 | 1260 | ||
1265 | if (pci_enable_device(pdev)) | 1261 | if (pci_enable_device(pdev)) |
1266 | goto probe_out; | 1262 | goto probe_out; |
1267 | 1263 | ||
1268 | host = scsi_host_alloc(brd_info->sht ? brd_info->sht: | 1264 | sht = &qla2x00_driver_template; |
1269 | &qla2x00_driver_template, sizeof(scsi_qla_host_t)); | 1265 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || |
1266 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) | ||
1267 | sht = &qla24xx_driver_template; | ||
1268 | host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); | ||
1270 | if (host == NULL) { | 1269 | if (host == NULL) { |
1271 | printk(KERN_WARNING | 1270 | printk(KERN_WARNING |
1272 | "qla2xxx: Couldn't allocate host from scsi layer!\n"); | 1271 | "qla2xxx: Couldn't allocate host from scsi layer!\n"); |
@@ -1291,8 +1290,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1291 | goto probe_failed; | 1290 | goto probe_failed; |
1292 | 1291 | ||
1293 | qla_printk(KERN_INFO, ha, | 1292 | qla_printk(KERN_INFO, ha, |
1294 | "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name, | 1293 | "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, |
1295 | pdev->irq, ha->iobase); | 1294 | ha->iobase); |
1296 | 1295 | ||
1297 | spin_lock_init(&ha->hardware_lock); | 1296 | spin_lock_init(&ha->hardware_lock); |
1298 | 1297 | ||
@@ -1368,9 +1367,11 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1368 | ha->isp_ops.reset_adapter = qla24xx_reset_adapter; | 1367 | ha->isp_ops.reset_adapter = qla24xx_reset_adapter; |
1369 | ha->isp_ops.nvram_config = qla24xx_nvram_config; | 1368 | ha->isp_ops.nvram_config = qla24xx_nvram_config; |
1370 | ha->isp_ops.update_fw_options = qla24xx_update_fw_options; | 1369 | ha->isp_ops.update_fw_options = qla24xx_update_fw_options; |
1370 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
1371 | ha->isp_ops.load_risc = qla24xx_load_risc_flash; | 1371 | ha->isp_ops.load_risc = qla24xx_load_risc_flash; |
1372 | if (ql2xfwloadbin) | 1372 | #else |
1373 | ha->isp_ops.load_risc = qla24xx_load_risc_hotplug; | 1373 | ha->isp_ops.load_risc = qla24xx_load_risc; |
1374 | #endif | ||
1374 | ha->isp_ops.pci_info_str = qla24xx_pci_info_str; | 1375 | ha->isp_ops.pci_info_str = qla24xx_pci_info_str; |
1375 | ha->isp_ops.fw_version_str = qla24xx_fw_version_str; | 1376 | ha->isp_ops.fw_version_str = qla24xx_fw_version_str; |
1376 | ha->isp_ops.intr_handler = qla24xx_intr_handler; | 1377 | ha->isp_ops.intr_handler = qla24xx_intr_handler; |
@@ -1531,11 +1532,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1531 | qla_printk(KERN_INFO, ha, "\n" | 1532 | qla_printk(KERN_INFO, ha, "\n" |
1532 | " QLogic Fibre Channel HBA Driver: %s\n" | 1533 | " QLogic Fibre Channel HBA Driver: %s\n" |
1533 | " QLogic %s - %s\n" | 1534 | " QLogic %s - %s\n" |
1534 | " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, | 1535 | " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", |
1535 | ha->model_number, ha->model_desc ? ha->model_desc: "", | 1536 | qla2x00_version_str, ha->model_number, |
1536 | ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info), | 1537 | ha->model_desc ? ha->model_desc: "", pdev->device, |
1537 | pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-', | 1538 | ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev), |
1538 | ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str)); | 1539 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, |
1540 | ha->isp_ops.fw_version_str(ha, fw_str)); | ||
1539 | 1541 | ||
1540 | /* Go with fc_rport registration. */ | 1542 | /* Go with fc_rport registration. */ |
1541 | list_for_each_entry(fcport, &ha->fcports, list) | 1543 | list_for_each_entry(fcport, &ha->fcports, list) |
@@ -2483,6 +2485,10 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) | |||
2483 | return -ETIMEDOUT; | 2485 | return -ETIMEDOUT; |
2484 | } | 2486 | } |
2485 | 2487 | ||
2488 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
2489 | |||
2490 | #define qla2x00_release_firmware() do { } while (0) | ||
2491 | |||
2486 | static struct qla_board_info qla_board_tbl[] = { | 2492 | static struct qla_board_info qla_board_tbl[] = { |
2487 | { | 2493 | { |
2488 | .drv_name = "qla2400", | 2494 | .drv_name = "qla2400", |
@@ -2530,8 +2536,122 @@ qla2xxx_remove_one(struct pci_dev *pdev) | |||
2530 | qla2x00_remove_one(pdev); | 2536 | qla2x00_remove_one(pdev); |
2531 | } | 2537 | } |
2532 | 2538 | ||
2539 | #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ | ||
2540 | |||
2541 | /* Firmware interface routines. */ | ||
2542 | |||
2543 | #define FW_BLOBS 6 | ||
2544 | #define FW_ISP21XX 0 | ||
2545 | #define FW_ISP22XX 1 | ||
2546 | #define FW_ISP2300 2 | ||
2547 | #define FW_ISP2322 3 | ||
2548 | #define FW_ISP63XX 4 | ||
2549 | #define FW_ISP24XX 5 | ||
2550 | |||
2551 | static DECLARE_MUTEX(qla_fw_lock); | ||
2552 | |||
2553 | static struct fw_blob qla_fw_blobs[FW_BLOBS] = { | ||
2554 | { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, }, | ||
2555 | { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, | ||
2556 | { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, | ||
2557 | { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, | ||
2558 | { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, }, | ||
2559 | { .name = "ql2400_fw.bin", }, | ||
2560 | }; | ||
2561 | |||
2562 | struct fw_blob * | ||
2563 | qla2x00_request_firmware(scsi_qla_host_t *ha) | ||
2564 | { | ||
2565 | struct fw_blob *blob; | ||
2566 | |||
2567 | blob = NULL; | ||
2568 | if (IS_QLA2100(ha)) { | ||
2569 | blob = &qla_fw_blobs[FW_ISP21XX]; | ||
2570 | } else if (IS_QLA2200(ha)) { | ||
2571 | blob = &qla_fw_blobs[FW_ISP22XX]; | ||
2572 | } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) { | ||
2573 | blob = &qla_fw_blobs[FW_ISP2300]; | ||
2574 | } else if (IS_QLA2322(ha)) { | ||
2575 | blob = &qla_fw_blobs[FW_ISP2322]; | ||
2576 | } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { | ||
2577 | blob = &qla_fw_blobs[FW_ISP63XX]; | ||
2578 | } else if (IS_QLA24XX(ha)) { | ||
2579 | blob = &qla_fw_blobs[FW_ISP24XX]; | ||
2580 | } | ||
2581 | |||
2582 | down(&qla_fw_lock); | ||
2583 | if (blob->fw) | ||
2584 | goto out; | ||
2585 | |||
2586 | if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { | ||
2587 | DEBUG2(printk("scsi(%ld): Failed to load firmware image " | ||
2588 | "(%s).\n", ha->host_no, blob->name)); | ||
2589 | blob->fw = NULL; | ||
2590 | blob = NULL; | ||
2591 | goto out; | ||
2592 | } | ||
2593 | |||
2594 | out: | ||
2595 | up(&qla_fw_lock); | ||
2596 | return blob; | ||
2597 | } | ||
2598 | |||
2599 | static void | ||
2600 | qla2x00_release_firmware(void) | ||
2601 | { | ||
2602 | int idx; | ||
2603 | |||
2604 | down(&qla_fw_lock); | ||
2605 | for (idx = 0; idx < FW_BLOBS; idx++) | ||
2606 | if (qla_fw_blobs[idx].fw) | ||
2607 | release_firmware(qla_fw_blobs[idx].fw); | ||
2608 | up(&qla_fw_lock); | ||
2609 | } | ||
2610 | |||
2611 | static struct qla_board_info qla_board_tbl = { | ||
2612 | .drv_name = "qla2xxx", | ||
2613 | }; | ||
2614 | |||
2615 | static struct pci_device_id qla2xxx_pci_tbl[] = { | ||
2616 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, | ||
2617 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2618 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, | ||
2619 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2620 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300, | ||
2621 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2622 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312, | ||
2623 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2624 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322, | ||
2625 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2626 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312, | ||
2627 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2628 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322, | ||
2629 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2630 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422, | ||
2631 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2632 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, | ||
2633 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2634 | { 0 }, | ||
2635 | }; | ||
2636 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); | ||
2637 | |||
2638 | static int __devinit | ||
2639 | qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | ||
2640 | { | ||
2641 | return qla2x00_probe_one(pdev, &qla_board_tbl); | ||
2642 | } | ||
2643 | |||
2644 | static void __devexit | ||
2645 | qla2xxx_remove_one(struct pci_dev *pdev) | ||
2646 | { | ||
2647 | qla2x00_remove_one(pdev); | ||
2648 | } | ||
2649 | |||
2650 | #endif | ||
2651 | |||
2533 | static struct pci_driver qla2xxx_pci_driver = { | 2652 | static struct pci_driver qla2xxx_pci_driver = { |
2534 | .name = "qla2xxx", | 2653 | .name = "qla2xxx", |
2654 | .owner = THIS_MODULE, | ||
2535 | .id_table = qla2xxx_pci_tbl, | 2655 | .id_table = qla2xxx_pci_tbl, |
2536 | .probe = qla2xxx_probe_one, | 2656 | .probe = qla2xxx_probe_one, |
2537 | .remove = __devexit_p(qla2xxx_remove_one), | 2657 | .remove = __devexit_p(qla2xxx_remove_one), |
@@ -2556,6 +2676,9 @@ qla2x00_module_init(void) | |||
2556 | 2676 | ||
2557 | /* Derive version string. */ | 2677 | /* Derive version string. */ |
2558 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); | 2678 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); |
2679 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
2680 | strcat(qla2x00_version_str, "-fw"); | ||
2681 | #endif | ||
2559 | #if DEBUG_QLA2100 | 2682 | #if DEBUG_QLA2100 |
2560 | strcat(qla2x00_version_str, "-debug"); | 2683 | strcat(qla2x00_version_str, "-debug"); |
2561 | #endif | 2684 | #endif |
@@ -2580,6 +2703,7 @@ static void __exit | |||
2580 | qla2x00_module_exit(void) | 2703 | qla2x00_module_exit(void) |
2581 | { | 2704 | { |
2582 | pci_unregister_driver(&qla2xxx_pci_driver); | 2705 | pci_unregister_driver(&qla2xxx_pci_driver); |
2706 | qla2x00_release_firmware(); | ||
2583 | kmem_cache_destroy(srb_cachep); | 2707 | kmem_cache_destroy(srb_cachep); |
2584 | fc_release_transport(qla2xxx_transport_template); | 2708 | fc_release_transport(qla2xxx_transport_template); |
2585 | } | 2709 | } |