aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qlogicpti.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qlogicpti.c')
-rw-r--r--drivers/scsi/qlogicpti.c63
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 @@
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/of.h> 29#include <linux/of.h>
30#include <linux/of_device.h> 30#include <linux/of_device.h>
31#include <linux/firmware.h>
31 32
32#include <asm/byteorder.h> 33#include <asm/byteorder.h>
33 34
@@ -53,8 +54,6 @@
53 54
54#define DEFAULT_LOOP_COUNT 10000 55#define DEFAULT_LOOP_COUNT 10000
55 56
56#include "qlogicpti_asm.c"
57
58static struct qlogicpti *qptichain = NULL; 57static struct qlogicpti *qptichain = NULL;
59static DEFINE_SPINLOCK(qptichain_lock); 58static DEFINE_SPINLOCK(qptichain_lock);
60 59
@@ -465,16 +464,32 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
465 464
466static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) 465static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
467{ 466{
467 const struct firmware *fw;
468 const char fwname[] = "qlogic/isp1000.bin";
469 const __le16 *fw_data;
468 struct Scsi_Host *host = qpti->qhost; 470 struct Scsi_Host *host = qpti->qhost;
469 unsigned short csum = 0; 471 unsigned short csum = 0;
470 unsigned short param[6]; 472 unsigned short param[6];
471 unsigned short *risc_code, risc_code_addr, risc_code_length; 473 unsigned short risc_code_addr, risc_code_length;
474 int err;
472 unsigned long flags; 475 unsigned long flags;
473 int i, timeout; 476 int i, timeout;
474 477
475 risc_code = &sbus_risc_code01[0]; 478 err = request_firmware(&fw, fwname, &qpti->op->dev);
479 if (err) {
480 printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
481 fwname, err);
482 return err;
483 }
484 if (fw->size % 2) {
485 printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
486 fw->size, fwname);
487 err = -EINVAL;
488 goto outfirm;
489 }
490 fw_data = (const __le16 *)&fw->data[0];
476 risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */ 491 risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */
477 risc_code_length = sbus_risc_code_length01; 492 risc_code_length = fw->size / 2;
478 493
479 spin_lock_irqsave(host->host_lock, flags); 494 spin_lock_irqsave(host->host_lock, flags);
480 495
@@ -482,12 +497,12 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
482 * afterwards via the mailbox commands. 497 * afterwards via the mailbox commands.
483 */ 498 */
484 for (i = 0; i < risc_code_length; i++) 499 for (i = 0; i < risc_code_length; i++)
485 csum += risc_code[i]; 500 csum += __le16_to_cpu(fw_data[i]);
486 if (csum) { 501 if (csum) {
487 spin_unlock_irqrestore(host->host_lock, flags);
488 printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!", 502 printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
489 qpti->qpti_id); 503 qpti->qpti_id);
490 return 1; 504 err = 1;
505 goto out;
491 } 506 }
492 sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); 507 sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL);
493 sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); 508 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)
496 while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET)) 511 while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET))
497 udelay(20); 512 udelay(20);
498 if (!timeout) { 513 if (!timeout) {
499 spin_unlock_irqrestore(host->host_lock, flags);
500 printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id); 514 printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id);
501 return 1; 515 err = 1;
516 goto out;
502 } 517 }
503 518
504 sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL); 519 sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL);
@@ -536,21 +551,21 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
536 if (qlogicpti_mbox_command(qpti, param, 1)) { 551 if (qlogicpti_mbox_command(qpti, param, 1)) {
537 printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n", 552 printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n",
538 qpti->qpti_id); 553 qpti->qpti_id);
539 spin_unlock_irqrestore(host->host_lock, flags); 554 err = 1;
540 return 1; 555 goto out;
541 } 556 }
542 557
543 /* Load it up.. */ 558 /* Load it up.. */
544 for (i = 0; i < risc_code_length; i++) { 559 for (i = 0; i < risc_code_length; i++) {
545 param[0] = MBOX_WRITE_RAM_WORD; 560 param[0] = MBOX_WRITE_RAM_WORD;
546 param[1] = risc_code_addr + i; 561 param[1] = risc_code_addr + i;
547 param[2] = risc_code[i]; 562 param[2] = __le16_to_cpu(fw_data[i]);
548 if (qlogicpti_mbox_command(qpti, param, 1) || 563 if (qlogicpti_mbox_command(qpti, param, 1) ||
549 param[0] != MBOX_COMMAND_COMPLETE) { 564 param[0] != MBOX_COMMAND_COMPLETE) {
550 printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", 565 printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
551 qpti->qpti_id); 566 qpti->qpti_id);
552 spin_unlock_irqrestore(host->host_lock, flags); 567 err = 1;
553 return 1; 568 goto out;
554 } 569 }
555 } 570 }
556 571
@@ -569,8 +584,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
569 (param[0] != MBOX_COMMAND_COMPLETE)) { 584 (param[0] != MBOX_COMMAND_COMPLETE)) {
570 printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n", 585 printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
571 qpti->qpti_id); 586 qpti->qpti_id);
572 spin_unlock_irqrestore(host->host_lock, flags); 587 err = 1;
573 return 1; 588 goto out;
574 } 589 }
575 590
576 /* Start using newly downloaded firmware. */ 591 /* Start using newly downloaded firmware. */
@@ -583,8 +598,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
583 (param[0] != MBOX_COMMAND_COMPLETE)) { 598 (param[0] != MBOX_COMMAND_COMPLETE)) {
584 printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n", 599 printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n",
585 qpti->qpti_id); 600 qpti->qpti_id);
586 spin_unlock_irqrestore(host->host_lock, flags); 601 err = 1;
587 return 1; 602 goto out;
588 } 603 }
589 604
590 /* Snag the major and minor revisions from the result. */ 605 /* Snag the major and minor revisions from the result. */
@@ -599,8 +614,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
599 (param[0] != MBOX_COMMAND_COMPLETE)) { 614 (param[0] != MBOX_COMMAND_COMPLETE)) {
600 printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n", 615 printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n",
601 qpti->qpti_id); 616 qpti->qpti_id);
602 spin_unlock_irqrestore(host->host_lock, flags); 617 err = 1;
603 return 1; 618 goto out;
604 } 619 }
605 620
606 if (qpti->is_pti != 0) { 621 if (qpti->is_pti != 0) {
@@ -616,8 +631,11 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
616 qlogicpti_mbox_command(qpti, param, 1); 631 qlogicpti_mbox_command(qpti, param, 1);
617 } 632 }
618 633
634out:
619 spin_unlock_irqrestore(host->host_lock, flags); 635 spin_unlock_irqrestore(host->host_lock, flags);
620 return 0; 636outfirm:
637 release_firmware(fw);
638 return err;
621} 639}
622 640
623static int qlogicpti_verify_tmon(struct qlogicpti *qpti) 641static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
@@ -1458,6 +1476,7 @@ MODULE_DESCRIPTION("QlogicISP SBUS driver");
1458MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); 1476MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
1459MODULE_LICENSE("GPL"); 1477MODULE_LICENSE("GPL");
1460MODULE_VERSION("2.1"); 1478MODULE_VERSION("2.1");
1479MODULE_FIRMWARE("qlogic/isp1000.bin");
1461 1480
1462module_init(qpti_init); 1481module_init(qpti_init);
1463module_exit(qpti_exit); 1482module_exit(qpti_exit);