diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2005-11-10 00:49:04 +0100 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-12-14 02:11:16 +0100 |
commit | 5433383ef33ed40c9c8a86a4355da344234af2a5 (patch) | |
tree | 8d82c620fe6faadfa805fb465d5beb67946133c7 /drivers/scsi/qla2xxx/qla_os.c | |
parent | [SCSI] scsi_lib: stricter checks for clearing use_10_for_rw (diff) | |
download | linux-5433383ef33ed40c9c8a86a4355da344234af2a5.tar.xz linux-5433383ef33ed40c9c8a86a4355da344234af2a5.zip |
[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); MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); -int ql2xfwloadbin=1; -module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xfwloadbin, - "Load ISP2xxx firmware image via hotplug."); - static void qla2x00_free_device(scsi_qla_host_t *); 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) char pci_info[20]; char fw_str[30]; fc_port_t *fcport; + struct scsi_host_template *sht; if (pci_enable_device(pdev)) goto probe_out; - host = scsi_host_alloc(brd_info->sht ? brd_info->sht: - &qla2x00_driver_template, sizeof(scsi_qla_host_t)); + sht = &qla2x00_driver_template; + if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) + sht = &qla24xx_driver_template; + host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); if (host == NULL) { printk(KERN_WARNING "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) goto probe_failed; qla_printk(KERN_INFO, ha, - "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name, - pdev->irq, ha->iobase); + "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, + ha->iobase); spin_lock_init(&ha->hardware_lock); @@ -1368,9 +1367,11 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.reset_adapter = qla24xx_reset_adapter; ha->isp_ops.nvram_config = qla24xx_nvram_config; ha->isp_ops.update_fw_options = qla24xx_update_fw_options; +#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) ha->isp_ops.load_risc = qla24xx_load_risc_flash; - if (ql2xfwloadbin) - ha->isp_ops.load_risc = qla24xx_load_risc_hotplug; +#else + ha->isp_ops.load_risc = qla24xx_load_risc; +#endif ha->isp_ops.pci_info_str = qla24xx_pci_info_str; ha->isp_ops.fw_version_str = qla24xx_fw_version_str; 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) qla_printk(KERN_INFO, ha, "\n" " QLogic Fibre Channel HBA Driver: %s\n" " QLogic %s - %s\n" - " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, - ha->model_number, ha->model_desc ? ha->model_desc: "", - ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info), - pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-', - ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str)); + " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", + qla2x00_version_str, ha->model_number, + ha->model_desc ? ha->model_desc: "", pdev->device, + ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev), + ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, + ha->isp_ops.fw_version_str(ha, fw_str)); /* Go with fc_rport registration. */ list_for_each_entry(fcport, &ha->fcports, list) @@ -2483,6 +2485,10 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) return -ETIMEDOUT; } +#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) + +#define qla2x00_release_firmware() do { } while (0) + static struct qla_board_info qla_board_tbl[] = { { .drv_name = "qla2400", @@ -2530,8 +2536,122 @@ qla2xxx_remove_one(struct pci_dev *pdev) qla2x00_remove_one(pdev); } +#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ + +/* Firmware interface routines. */ + +#define FW_BLOBS 6 +#define FW_ISP21XX 0 +#define FW_ISP22XX 1 +#define FW_ISP2300 2 +#define FW_ISP2322 3 +#define FW_ISP63XX 4 +#define FW_ISP24XX 5 + +static DECLARE_MUTEX(qla_fw_lock); + +static struct fw_blob qla_fw_blobs[FW_BLOBS] = { + { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, }, + { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, + { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, + { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, + { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, }, + { .name = "ql2400_fw.bin", }, +}; + +struct fw_blob * +qla2x00_request_firmware(scsi_qla_host_t *ha) +{ + struct fw_blob *blob; + + blob = NULL; + if (IS_QLA2100(ha)) { + blob = &qla_fw_blobs[FW_ISP21XX]; + } else if (IS_QLA2200(ha)) { + blob = &qla_fw_blobs[FW_ISP22XX]; + } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) { + blob = &qla_fw_blobs[FW_ISP2300]; + } else if (IS_QLA2322(ha)) { + blob = &qla_fw_blobs[FW_ISP2322]; + } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { + blob = &qla_fw_blobs[FW_ISP63XX]; + } else if (IS_QLA24XX(ha)) { + blob = &qla_fw_blobs[FW_ISP24XX]; + } + + down(&qla_fw_lock); + if (blob->fw) + goto out; + + if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { + DEBUG2(printk("scsi(%ld): Failed to load firmware image " + "(%s).\n", ha->host_no, blob->name)); + blob->fw = NULL; + blob = NULL; + goto out; + } + +out: + up(&qla_fw_lock); + return blob; +} + +static void +qla2x00_release_firmware(void) +{ + int idx; + + down(&qla_fw_lock); + for (idx = 0; idx < FW_BLOBS; idx++) + if (qla_fw_blobs[idx].fw) + release_firmware(qla_fw_blobs[idx].fw); + up(&qla_fw_lock); +} + +static struct qla_board_info qla_board_tbl = { + .drv_name = "qla2xxx", +}; + +static struct pci_device_id qla2xxx_pci_tbl[] = { + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, + PCI_ANY_ID, PCI_ANY_ID, }, + { 0 }, +}; +MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); + +static int __devinit +qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + return qla2x00_probe_one(pdev, &qla_board_tbl); +} + +static void __devexit +qla2xxx_remove_one(struct pci_dev *pdev) +{ + qla2x00_remove_one(pdev); +} + +#endif + static struct pci_driver qla2xxx_pci_driver = { .name = "qla2xxx", + .owner = THIS_MODULE, .id_table = qla2xxx_pci_tbl, .probe = qla2xxx_probe_one, .remove = __devexit_p(qla2xxx_remove_one), @@ -2556,6 +2676,9 @@ qla2x00_module_init(void) /* Derive version string. */ strcpy(qla2x00_version_str, QLA2XXX_VERSION); +#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) + strcat(qla2x00_version_str, "-fw"); +#endif #if DEBUG_QLA2100 strcat(qla2x00_version_str, "-debug"); #endif @@ -2580,6 +2703,7 @@ static void __exit qla2x00_module_exit(void) { pci_unregister_driver(&qla2xxx_pci_driver); + qla2x00_release_firmware(); kmem_cache_destroy(srb_cachep); fc_release_transport(qla2xxx_transport_template); } |