aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c196
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);
54MODULE_PARM_DESC(ql2xloginretrycount, 54MODULE_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
57int ql2xfwloadbin=1; 57#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
58module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); 58int ql2xfwloadflash;
59MODULE_PARM_DESC(ql2xfwloadbin, 59module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR);
60 "Load ISP2xxx firmware image via hotplug."); 60MODULE_PARM_DESC(ql2xfwloadflash,
61 "Load ISP24xx firmware image from FLASH (onboard memory).");
62#endif
61 63
62static void qla2x00_free_device(scsi_qla_host_t *); 64static 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
2486static 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
2513static DECLARE_MUTEX(qla_fw_lock);
2514
2515static 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
2524struct fw_blob *
2525qla2x00_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
2556out:
2557 up(&qla_fw_lock);
2558 return blob;
2559}
2560
2561static void
2562qla2x00_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
2573static struct qla_board_info qla_board_tbl = {
2574 .drv_name = "qla2xxx",
2499}; 2575};
2500 2576
2501static struct pci_device_id qla2xxx_pci_tbl[] = { 2577static 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};
2518MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); 2598MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
2519 2599
2520static int __devinit 2600static int __devinit
2521qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) 2601qla2xxx_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
2527static void __devexit 2606static void __devexit
@@ -2532,11 +2611,28 @@ qla2xxx_remove_one(struct pci_dev *pdev)
2532 2611
2533static struct pci_driver qla2xxx_pci_driver = { 2612static 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
2622static inline int
2623qla2x00_pci_module_init(void)
2624{
2625 return pci_module_init(&qla2xxx_pci_driver);
2626}
2627
2628static inline void
2629qla2x00_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)
2579static void __exit 2678static void __exit
2580qla2x00_module_exit(void) 2679qla2x00_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}