diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 196 |
1 files changed, 148 insertions, 48 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c58c9d97b041..24304300d7b5 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -54,10 +54,12 @@ 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; | 57 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) |
58 | module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); | 58 | int ql2xfwloadflash; |
59 | MODULE_PARM_DESC(ql2xfwloadbin, | 59 | module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR); |
60 | "Load ISP2xxx firmware image via hotplug."); | 60 | MODULE_PARM_DESC(ql2xfwloadflash, |
61 | "Load ISP24xx firmware image from FLASH (onboard memory)."); | ||
62 | #endif | ||
61 | 63 | ||
62 | static void qla2x00_free_device(scsi_qla_host_t *); | 64 | static void qla2x00_free_device(scsi_qla_host_t *); |
63 | 65 | ||
@@ -1261,12 +1263,16 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1261 | char pci_info[20]; | 1263 | char pci_info[20]; |
1262 | char fw_str[30]; | 1264 | char fw_str[30]; |
1263 | fc_port_t *fcport; | 1265 | fc_port_t *fcport; |
1266 | struct scsi_host_template *sht; | ||
1264 | 1267 | ||
1265 | if (pci_enable_device(pdev)) | 1268 | if (pci_enable_device(pdev)) |
1266 | goto probe_out; | 1269 | goto probe_out; |
1267 | 1270 | ||
1268 | host = scsi_host_alloc(brd_info->sht ? brd_info->sht: | 1271 | sht = &qla2x00_driver_template; |
1269 | &qla2x00_driver_template, sizeof(scsi_qla_host_t)); | 1272 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || |
1273 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) | ||
1274 | sht = &qla24xx_driver_template; | ||
1275 | host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); | ||
1270 | if (host == NULL) { | 1276 | if (host == NULL) { |
1271 | printk(KERN_WARNING | 1277 | printk(KERN_WARNING |
1272 | "qla2xxx: Couldn't allocate host from scsi layer!\n"); | 1278 | "qla2xxx: Couldn't allocate host from scsi layer!\n"); |
@@ -1291,8 +1297,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1291 | goto probe_failed; | 1297 | goto probe_failed; |
1292 | 1298 | ||
1293 | qla_printk(KERN_INFO, ha, | 1299 | qla_printk(KERN_INFO, ha, |
1294 | "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name, | 1300 | "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, |
1295 | pdev->irq, ha->iobase); | 1301 | ha->iobase); |
1296 | 1302 | ||
1297 | spin_lock_init(&ha->hardware_lock); | 1303 | spin_lock_init(&ha->hardware_lock); |
1298 | 1304 | ||
@@ -1368,9 +1374,11 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1368 | ha->isp_ops.reset_adapter = qla24xx_reset_adapter; | 1374 | ha->isp_ops.reset_adapter = qla24xx_reset_adapter; |
1369 | ha->isp_ops.nvram_config = qla24xx_nvram_config; | 1375 | ha->isp_ops.nvram_config = qla24xx_nvram_config; |
1370 | ha->isp_ops.update_fw_options = qla24xx_update_fw_options; | 1376 | ha->isp_ops.update_fw_options = qla24xx_update_fw_options; |
1371 | ha->isp_ops.load_risc = qla24xx_load_risc_flash; | 1377 | ha->isp_ops.load_risc = qla24xx_load_risc; |
1372 | if (ql2xfwloadbin) | 1378 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) |
1373 | ha->isp_ops.load_risc = qla24xx_load_risc_hotplug; | 1379 | if (ql2xfwloadflash) |
1380 | ha->isp_ops.load_risc = qla24xx_load_risc_flash; | ||
1381 | #endif | ||
1374 | ha->isp_ops.pci_info_str = qla24xx_pci_info_str; | 1382 | ha->isp_ops.pci_info_str = qla24xx_pci_info_str; |
1375 | ha->isp_ops.fw_version_str = qla24xx_fw_version_str; | 1383 | ha->isp_ops.fw_version_str = qla24xx_fw_version_str; |
1376 | ha->isp_ops.intr_handler = qla24xx_intr_handler; | 1384 | ha->isp_ops.intr_handler = qla24xx_intr_handler; |
@@ -1531,11 +1539,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) | |||
1531 | qla_printk(KERN_INFO, ha, "\n" | 1539 | qla_printk(KERN_INFO, ha, "\n" |
1532 | " QLogic Fibre Channel HBA Driver: %s\n" | 1540 | " QLogic Fibre Channel HBA Driver: %s\n" |
1533 | " QLogic %s - %s\n" | 1541 | " QLogic %s - %s\n" |
1534 | " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, | 1542 | " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", |
1535 | ha->model_number, ha->model_desc ? ha->model_desc: "", | 1543 | qla2x00_version_str, ha->model_number, |
1536 | ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info), | 1544 | ha->model_desc ? ha->model_desc: "", pdev->device, |
1537 | pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-', | 1545 | 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)); | 1546 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, |
1547 | ha->isp_ops.fw_version_str(ha, fw_str)); | ||
1539 | 1548 | ||
1540 | /* Go with fc_rport registration. */ | 1549 | /* Go with fc_rport registration. */ |
1541 | list_for_each_entry(fcport, &ha->fcports, list) | 1550 | list_for_each_entry(fcport, &ha->fcports, list) |
@@ -2483,45 +2492,115 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) | |||
2483 | return -ETIMEDOUT; | 2492 | return -ETIMEDOUT; |
2484 | } | 2493 | } |
2485 | 2494 | ||
2486 | static struct qla_board_info qla_board_tbl[] = { | 2495 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) |
2487 | { | 2496 | |
2488 | .drv_name = "qla2400", | 2497 | #define qla2x00_release_firmware() do { } while (0) |
2489 | .isp_name = "ISP2422", | 2498 | #define qla2x00_pci_module_init() (0) |
2490 | .fw_fname = "ql2400_fw.bin", | 2499 | #define qla2x00_pci_module_exit() do { } while (0) |
2491 | .sht = &qla24xx_driver_template, | 2500 | |
2492 | }, | 2501 | #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ |
2493 | { | 2502 | |
2494 | .drv_name = "qla2400", | 2503 | /* Firmware interface routines. */ |
2495 | .isp_name = "ISP2432", | 2504 | |
2496 | .fw_fname = "ql2400_fw.bin", | 2505 | #define FW_BLOBS 6 |
2497 | .sht = &qla24xx_driver_template, | 2506 | #define FW_ISP21XX 0 |
2498 | }, | 2507 | #define FW_ISP22XX 1 |
2508 | #define FW_ISP2300 2 | ||
2509 | #define FW_ISP2322 3 | ||
2510 | #define FW_ISP63XX 4 | ||
2511 | #define FW_ISP24XX 5 | ||
2512 | |||
2513 | static DECLARE_MUTEX(qla_fw_lock); | ||
2514 | |||
2515 | static struct fw_blob qla_fw_blobs[FW_BLOBS] = { | ||
2516 | { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, }, | ||
2517 | { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, | ||
2518 | { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, | ||
2519 | { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, | ||
2520 | { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, }, | ||
2521 | { .name = "ql2400_fw.bin", }, | ||
2522 | }; | ||
2523 | |||
2524 | struct fw_blob * | ||
2525 | qla2x00_request_firmware(scsi_qla_host_t *ha) | ||
2526 | { | ||
2527 | struct fw_blob *blob; | ||
2528 | |||
2529 | blob = NULL; | ||
2530 | if (IS_QLA2100(ha)) { | ||
2531 | blob = &qla_fw_blobs[FW_ISP21XX]; | ||
2532 | } else if (IS_QLA2200(ha)) { | ||
2533 | blob = &qla_fw_blobs[FW_ISP22XX]; | ||
2534 | } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) { | ||
2535 | blob = &qla_fw_blobs[FW_ISP2300]; | ||
2536 | } else if (IS_QLA2322(ha)) { | ||
2537 | blob = &qla_fw_blobs[FW_ISP2322]; | ||
2538 | } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { | ||
2539 | blob = &qla_fw_blobs[FW_ISP63XX]; | ||
2540 | } else if (IS_QLA24XX(ha)) { | ||
2541 | blob = &qla_fw_blobs[FW_ISP24XX]; | ||
2542 | } | ||
2543 | |||
2544 | down(&qla_fw_lock); | ||
2545 | if (blob->fw) | ||
2546 | goto out; | ||
2547 | |||
2548 | if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { | ||
2549 | DEBUG2(printk("scsi(%ld): Failed to load firmware image " | ||
2550 | "(%s).\n", ha->host_no, blob->name)); | ||
2551 | blob->fw = NULL; | ||
2552 | blob = NULL; | ||
2553 | goto out; | ||
2554 | } | ||
2555 | |||
2556 | out: | ||
2557 | up(&qla_fw_lock); | ||
2558 | return blob; | ||
2559 | } | ||
2560 | |||
2561 | static void | ||
2562 | qla2x00_release_firmware(void) | ||
2563 | { | ||
2564 | int idx; | ||
2565 | |||
2566 | down(&qla_fw_lock); | ||
2567 | for (idx = 0; idx < FW_BLOBS; idx++) | ||
2568 | if (qla_fw_blobs[idx].fw) | ||
2569 | release_firmware(qla_fw_blobs[idx].fw); | ||
2570 | up(&qla_fw_lock); | ||
2571 | } | ||
2572 | |||
2573 | static struct qla_board_info qla_board_tbl = { | ||
2574 | .drv_name = "qla2xxx", | ||
2499 | }; | 2575 | }; |
2500 | 2576 | ||
2501 | static struct pci_device_id qla2xxx_pci_tbl[] = { | 2577 | static struct pci_device_id qla2xxx_pci_tbl[] = { |
2502 | { | 2578 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, |
2503 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2579 | PCI_ANY_ID, PCI_ANY_ID, }, |
2504 | .device = PCI_DEVICE_ID_QLOGIC_ISP2422, | 2580 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, |
2505 | .subvendor = PCI_ANY_ID, | 2581 | PCI_ANY_ID, PCI_ANY_ID, }, |
2506 | .subdevice = PCI_ANY_ID, | 2582 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300, |
2507 | .driver_data = (unsigned long)&qla_board_tbl[0], | 2583 | PCI_ANY_ID, PCI_ANY_ID, }, |
2508 | }, | 2584 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312, |
2509 | { | 2585 | PCI_ANY_ID, PCI_ANY_ID, }, |
2510 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2586 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322, |
2511 | .device = PCI_DEVICE_ID_QLOGIC_ISP2432, | 2587 | PCI_ANY_ID, PCI_ANY_ID, }, |
2512 | .subvendor = PCI_ANY_ID, | 2588 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312, |
2513 | .subdevice = PCI_ANY_ID, | 2589 | PCI_ANY_ID, PCI_ANY_ID, }, |
2514 | .driver_data = (unsigned long)&qla_board_tbl[1], | 2590 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322, |
2515 | }, | 2591 | PCI_ANY_ID, PCI_ANY_ID, }, |
2516 | {0, 0}, | 2592 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422, |
2593 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2594 | { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, | ||
2595 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
2596 | { 0 }, | ||
2517 | }; | 2597 | }; |
2518 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); | 2598 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); |
2519 | 2599 | ||
2520 | static int __devinit | 2600 | static int __devinit |
2521 | qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | 2601 | qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) |
2522 | { | 2602 | { |
2523 | return qla2x00_probe_one(pdev, | 2603 | return qla2x00_probe_one(pdev, &qla_board_tbl); |
2524 | (struct qla_board_info *)id->driver_data); | ||
2525 | } | 2604 | } |
2526 | 2605 | ||
2527 | static void __devexit | 2606 | static void __devexit |
@@ -2532,11 +2611,28 @@ qla2xxx_remove_one(struct pci_dev *pdev) | |||
2532 | 2611 | ||
2533 | static struct pci_driver qla2xxx_pci_driver = { | 2612 | static struct pci_driver qla2xxx_pci_driver = { |
2534 | .name = "qla2xxx", | 2613 | .name = "qla2xxx", |
2614 | .driver = { | ||
2615 | .owner = THIS_MODULE, | ||
2616 | }, | ||
2535 | .id_table = qla2xxx_pci_tbl, | 2617 | .id_table = qla2xxx_pci_tbl, |
2536 | .probe = qla2xxx_probe_one, | 2618 | .probe = qla2xxx_probe_one, |
2537 | .remove = __devexit_p(qla2xxx_remove_one), | 2619 | .remove = __devexit_p(qla2xxx_remove_one), |
2538 | }; | 2620 | }; |
2539 | 2621 | ||
2622 | static inline int | ||
2623 | qla2x00_pci_module_init(void) | ||
2624 | { | ||
2625 | return pci_module_init(&qla2xxx_pci_driver); | ||
2626 | } | ||
2627 | |||
2628 | static inline void | ||
2629 | qla2x00_pci_module_exit(void) | ||
2630 | { | ||
2631 | pci_unregister_driver(&qla2xxx_pci_driver); | ||
2632 | } | ||
2633 | |||
2634 | #endif | ||
2635 | |||
2540 | /** | 2636 | /** |
2541 | * qla2x00_module_init - Module initialization. | 2637 | * qla2x00_module_init - Module initialization. |
2542 | **/ | 2638 | **/ |
@@ -2556,6 +2652,9 @@ qla2x00_module_init(void) | |||
2556 | 2652 | ||
2557 | /* Derive version string. */ | 2653 | /* Derive version string. */ |
2558 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); | 2654 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); |
2655 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
2656 | strcat(qla2x00_version_str, "-fw"); | ||
2657 | #endif | ||
2559 | #if DEBUG_QLA2100 | 2658 | #if DEBUG_QLA2100 |
2560 | strcat(qla2x00_version_str, "-debug"); | 2659 | strcat(qla2x00_version_str, "-debug"); |
2561 | #endif | 2660 | #endif |
@@ -2565,7 +2664,7 @@ qla2x00_module_init(void) | |||
2565 | return -ENODEV; | 2664 | return -ENODEV; |
2566 | 2665 | ||
2567 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); | 2666 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); |
2568 | ret = pci_module_init(&qla2xxx_pci_driver); | 2667 | ret = qla2x00_pci_module_init(); |
2569 | if (ret) { | 2668 | if (ret) { |
2570 | kmem_cache_destroy(srb_cachep); | 2669 | kmem_cache_destroy(srb_cachep); |
2571 | fc_release_transport(qla2xxx_transport_template); | 2670 | fc_release_transport(qla2xxx_transport_template); |
@@ -2579,7 +2678,8 @@ qla2x00_module_init(void) | |||
2579 | static void __exit | 2678 | static void __exit |
2580 | qla2x00_module_exit(void) | 2679 | qla2x00_module_exit(void) |
2581 | { | 2680 | { |
2582 | pci_unregister_driver(&qla2xxx_pci_driver); | 2681 | qla2x00_pci_module_exit(); |
2682 | qla2x00_release_firmware(); | ||
2583 | kmem_cache_destroy(srb_cachep); | 2683 | kmem_cache_destroy(srb_cachep); |
2584 | fc_release_transport(qla2xxx_transport_template); | 2684 | fc_release_transport(qla2xxx_transport_template); |
2585 | } | 2685 | } |