diff options
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 69d6ad8..fa34b92 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); |