aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2005-11-09 18:49:04 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-13 20:11:16 -0500
commit5433383ef33ed40c9c8a86a4355da344234af2a5 (patch)
tree8d82c620fe6faadfa805fb465d5beb67946133c7 /drivers/scsi/qla2xxx
parent26a68019c86e1d1782984a7a5babff762cde1501 (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')
-rw-r--r--drivers/scsi/qla2xxx/Kconfig69
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h24
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c189
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c156
7 files changed, 348 insertions, 98 deletions
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index c1c1c687bcbd..5205c4e7d6ff 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,55 +1,70 @@
1config SCSI_QLA2XXX 1config SCSI_QLA2XXX
2 tristate 2 tristate "QLogic QLA2XXX Fibre Channel Support"
3 default (SCSI && PCI) 3 depends on PCI && SCSI
4 depends on SCSI && PCI 4 select SCSI_FC_ATTRS
5 select FW_LOADER
6 ---help---
7 This qla2xxx driver supports all QLogic Fibre Channel
8 PCI and PCIe host adapters.
5 9
6config SCSI_QLA21XX 10 By default, firmware for the ISP parts will be loaded
7 tristate "QLogic ISP2100 host adapter family support" 11 via the Firmware Loader interface.
12
13 ISP Firmware Filename
14 ---------- -----------------
15 21xx ql2100_fw.bin
16 22xx ql2200_fw.bin
17 2300, 2312 ql2300_fw.bin
18 2322 ql2322_fw.bin
19 6312, 6322 ql6312_fw.bin
20 24xx ql2400_fw.bin
21
22 Upon request, the driver caches the firmware image until
23 the driver is unloaded.
24
25 NOTE: The original method of building firmware-loader
26 modules has been deprecated as the firmware-images will
27 be removed from the kernel sources.
28
29config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
30 bool " Use firmware-loader modules (DEPRECATED)"
8 depends on SCSI_QLA2XXX 31 depends on SCSI_QLA2XXX
9 select SCSI_FC_ATTRS 32
10 select FW_LOADER 33config SCSI_QLA21XX
34 tristate " Build QLogic ISP2100 firmware-module"
35 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
11 ---help--- 36 ---help---
12 This driver supports the QLogic 21xx (ISP2100) host adapter family. 37 This driver supports the QLogic 21xx (ISP2100) host adapter family.
13 38
14config SCSI_QLA22XX 39config SCSI_QLA22XX
15 tristate "QLogic ISP2200 host adapter family support" 40 tristate " Build QLogic ISP2200 firmware-module"
16 depends on SCSI_QLA2XXX 41 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
17 select SCSI_FC_ATTRS
18 select FW_LOADER
19 ---help--- 42 ---help---
20 This driver supports the QLogic 22xx (ISP2200) host adapter family. 43 This driver supports the QLogic 22xx (ISP2200) host adapter family.
21 44
22config SCSI_QLA2300 45config SCSI_QLA2300
23 tristate "QLogic ISP2300 host adapter family support" 46 tristate " Build QLogic ISP2300 firmware-module"
24 depends on SCSI_QLA2XXX 47 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
25 select SCSI_FC_ATTRS
26 select FW_LOADER
27 ---help--- 48 ---help---
28 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host 49 This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
29 adapter family. 50 adapter family.
30 51
31config SCSI_QLA2322 52config SCSI_QLA2322
32 tristate "QLogic ISP2322 host adapter family support" 53 tristate " Build QLogic ISP2322 firmware-module"
33 depends on SCSI_QLA2XXX 54 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
34 select SCSI_FC_ATTRS
35 select FW_LOADER
36 ---help--- 55 ---help---
37 This driver supports the QLogic 2322 (ISP2322) host adapter family. 56 This driver supports the QLogic 2322 (ISP2322) host adapter family.
38 57
39config SCSI_QLA6312 58config SCSI_QLA6312
40 tristate "QLogic ISP63xx host adapter family support" 59 tristate " Build QLogic ISP63xx firmware-module"
41 depends on SCSI_QLA2XXX 60 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
42 select SCSI_FC_ATTRS
43 select FW_LOADER
44 ---help--- 61 ---help---
45 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host 62 This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
46 adapter family. 63 adapter family.
47 64
48config SCSI_QLA24XX 65config SCSI_QLA24XX
49 tristate "QLogic ISP24xx host adapter family support" 66 tristate " Build QLogic ISP24xx firmware-module"
50 depends on SCSI_QLA2XXX 67 depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
51 select SCSI_FC_ATTRS
52 select FW_LOADER
53 ---help--- 68 ---help---
54 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host 69 This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
55 adapter family. 70 adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index b169687d08ff..549dfe410208 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,6 +3,8 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o 4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
5 5
6obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o
7
6qla2100-y := ql2100.o ql2100_fw.o 8qla2100-y := ql2100.o ql2100_fw.o
7qla2200-y := ql2200.o ql2200_fw.o 9qla2200-y := ql2200.o ql2200_fw.o
8qla2300-y := ql2300.o ql2300_fw.o 10qla2300-y := ql2300.o ql2300_fw.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 48e460eef05a..2efca52dff50 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -232,7 +232,7 @@ static ssize_t
232qla2x00_isp_name_show(struct class_device *cdev, char *buf) 232qla2x00_isp_name_show(struct class_device *cdev, char *buf)
233{ 233{
234 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 234 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
235 return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name); 235 return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
236} 236}
237 237
238static ssize_t 238static ssize_t
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7096945ea234..ce0d88bbaa06 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -22,6 +22,7 @@
22#include <linux/completion.h> 22#include <linux/completion.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/firmware.h>
25#include <asm/semaphore.h> 26#include <asm/semaphore.h>
26 27
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
@@ -29,6 +30,7 @@
29#include <scsi/scsi_device.h> 30#include <scsi/scsi_device.h>
30#include <scsi/scsi_cmnd.h> 31#include <scsi/scsi_cmnd.h>
31 32
33#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
32#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE) 34#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
33#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100) 35#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
34#else 36#else
@@ -79,9 +81,23 @@
79#define IS_QLA2522(ha) 0 81#define IS_QLA2522(ha) 0
80#endif 82#endif
81 83
84#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
85
86#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
87#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200)
88#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300)
89#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312)
90#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322)
91#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312)
92#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322)
93#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
94#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
95#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
96#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
97#endif
98
82#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ 99#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
83 IS_QLA6312(ha) || IS_QLA6322(ha)) 100 IS_QLA6312(ha) || IS_QLA6322(ha))
84
85#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) 101#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
86#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha)) 102#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha))
87 103
@@ -2124,6 +2140,12 @@ struct qla_board_info {
2124 struct scsi_host_template *sht; 2140 struct scsi_host_template *sht;
2125}; 2141};
2126 2142
2143struct fw_blob {
2144 char *name;
2145 uint32_t segs[4];
2146 const struct firmware *fw;
2147};
2148
2127/* Return data from MBC_GET_ID_LIST call. */ 2149/* Return data from MBC_GET_ID_LIST call. */
2128struct gid_list_info { 2150struct gid_list_info {
2129 uint8_t al_pa; 2151 uint8_t al_pa;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fedcb0d3fc72..bec81adcf4fd 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -33,8 +33,8 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *);
33extern void qla2x00_update_fw_options(struct scsi_qla_host *); 33extern void qla2x00_update_fw_options(struct scsi_qla_host *);
34extern void qla24xx_update_fw_options(scsi_qla_host_t *); 34extern void qla24xx_update_fw_options(scsi_qla_host_t *);
35extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); 35extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
36extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
36extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *); 37extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
37extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
38 38
39extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t); 39extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
40 40
@@ -76,6 +76,8 @@ extern void qla2x00_blink_led(scsi_qla_host_t *);
76 76
77extern int qla2x00_down_timeout(struct semaphore *, unsigned long); 77extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
78 78
79extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
80
79/* 81/*
80 * Global Function Prototypes in qla_iocb.c source file. 82 * Global Function Prototypes in qla_iocb.c source file.
81 */ 83 */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 2d720121a0d3..13e2aaf56769 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
8 8
9#include <linux/delay.h> 9#include <linux/delay.h>
10#include <linux/vmalloc.h> 10#include <linux/vmalloc.h>
11#include <linux/firmware.h>
12#include <scsi/scsi_transport_fc.h> 11#include <scsi/scsi_transport_fc.h>
13 12
14#include "qla_devtbl.h" 13#include "qla_devtbl.h"
@@ -3484,17 +3483,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
3484 return (rval); 3483 return (rval);
3485} 3484}
3486 3485
3486#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
3487
3487int 3488int
3488qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) 3489qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3489{ 3490{
3490 int rval; 3491 int rval, num, i;
3491 uint16_t cnt; 3492 uint32_t cnt;
3492 uint16_t *risc_code; 3493 uint16_t *risc_code;
3493 unsigned long risc_address; 3494 uint32_t risc_addr, risc_size;
3494 unsigned long risc_code_size; 3495 uint16_t *req_ring;
3495 int num;
3496 int i;
3497 uint16_t *req_ring;
3498 struct qla_fw_info *fw_iter; 3496 struct qla_fw_info *fw_iter;
3499 3497
3500 rval = QLA_SUCCESS; 3498 rval = QLA_SUCCESS;
@@ -3504,37 +3502,29 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3504 *srisc_addr = *ha->brd_info->fw_info->fwstart; 3502 *srisc_addr = *ha->brd_info->fw_info->fwstart;
3505 while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { 3503 while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
3506 risc_code = fw_iter->fwcode; 3504 risc_code = fw_iter->fwcode;
3507 risc_code_size = *fw_iter->fwlen; 3505 risc_size = *fw_iter->fwlen;
3508 3506 if (fw_iter->addressing == FW_INFO_ADDR_NORMAL)
3509 if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { 3507 risc_addr = *fw_iter->fwstart;
3510 risc_address = *fw_iter->fwstart; 3508 else
3511 } else { 3509 risc_addr = *fw_iter->lfwstart;
3512 /* Extended address */
3513 risc_address = *fw_iter->lfwstart;
3514 }
3515 3510
3516 num = 0; 3511 num = 0;
3517 rval = 0; 3512 rval = 0;
3518 while (risc_code_size > 0 && !rval) { 3513 while (risc_size > 0 && !rval) {
3519 cnt = (uint16_t)(ha->fw_transfer_size >> 1); 3514 cnt = (uint16_t)(ha->fw_transfer_size >> 1);
3520 if (cnt > risc_code_size) 3515 if (cnt > risc_size)
3521 cnt = risc_code_size; 3516 cnt = risc_size;
3522 3517
3523 DEBUG7(printk("scsi(%ld): Loading risc segment@ " 3518 DEBUG7(printk("scsi(%ld): Loading risc segment@ "
3524 "addr %p, number of bytes 0x%x, offset 0x%lx.\n", 3519 "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
3525 ha->host_no, risc_code, cnt, risc_address)); 3520 ha->host_no, risc_code, cnt, risc_addr));
3526 3521
3527 req_ring = (uint16_t *)ha->request_ring; 3522 req_ring = (uint16_t *)ha->request_ring;
3528 for (i = 0; i < cnt; i++) 3523 for (i = 0; i < cnt; i++)
3529 req_ring[i] = cpu_to_le16(risc_code[i]); 3524 req_ring[i] = cpu_to_le16(risc_code[i]);
3530 3525
3531 if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { 3526 rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3532 rval = qla2x00_load_ram(ha, ha->request_dma, 3527 cnt);
3533 risc_address, cnt);
3534 } else {
3535 rval = qla2x00_load_ram_ext(ha,
3536 ha->request_dma, risc_address, cnt);
3537 }
3538 if (rval) { 3528 if (rval) {
3539 DEBUG(printk("scsi(%ld): [ERROR] Failed to " 3529 DEBUG(printk("scsi(%ld): [ERROR] Failed to "
3540 "load segment %d of firmware\n", 3530 "load segment %d of firmware\n",
@@ -3548,16 +3538,15 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3548 } 3538 }
3549 3539
3550 risc_code += cnt; 3540 risc_code += cnt;
3551 risc_address += cnt; 3541 risc_addr += cnt;
3552 risc_code_size -= cnt; 3542 risc_size -= cnt;
3553 num++; 3543 num++;
3554 } 3544 }
3555 3545
3556 /* Next firmware sequence */ 3546 /* Next firmware sequence */
3557 fw_iter++; 3547 fw_iter++;
3558 } 3548 }
3559 3549 return rval;
3560 return (rval);
3561} 3550}
3562 3551
3563int 3552int
@@ -3642,8 +3631,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3642 return rval; 3631 return rval;
3643} 3632}
3644 3633
3634#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
3635
3645int 3636int
3646qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) 3637qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3638{
3639 int rval;
3640 int i, fragment;
3641 uint16_t *wcode, *fwcode;
3642 uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
3643 struct fw_blob *blob;
3644
3645 /* Load firmware blob. */
3646 blob = qla2x00_request_firmware(ha);
3647 if (!blob) {
3648 qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
3649 return QLA_FUNCTION_FAILED;
3650 }
3651
3652 rval = QLA_SUCCESS;
3653
3654 wcode = (uint16_t *)ha->request_ring;
3655 *srisc_addr = 0;
3656 fwcode = (uint16_t *)blob->fw->data;
3657 fwclen = 0;
3658
3659 /* Validate firmware image by checking version. */
3660 if (blob->fw->size < 8 * sizeof(uint16_t)) {
3661 qla_printk(KERN_WARNING, ha,
3662 "Unable to verify integrity of firmware image (%Zd)!\n",
3663 blob->fw->size);
3664 goto fail_fw_integrity;
3665 }
3666 for (i = 0; i < 4; i++)
3667 wcode[i] = be16_to_cpu(fwcode[i + 4]);
3668 if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
3669 wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
3670 wcode[2] == 0 && wcode[3] == 0)) {
3671 qla_printk(KERN_WARNING, ha,
3672 "Unable to verify integrity of firmware image!\n");
3673 qla_printk(KERN_WARNING, ha,
3674 "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
3675 wcode[1], wcode[2], wcode[3]);
3676 goto fail_fw_integrity;
3677 }
3678
3679 seg = blob->segs;
3680 while (*seg && rval == QLA_SUCCESS) {
3681 risc_addr = *seg;
3682 *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
3683 risc_size = be16_to_cpu(fwcode[3]);
3684
3685 /* Validate firmware image size. */
3686 fwclen += risc_size * sizeof(uint16_t);
3687 if (blob->fw->size < fwclen) {
3688 qla_printk(KERN_WARNING, ha,
3689 "Unable to verify integrity of firmware image "
3690 "(%Zd)!\n", blob->fw->size);
3691 goto fail_fw_integrity;
3692 }
3693
3694 fragment = 0;
3695 while (risc_size > 0 && rval == QLA_SUCCESS) {
3696 wlen = (uint16_t)(ha->fw_transfer_size >> 1);
3697 if (wlen > risc_size)
3698 wlen = risc_size;
3699
3700 DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
3701 "addr %x, number of words 0x%x.\n", ha->host_no,
3702 risc_addr, wlen));
3703
3704 for (i = 0; i < wlen; i++)
3705 wcode[i] = swab16(fwcode[i]);
3706
3707 rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3708 wlen);
3709 if (rval) {
3710 DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
3711 "segment %d of firmware\n", ha->host_no,
3712 fragment));
3713 qla_printk(KERN_WARNING, ha,
3714 "[ERROR] Failed to load segment %d of "
3715 "firmware\n", fragment);
3716 break;
3717 }
3718
3719 fwcode += wlen;
3720 risc_addr += wlen;
3721 risc_size -= wlen;
3722 fragment++;
3723 }
3724
3725 /* Next segment. */
3726 seg++;
3727 }
3728 return rval;
3729
3730fail_fw_integrity:
3731 return QLA_FUNCTION_FAILED;
3732}
3733
3734int
3735qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3647{ 3736{
3648 int rval; 3737 int rval;
3649 int segments, fragment; 3738 int segments, fragment;
@@ -3651,14 +3740,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3651 uint32_t risc_addr; 3740 uint32_t risc_addr;
3652 uint32_t risc_size; 3741 uint32_t risc_size;
3653 uint32_t i; 3742 uint32_t i;
3654 const struct firmware *fw_entry; 3743 struct fw_blob *blob;
3655 uint32_t *fwcode, fwclen; 3744 uint32_t *fwcode, fwclen;
3656 3745
3657 if (request_firmware(&fw_entry, ha->brd_info->fw_fname, 3746 /* Load firmware blob. */
3658 &ha->pdev->dev)) { 3747 blob = qla2x00_request_firmware(ha);
3659 qla_printk(KERN_ERR, ha, 3748 if (!blob) {
3660 "Firmware image file not available: '%s'\n", 3749 qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
3661 ha->brd_info->fw_fname);
3662 return QLA_FUNCTION_FAILED; 3750 return QLA_FUNCTION_FAILED;
3663 } 3751 }
3664 3752
@@ -3667,14 +3755,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3667 segments = FA_RISC_CODE_SEGMENTS; 3755 segments = FA_RISC_CODE_SEGMENTS;
3668 dcode = (uint32_t *)ha->request_ring; 3756 dcode = (uint32_t *)ha->request_ring;
3669 *srisc_addr = 0; 3757 *srisc_addr = 0;
3670 fwcode = (uint32_t *)fw_entry->data; 3758 fwcode = (uint32_t *)blob->fw->data;
3671 fwclen = 0; 3759 fwclen = 0;
3672 3760
3673 /* Validate firmware image by checking version. */ 3761 /* Validate firmware image by checking version. */
3674 if (fw_entry->size < 8 * sizeof(uint32_t)) { 3762 if (blob->fw->size < 8 * sizeof(uint32_t)) {
3675 qla_printk(KERN_WARNING, ha, 3763 qla_printk(KERN_WARNING, ha,
3676 "Unable to verify integrity of flash firmware image " 3764 "Unable to verify integrity of firmware image (%Zd)!\n",
3677 "(%Zd)!\n", fw_entry->size); 3765 blob->fw->size);
3678 goto fail_fw_integrity; 3766 goto fail_fw_integrity;
3679 } 3767 }
3680 for (i = 0; i < 4; i++) 3768 for (i = 0; i < 4; i++)
@@ -3684,7 +3772,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3684 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && 3772 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
3685 dcode[3] == 0)) { 3773 dcode[3] == 0)) {
3686 qla_printk(KERN_WARNING, ha, 3774 qla_printk(KERN_WARNING, ha,
3687 "Unable to verify integrity of flash firmware image!\n"); 3775 "Unable to verify integrity of firmware image!\n");
3688 qla_printk(KERN_WARNING, ha, 3776 qla_printk(KERN_WARNING, ha,
3689 "Firmware data: %08x %08x %08x %08x!\n", dcode[0], 3777 "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
3690 dcode[1], dcode[2], dcode[3]); 3778 dcode[1], dcode[2], dcode[3]);
@@ -3698,10 +3786,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3698 3786
3699 /* Validate firmware image size. */ 3787 /* Validate firmware image size. */
3700 fwclen += risc_size * sizeof(uint32_t); 3788 fwclen += risc_size * sizeof(uint32_t);
3701 if (fw_entry->size < fwclen) { 3789 if (blob->fw->size < fwclen) {
3702 qla_printk(KERN_WARNING, ha, 3790 qla_printk(KERN_WARNING, ha,
3703 "Unable to verify integrity of flash firmware " 3791 "Unable to verify integrity of firmware image "
3704 "image (%Zd)!\n", fw_entry->size); 3792 "(%Zd)!\n", blob->fw->size);
3793
3705 goto fail_fw_integrity; 3794 goto fail_fw_integrity;
3706 } 3795 }
3707 3796
@@ -3739,13 +3828,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3739 /* Next segment. */ 3828 /* Next segment. */
3740 segments--; 3829 segments--;
3741 } 3830 }
3742
3743 release_firmware(fw_entry);
3744 return rval; 3831 return rval;
3745 3832
3746fail_fw_integrity: 3833fail_fw_integrity:
3747
3748 release_firmware(fw_entry);
3749 return QLA_FUNCTION_FAILED; 3834 return QLA_FUNCTION_FAILED;
3750
3751} 3835}
3836#endif
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);
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;
58module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
59MODULE_PARM_DESC(ql2xfwloadbin,
60 "Load ISP2xxx firmware image via hotplug.");
61
62static void qla2x00_free_device(scsi_qla_host_t *); 57static void qla2x00_free_device(scsi_qla_host_t *);
63 58
64static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); 59static 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
2486static struct qla_board_info qla_board_tbl[] = { 2492static 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
2551static DECLARE_MUTEX(qla_fw_lock);
2552
2553static 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
2562struct fw_blob *
2563qla2x00_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
2594out:
2595 up(&qla_fw_lock);
2596 return blob;
2597}
2598
2599static void
2600qla2x00_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
2611static struct qla_board_info qla_board_tbl = {
2612 .drv_name = "qla2xxx",
2613};
2614
2615static 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};
2636MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
2637
2638static int __devinit
2639qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2640{
2641 return qla2x00_probe_one(pdev, &qla_board_tbl);
2642}
2643
2644static void __devexit
2645qla2xxx_remove_one(struct pci_dev *pdev)
2646{
2647 qla2x00_remove_one(pdev);
2648}
2649
2650#endif
2651
2533static struct pci_driver qla2xxx_pci_driver = { 2652static 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
2580qla2x00_module_exit(void) 2703qla2x00_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}