aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
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
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')
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c48
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c221
4 files changed, 220 insertions, 56 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index aa1e41152283..e8122e8444c7 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -134,6 +134,9 @@ extern int
134qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); 134qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
135 135
136extern int 136extern int
137qla2x00_dump_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
138
139extern int
137qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); 140qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
138 141
139extern void 142extern void
@@ -302,6 +305,8 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
302 uint32_t, uint32_t); 305 uint32_t, uint32_t);
303extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, 306extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
304 uint32_t, uint32_t); 307 uint32_t, uint32_t);
308extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
309 uint32_t, uint32_t);
305 310
306extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); 311extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
307extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); 312extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index d3746ec80a85..e4f4b1fc2b29 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2980,3 +2980,51 @@ qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format,
2980 2980
2981 return rval; 2981 return rval;
2982} 2982}
2983
2984int
2985qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
2986 uint32_t size)
2987{
2988 int rval;
2989 mbx_cmd_t mc;
2990 mbx_cmd_t *mcp = &mc;
2991
2992 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2993
2994 if (MSW(addr) || IS_FWI2_CAPABLE(ha)) {
2995 mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
2996 mcp->mb[8] = MSW(addr);
2997 mcp->out_mb = MBX_8|MBX_0;
2998 } else {
2999 mcp->mb[0] = MBC_DUMP_RISC_RAM;
3000 mcp->out_mb = MBX_0;
3001 }
3002 mcp->mb[1] = LSW(addr);
3003 mcp->mb[2] = MSW(req_dma);
3004 mcp->mb[3] = LSW(req_dma);
3005 mcp->mb[6] = MSW(MSD(req_dma));
3006 mcp->mb[7] = LSW(MSD(req_dma));
3007 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
3008 if (IS_FWI2_CAPABLE(ha)) {
3009 mcp->mb[4] = MSW(size);
3010 mcp->mb[5] = LSW(size);
3011 mcp->out_mb |= MBX_5|MBX_4;
3012 } else {
3013 mcp->mb[4] = LSW(size);
3014 mcp->out_mb |= MBX_4;
3015 }
3016
3017 mcp->in_mb = MBX_0;
3018 mcp->tov = 30;
3019 mcp->flags = 0;
3020 rval = qla2x00_mailbox_command(ha, mcp);
3021
3022 if (rval != QLA_SUCCESS) {
3023 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
3024 ha->host_no, rval, mcp->mb[0]));
3025 } else {
3026 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
3027 }
3028
3029 return rval;
3030}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index acca898ce0a2..2a03400b6f72 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1384,7 +1384,7 @@ static struct isp_operations qla25xx_isp_ops = {
1384 .beacon_on = qla24xx_beacon_on, 1384 .beacon_on = qla24xx_beacon_on,
1385 .beacon_off = qla24xx_beacon_off, 1385 .beacon_off = qla24xx_beacon_off,
1386 .beacon_blink = qla24xx_beacon_blink, 1386 .beacon_blink = qla24xx_beacon_blink,
1387 .read_optrom = qla24xx_read_optrom_data, 1387 .read_optrom = qla25xx_read_optrom_data,
1388 .write_optrom = qla24xx_write_optrom_data, 1388 .write_optrom = qla24xx_write_optrom_data,
1389 .get_flash_version = qla24xx_get_flash_version, 1389 .get_flash_version = qla24xx_get_flash_version,
1390}; 1390};
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