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 69d6ad862b60..fa34b92850a6 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 | |||
58 | static struct qlogicpti *qptichain = NULL; | 57 | static struct qlogicpti *qptichain = NULL; |
59 | static DEFINE_SPINLOCK(qptichain_lock); | 58 | static DEFINE_SPINLOCK(qptichain_lock); |
60 | 59 | ||
@@ -465,16 +464,32 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) | |||
465 | 464 | ||
466 | static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) | 465 | static 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 | ||
634 | out: | ||
619 | spin_unlock_irqrestore(host->host_lock, flags); | 635 | spin_unlock_irqrestore(host->host_lock, flags); |
620 | return 0; | 636 | outfirm: |
637 | release_firmware(fw); | ||
638 | return err; | ||
621 | } | 639 | } |
622 | 640 | ||
623 | static int qlogicpti_verify_tmon(struct qlogicpti *qpti) | 641 | static int qlogicpti_verify_tmon(struct qlogicpti *qpti) |
@@ -1458,6 +1476,7 @@ MODULE_DESCRIPTION("QlogicISP SBUS driver"); | |||
1458 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | 1476 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); |
1459 | MODULE_LICENSE("GPL"); | 1477 | MODULE_LICENSE("GPL"); |
1460 | MODULE_VERSION("2.1"); | 1478 | MODULE_VERSION("2.1"); |
1479 | MODULE_FIRMWARE("qlogic/isp1000.bin"); | ||
1461 | 1480 | ||
1462 | module_init(qpti_init); | 1481 | module_init(qpti_init); |
1463 | module_exit(qpti_exit); | 1482 | module_exit(qpti_exit); |