diff options
Diffstat (limited to 'drivers/scsi/qlogicpti.c')
| -rw-r--r-- | drivers/scsi/qlogicpti.c | 139 |
1 files changed, 79 insertions, 60 deletions
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 69d6ad862b6..6d48d30bed0 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -16,7 +16,7 @@ #include <linux/delay.h> #include <linux/types.h> #include <linux/string.h> -#include <linux/slab.h> +#include <linux/gfp.h> #include <linux/blkdev.h> #include <linux/proc_fs.h> #include <linux/stat.h> @@ -28,13 +28,13 @@ #include <linux/dma-mapping.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/firmware.h> #include <asm/byteorder.h> #include "qlogicpti.h" #include <asm/dma.h> -#include <asm/system.h> #include <asm/ptrace.h> #include <asm/pgtable.h> #include <asm/oplib.h> @@ -53,8 +53,6 @@ #define DEFAULT_LOOP_COUNT 10000 -#include "qlogicpti_asm.c" - static struct qlogicpti *qptichain = NULL; static DEFINE_SPINLOCK(qptichain_lock); @@ -463,18 +461,34 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) #define PTI_RESET_LIMIT 400 -static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) +static int 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 +496,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 +510,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 +550,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 +583,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 +597,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 +613,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 +630,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) @@ -653,7 +670,7 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti) static irqreturn_t qpti_intr(int irq, void *dev_id); -static void __devinit qpti_chain_add(struct qlogicpti *qpti) +static void qpti_chain_add(struct qlogicpti *qpti) { spin_lock_irq(&qptichain_lock); if (qptichain != NULL) { @@ -669,7 +686,7 @@ static void __devinit qpti_chain_add(struct qlogicpti *qpti) spin_unlock_irq(&qptichain_lock); } -static void __devexit qpti_chain_del(struct qlogicpti *qpti) +static void qpti_chain_del(struct qlogicpti *qpti) { spin_lock_irq(&qptichain_lock); if (qptichain == qpti) { @@ -684,9 +701,9 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) spin_unlock_irq(&qptichain_lock); } -static int __devinit qpti_map_regs(struct qlogicpti *qpti) +static int qpti_map_regs(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qregs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), @@ -707,11 +724,11 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) return 0; } -static int __devinit qpti_register_irq(struct qlogicpti *qpti) +static int qpti_register_irq(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; - qpti->qhost->irq = qpti->irq = op->irqs[0]; + qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; /* We used to try various overly-clever things to * reduce the interrupt processing overhead on @@ -720,7 +737,7 @@ static int __devinit qpti_register_irq(struct qlogicpti *qpti) * sanely maintain. */ if (request_irq(qpti->irq, qpti_intr, - IRQF_SHARED, "Qlogic/PTI", qpti)) + IRQF_SHARED, "QlogicPTI", qpti)) goto fail; printk("qlogicpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); @@ -732,12 +749,12 @@ fail: return -1; } -static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) +static void qpti_get_scsi_id(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; struct device_node *dp; - dp = op->node; + dp = op->dev.of_node; qpti->scsi_id = of_getintprop_default(dp, "initiator-id", -1); if (qpti->scsi_id == -1) @@ -755,11 +772,11 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) static void qpti_get_bursts(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; u8 bursts, bmask; - bursts = of_getintprop_default(op->node, "burst-sizes", 0xff); - bmask = of_getintprop_default(op->node->parent, "burst-sizes", 0xff); + bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); + bmask = of_getintprop_default(op->dev.of_node->parent, "burst-sizes", 0xff); if (bmask != 0xff) bursts &= bmask; if (bursts == 0xff || @@ -786,9 +803,9 @@ static void qpti_get_clock(struct qlogicpti *qpti) /* The request and response queues must each be aligned * on a page boundary. */ -static int __devinit qpti_map_queues(struct qlogicpti *qpti) +static int qpti_map_queues(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) qpti->res_cpu = dma_alloc_coherent(&op->dev, @@ -862,7 +879,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd, cmd->control_flags |= CFLAG_WRITE; else cmd->control_flags |= CFLAG_READ; - cmd->time_out = 30; + cmd->time_out = Cmnd->request->timeout/HZ; memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); } @@ -985,7 +1002,7 @@ static int qlogicpti_slave_configure(struct scsi_device *sdev) * * "This code must fly." -davem */ -static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *)) +static int qlogicpti_queuecommand_lck(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *)) { struct Scsi_Host *host = Cmnd->device->host; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; @@ -1034,6 +1051,8 @@ toss_command: return 1; } +static DEF_SCSI_QCMD(qlogicpti_queuecommand) + static int qlogicpti_return_status(struct Status_Entry *sts, int id) { int host_status = DID_ERROR; @@ -1272,10 +1291,10 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) +static const struct of_device_id qpti_match[]; +static int qpti_sbus_probe(struct platform_device *op) { - struct scsi_host_template *tpnt = match->data; - struct device_node *dp = op->node; + struct device_node *dp = op->dev.of_node; struct Scsi_Host *host; struct qlogicpti *qpti; static int nqptis; @@ -1284,10 +1303,10 @@ static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_devic /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ - if (op->irqs[0] == 0) + if (op->archdata.irqs[0] == 0) return -ENODEV; - host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); + host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti)); if (!host) return -ENOMEM; @@ -1297,7 +1316,7 @@ static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_devic qpti->qhost = host; qpti->op = op; qpti->qpti_id = nqptis; - strcpy(qpti->prom_name, op->node->name); + strcpy(qpti->prom_name, op->dev.of_node->name); qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); if (qpti_map_regs(qpti) < 0) @@ -1383,7 +1402,7 @@ fail_unlink: return -ENODEV; } -static int __devexit qpti_sbus_remove(struct of_device *op) +static int qpti_sbus_remove(struct platform_device *op) { struct qlogicpti *qpti = dev_get_drvdata(&op->dev); @@ -1419,45 +1438,45 @@ static int __devexit qpti_sbus_remove(struct of_device *op) static const struct of_device_id qpti_match[] = { { .name = "ptisp", - .data = &qpti_template, }, { .name = "PTI,ptisp", - .data = &qpti_template, }, { .name = "QLGC,isp", - .data = &qpti_template, }, { .name = "SUNW,isp", - .data = &qpti_template, }, {}, }; MODULE_DEVICE_TABLE(of, qpti_match); -static struct of_platform_driver qpti_sbus_driver = { - .name = "qpti", - .match_table = qpti_match, +static struct platform_driver qpti_sbus_driver = { + .driver = { + .name = "qpti", + .owner = THIS_MODULE, + .of_match_table = qpti_match, + }, .probe = qpti_sbus_probe, - .remove = __devexit_p(qpti_sbus_remove), + .remove = qpti_sbus_remove, }; static int __init qpti_init(void) { - return of_register_driver(&qpti_sbus_driver, &of_bus_type); + return platform_driver_register(&qpti_sbus_driver); } static void __exit qpti_exit(void) { - of_unregister_driver(&qpti_sbus_driver); + platform_driver_unregister(&qpti_sbus_driver); } 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); |
