diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 13:24:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 13:24:49 -0700 |
commit | 22eb5aa6c7940861f9603581665b9d9a1c60be30 (patch) | |
tree | 22890bcebae5647bcc1a29e7b544a1c5de2b1f8b /drivers/scsi/qlogicpti.c | |
parent | d7ca6f8cdffa5765e486edb3dada9121fba8e6aa (diff) | |
parent | 015640edb1f346e0b2eda703587c4cd1c310ec1d (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (74 commits)
[SCSI] sg: fix q->queue_lock on scsi_error_handler path
[SCSI] replace __inline with inline
[SCSI] a2091: make 2 functions static
[SCSI] a3000: make 2 functions static
[SCSI] ses: #if 0 the unused ses_match_host()
[SCSI] use kmem_cache_zalloc instead of kmem_cache_alloc/memset
[SCSI] sg: fix iovec bugs introduced by the block layer conversion
[SCSI] qlogicpti: use request_firmware
[SCSI] advansys: use request_firmware
[SCSI] qla1280: use request_firmware
[SCSI] libiscsi: fix iscsi pool error path
[SCSI] cxgb3i: call ddp release function directly
[SCSI] cxgb3i: merge cxgb3i_ddp into cxgb3i module
[SCSI] cxgb3i: close all tcp connections upon chip reset
[SCSI] cxgb3i: re-read ddp settings information after chip reset
[SCSI] cxgb3i: re-initialize ddp settings after chip reset
[SCSI] cxgb3i: subscribe to error notification from cxgb3 driver
[SCSI] aacraid driver update
[SCSI] mptsas: remove unneeded check
[SCSI] config: Make need for SCSI_CDROM clearer
...
Diffstat (limited to 'drivers/scsi/qlogicpti.c')
-rw-r--r-- | drivers/scsi/qlogicpti.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 69d6ad862b6..fa34b92850a 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -28,6 +28,7 @@ #include <linux/dma-mapping.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/firmware.h> #include <asm/byteorder.h> @@ -53,8 +54,6 @@ #define DEFAULT_LOOP_COUNT 10000 -#include "qlogicpti_asm.c" - static struct qlogicpti *qptichain = NULL; static DEFINE_SPINLOCK(qptichain_lock); @@ -465,16 +464,32 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) { + const struct firmware *fw; + const char fwname[] = "qlogic/isp1000.bin"; + const __le16 *fw_data; struct Scsi_Host *host = qpti->qhost; unsigned short csum = 0; unsigned short param[6]; - unsigned short *risc_code, risc_code_addr, risc_code_length; + unsigned short risc_code_addr, risc_code_length; + int err; unsigned long flags; int i, timeout; - risc_code = &sbus_risc_code01[0]; + err = request_firmware(&fw, fwname, &qpti->op->dev); + if (err) { + printk(KERN_ERR "Failed to load image \"%s\" err %d\n", + fwname, err); + return err; + } + if (fw->size % 2) { + printk(KERN_ERR "Bogus length %zu in image \"%s\"\n", + fw->size, fwname); + err = -EINVAL; + goto outfirm; + } + fw_data = (const __le16 *)&fw->data[0]; risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */ - risc_code_length = sbus_risc_code_length01; + risc_code_length = fw->size / 2; spin_lock_irqsave(host->host_lock, flags); @@ -482,12 +497,12 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) * afterwards via the mailbox commands. */ for (i = 0; i < risc_code_length; i++) - csum += risc_code[i]; + csum += __le16_to_cpu(fw_data[i]); if (csum) { - spin_unlock_irqrestore(host->host_lock, flags); printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!", qpti->qpti_id); - return 1; + err = 1; + goto out; } sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); @@ -496,9 +511,9 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET)) udelay(20); if (!timeout) { - spin_unlock_irqrestore(host->host_lock, flags); printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id); - return 1; + err = 1; + goto out; } sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL); @@ -536,21 +551,21 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n", qpti->qpti_id); - spin_unlock_irqrestore(host->host_lock, flags); - return 1; + err = 1; + goto out; } /* Load it up.. */ for (i = 0; i < risc_code_length; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr + i; - param[2] = risc_code[i]; + param[2] = __le16_to_cpu(fw_data[i]); if (qlogicpti_mbox_command(qpti, param, 1) || param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", qpti->qpti_id); - spin_unlock_irqrestore(host->host_lock, flags); - return 1; + err = 1; + goto out; } } @@ -569,8 +584,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n", qpti->qpti_id); - spin_unlock_irqrestore(host->host_lock, flags); - return 1; + err = 1; + goto out; } /* Start using newly downloaded firmware. */ @@ -583,8 +598,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n", qpti->qpti_id); - spin_unlock_irqrestore(host->host_lock, flags); - return 1; + err = 1; + goto out; } /* Snag the major and minor revisions from the result. */ @@ -599,8 +614,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n", qpti->qpti_id); - spin_unlock_irqrestore(host->host_lock, flags); - return 1; + err = 1; + goto out; } if (qpti->is_pti != 0) { @@ -616,8 +631,11 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) qlogicpti_mbox_command(qpti, param, 1); } +out: spin_unlock_irqrestore(host->host_lock, flags); - return 0; +outfirm: + release_firmware(fw); + return err; } static int qlogicpti_verify_tmon(struct qlogicpti *qpti) @@ -1458,6 +1476,7 @@ MODULE_DESCRIPTION("QlogicISP SBUS driver"); MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_LICENSE("GPL"); MODULE_VERSION("2.1"); +MODULE_FIRMWARE("qlogic/isp1000.bin"); module_init(qpti_init); module_exit(qpti_exit); |