aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_sup.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2007-09-20 17:07:33 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:49:38 -0400
commit338c9161e406591afbc1a6635a68d3b6d5362e00 (patch)
tree6bb711ac12bac66447ca924e56a9b616d6acd1e6 /drivers/scsi/qla2xxx/qla_sup.c
parentc81d04c9e27966c0e4c5650d130f209bff9671f9 (diff)
[SCSI] qla2xxx: Add flash burst-read/write support.
Newer ISPs support a mechanism to read and write flash-memory via the firmware LOAD/DUMP memory mailbox command routines. When supported, utilizing these mechanisms significantly reduces overall access times. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c221
1 files changed, 166 insertions, 55 deletions
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index a925a3f179f9..ad3d1de51d8c 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -425,6 +425,9 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
425/* Flash Manipulation Routines */ 425/* Flash Manipulation Routines */
426/*****************************************************************************/ 426/*****************************************************************************/
427 427
428#define OPTROM_BURST_SIZE 0x1000
429#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
430
428static inline uint32_t 431static inline uint32_t
429flash_conf_to_access_addr(uint32_t faddr) 432flash_conf_to_access_addr(uint32_t faddr)
430{ 433{
@@ -544,41 +547,59 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
544 uint32_t dwords) 547 uint32_t dwords)
545{ 548{
546 int ret; 549 int ret;
547 uint32_t liter; 550 uint32_t liter, miter;
548 uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; 551 uint32_t sec_mask, rest_addr, conf_addr;
549 uint32_t fdata, findex ; 552 uint32_t fdata, findex ;
550 uint8_t man_id, flash_id; 553 uint8_t man_id, flash_id;
551 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 554 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
555 dma_addr_t optrom_dma;
556 void *optrom = NULL;
557 uint32_t *s, *d;
552 558
553 ret = QLA_SUCCESS; 559 ret = QLA_SUCCESS;
554 560
561 /* Prepare burst-capable write on supported ISPs. */
562 if (IS_QLA25XX(ha) && !(faddr & ~OPTROM_BURST_SIZE) &&
563 dwords > OPTROM_BURST_DWORDS) {
564 optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
565 &optrom_dma, GFP_KERNEL);
566 if (!optrom) {
567 qla_printk(KERN_DEBUG, ha,
568 "Unable to allocate memory for optrom burst write "
569 "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
570 }
571 }
572
555 qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); 573 qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
556 DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, 574 DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
557 ha->host_no, man_id, flash_id)); 575 ha->host_no, man_id, flash_id));
558 576
559 sec_end_mask = 0;
560 conf_addr = flash_conf_to_access_addr(0x03d8); 577 conf_addr = flash_conf_to_access_addr(0x03d8);
561 switch (man_id) { 578 switch (man_id) {
562 case 0xbf: /* STT flash. */ 579 case 0xbf: /* STT flash. */
563 rest_addr = 0x1fff; 580 if (flash_id == 0x8e) {
564 sec_mask = 0x3e000; 581 rest_addr = 0x3fff;
582 sec_mask = 0x7c000;
583 } else {
584 rest_addr = 0x1fff;
585 sec_mask = 0x7e000;
586 }
565 if (flash_id == 0x80) 587 if (flash_id == 0x80)
566 conf_addr = flash_conf_to_access_addr(0x0352); 588 conf_addr = flash_conf_to_access_addr(0x0352);
567 break; 589 break;
568 case 0x13: /* ST M25P80. */ 590 case 0x13: /* ST M25P80. */
569 rest_addr = 0x3fff; 591 rest_addr = 0x3fff;
570 sec_mask = 0x3c000; 592 sec_mask = 0x7c000;
571 break; 593 break;
572 case 0x1f: // Atmel 26DF081A 594 case 0x1f: // Atmel 26DF081A
573 rest_addr = 0x0fff; 595 rest_addr = 0x3fff;
574 sec_mask = 0xff000; 596 sec_mask = 0x7c000;
575 sec_end_mask = 0x003ff;
576 conf_addr = flash_conf_to_access_addr(0x0320); 597 conf_addr = flash_conf_to_access_addr(0x0320);
577 break; 598 break;
578 default: 599 default:
579 /* Default to 64 kb sector size. */ 600 /* Default to 64 kb sector size. */
580 rest_addr = 0x3fff; 601 rest_addr = 0x3fff;
581 sec_mask = 0x3c000; 602 sec_mask = 0x7c000;
582 break; 603 break;
583 } 604 }
584 605
@@ -592,56 +613,81 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
592 /* Some flash parts need an additional zero-write to clear bits.*/ 613 /* Some flash parts need an additional zero-write to clear bits.*/
593 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); 614 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
594 615
595 do { /* Loop once to provide quick error exit. */ 616 for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
596 for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { 617 if (man_id == 0x1f) {
597 if (man_id == 0x1f) { 618 findex = faddr << 2;
598 findex = faddr << 2; 619 fdata = findex & sec_mask;
599 fdata = findex & sec_mask; 620 } else {
600 } else { 621 findex = faddr;
601 findex = faddr; 622 fdata = (findex & sec_mask) << 2;
602 fdata = (findex & sec_mask) << 2; 623 }
603 }
604 624
605 /* Are we at the beginning of a sector? */ 625 /* Are we at the beginning of a sector? */
606 if ((findex & rest_addr) == 0) { 626 if ((findex & rest_addr) == 0) {
607 /* 627 /* Do sector unprotect at 4K boundry for Atmel part. */
608 * Do sector unprotect at 4K boundry for Atmel 628 if (man_id == 0x1f)
609 * part. 629 qla24xx_write_flash_dword(ha,
610 */ 630 flash_conf_to_access_addr(0x0339),
611 if (man_id == 0x1f) 631 (fdata & 0xff00) | ((fdata << 16) &
612 qla24xx_write_flash_dword(ha,
613 flash_conf_to_access_addr(0x0339),
614 (fdata & 0xff00) | ((fdata << 16) &
615 0xff0000) | ((fdata >> 16) & 0xff));
616 ret = qla24xx_write_flash_dword(ha, conf_addr,
617 (fdata & 0xff00) |((fdata << 16) &
618 0xff0000) | ((fdata >> 16) & 0xff)); 632 0xff0000) | ((fdata >> 16) & 0xff));
619 if (ret != QLA_SUCCESS) { 633 ret = qla24xx_write_flash_dword(ha, conf_addr,
620 DEBUG9(printk("%s(%ld) Unable to flash " 634 (fdata & 0xff00) |((fdata << 16) &
621 "sector: address=%x.\n", __func__, 635 0xff0000) | ((fdata >> 16) & 0xff));
622 ha->host_no, faddr)); 636 if (ret != QLA_SUCCESS) {
623 break; 637 DEBUG9(printk("%s(%ld) Unable to flash "
624 } 638 "sector: address=%x.\n", __func__,
639 ha->host_no, faddr));
640 break;
625 } 641 }
626 ret = qla24xx_write_flash_dword(ha, 642 }
643
644 /* Go with burst-write. */
645 if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) {
646 /* Copy data to DMA'ble buffer. */
647 for (miter = 0, s = optrom, d = dwptr;
648 miter < OPTROM_BURST_DWORDS; miter++, s++, d++)
649 *s = cpu_to_le32(*d);
650
651 ret = qla2x00_load_ram(ha, optrom_dma,
627 flash_data_to_access_addr(faddr), 652 flash_data_to_access_addr(faddr),
628 cpu_to_le32(*dwptr)); 653 OPTROM_BURST_DWORDS);
629 if (ret != QLA_SUCCESS) { 654 if (ret != QLA_SUCCESS) {
630 DEBUG9(printk("%s(%ld) Unable to program flash " 655 qla_printk(KERN_WARNING, ha,
631 "address=%x data=%x.\n", __func__, 656 "Unable to burst-write optrom segment "
632 ha->host_no, faddr, *dwptr)); 657 "(%x/%x/%llx).\n", ret,
633 break; 658 flash_data_to_access_addr(faddr),
659 optrom_dma);
660 qla_printk(KERN_WARNING, ha,
661 "Reverting to slow-write.\n");
662
663 dma_free_coherent(&ha->pdev->dev,
664 OPTROM_BURST_SIZE, optrom, optrom_dma);
665 optrom = NULL;
666 } else {
667 liter += OPTROM_BURST_DWORDS - 1;
668 faddr += OPTROM_BURST_DWORDS - 1;
669 dwptr += OPTROM_BURST_DWORDS - 1;
670 continue;
634 } 671 }
672 }
635 673
636 /* Do sector protect at 4K boundry for Atmel part. */ 674 ret = qla24xx_write_flash_dword(ha,
637 if (man_id == 0x1f && 675 flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr));
638 ((faddr & sec_end_mask) == 0x3ff)) 676 if (ret != QLA_SUCCESS) {
639 qla24xx_write_flash_dword(ha, 677 DEBUG9(printk("%s(%ld) Unable to program flash "
640 flash_conf_to_access_addr(0x0336), 678 "address=%x data=%x.\n", __func__,
641 (fdata & 0xff00) | ((fdata << 16) & 679 ha->host_no, faddr, *dwptr));
642 0xff0000) | ((fdata >> 16) & 0xff)); 680 break;
643 } 681 }
644 } while (0); 682
683 /* Do sector protect at 4K boundry for Atmel part. */
684 if (man_id == 0x1f &&
685 ((faddr & rest_addr) == rest_addr))
686 qla24xx_write_flash_dword(ha,
687 flash_conf_to_access_addr(0x0336),
688 (fdata & 0xff00) | ((fdata << 16) &
689 0xff0000) | ((fdata >> 16) & 0xff));
690 }
645 691
646 /* Enable flash write-protection. */ 692 /* Enable flash write-protection. */
647 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); 693 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
@@ -651,6 +697,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
651 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE); 697 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
652 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */ 698 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
653 699
700 if (optrom)
701 dma_free_coherent(&ha->pdev->dev,
702 OPTROM_BURST_SIZE, optrom, optrom_dma);
703
654 return ret; 704 return ret;
655} 705}
656 706
@@ -1728,7 +1778,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1728{ 1778{
1729 /* Suspend HBA. */ 1779 /* Suspend HBA. */
1730 scsi_block_requests(ha->host); 1780 scsi_block_requests(ha->host);
1731 ha->isp_ops->disable_intrs(ha);
1732 set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); 1781 set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
1733 1782
1734 /* Go with read. */ 1783 /* Go with read. */
@@ -1736,7 +1785,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1736 1785
1737 /* Resume HBA. */ 1786 /* Resume HBA. */
1738 clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); 1787 clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
1739 ha->isp_ops->enable_intrs(ha);
1740 scsi_unblock_requests(ha->host); 1788 scsi_unblock_requests(ha->host);
1741 1789
1742 return buf; 1790 return buf;
@@ -1750,7 +1798,6 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1750 1798
1751 /* Suspend HBA. */ 1799 /* Suspend HBA. */
1752 scsi_block_requests(ha->host); 1800 scsi_block_requests(ha->host);
1753 ha->isp_ops->disable_intrs(ha);
1754 set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); 1801 set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
1755 1802
1756 /* Go with write. */ 1803 /* Go with write. */
@@ -1767,6 +1814,70 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1767 return rval; 1814 return rval;
1768} 1815}
1769 1816
1817uint8_t *
1818qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1819 uint32_t offset, uint32_t length)
1820{
1821 int rval;
1822 dma_addr_t optrom_dma;
1823 void *optrom;
1824 uint8_t *pbuf;
1825 uint32_t faddr, left, burst;
1826
1827 if (offset & ~OPTROM_BURST_SIZE)
1828 goto slow_read;
1829 if (length < OPTROM_BURST_SIZE)
1830 goto slow_read;
1831
1832 optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
1833 &optrom_dma, GFP_KERNEL);
1834 if (!optrom) {
1835 qla_printk(KERN_DEBUG, ha,
1836 "Unable to allocate memory for optrom burst read "
1837 "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
1838
1839 goto slow_read;
1840 }
1841
1842 pbuf = buf;
1843 faddr = offset >> 2;
1844 left = length >> 2;
1845 burst = OPTROM_BURST_DWORDS;
1846 while (left != 0) {
1847 if (burst > left)
1848 burst = left;
1849
1850 rval = qla2x00_dump_ram(ha, optrom_dma,
1851 flash_data_to_access_addr(faddr), burst);
1852 if (rval) {
1853 qla_printk(KERN_WARNING, ha,
1854 "Unable to burst-read optrom segment "
1855 "(%x/%x/%llx).\n", rval,
1856 flash_data_to_access_addr(faddr), optrom_dma);
1857 qla_printk(KERN_WARNING, ha,
1858 "Reverting to slow-read.\n");
1859
1860 dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
1861 optrom, optrom_dma);
1862 goto slow_read;
1863 }
1864
1865 memcpy(pbuf, optrom, burst * 4);
1866
1867 left -= burst;
1868 faddr += burst;
1869 pbuf += burst * 4;
1870 }
1871
1872 dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom,
1873 optrom_dma);
1874
1875 return buf;
1876
1877slow_read:
1878 return qla24xx_read_optrom_data(ha, buf, offset, length);
1879}
1880
1770/** 1881/**
1771 * qla2x00_get_fcode_version() - Determine an FCODE image's version. 1882 * qla2x00_get_fcode_version() - Determine an FCODE image's version.
1772 * @ha: HA context 1883 * @ha: HA context