Skip to content

Commit 338c916

Browse files
avasquez01James Bottomley
authored andcommitted
[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 <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent c81d04c commit 338c916

File tree

4 files changed

+220
-56
lines changed

4 files changed

+220
-56
lines changed

drivers/scsi/qla2xxx/qla_gbl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
133133
extern int
134134
qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
135135

136+
extern int
137+
qla2x00_dump_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
138+
136139
extern int
137140
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
138141

@@ -302,6 +305,8 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
302305
uint32_t, uint32_t);
303306
extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
304307
uint32_t, uint32_t);
308+
extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
309+
uint32_t, uint32_t);
305310

306311
extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
307312
extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);

drivers/scsi/qla2xxx/qla_mbx.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2980,3 +2980,51 @@ qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format,
29802980

29812981
return rval;
29822982
}
2983+
2984+
int
2985+
qla2x00_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+
}

drivers/scsi/qla2xxx/qla_os.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ static struct isp_operations qla25xx_isp_ops = {
13841384
.beacon_on = qla24xx_beacon_on,
13851385
.beacon_off = qla24xx_beacon_off,
13861386
.beacon_blink = qla24xx_beacon_blink,
1387-
.read_optrom = qla24xx_read_optrom_data,
1387+
.read_optrom = qla25xx_read_optrom_data,
13881388
.write_optrom = qla24xx_write_optrom_data,
13891389
.get_flash_version = qla24xx_get_flash_version,
13901390
};

drivers/scsi/qla2xxx/qla_sup.c

Lines changed: 166 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
425425
/* Flash Manipulation Routines */
426426
/*****************************************************************************/
427427

428+
#define OPTROM_BURST_SIZE 0x1000
429+
#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
430+
428431
static inline uint32_t
429432
flash_conf_to_access_addr(uint32_t faddr)
430433
{
@@ -544,41 +547,59 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
544547
uint32_t dwords)
545548
{
546549
int ret;
547-
uint32_t liter;
548-
uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask;
550+
uint32_t liter, miter;
551+
uint32_t sec_mask, rest_addr, conf_addr;
549552
uint32_t fdata, findex ;
550553
uint8_t man_id, flash_id;
551554
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
555+
dma_addr_t optrom_dma;
556+
void *optrom = NULL;
557+
uint32_t *s, *d;
552558

553559
ret = QLA_SUCCESS;
554560

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+
555573
qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
556574
DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
557575
ha->host_no, man_id, flash_id));
558576

559-
sec_end_mask = 0;
560577
conf_addr = flash_conf_to_access_addr(0x03d8);
561578
switch (man_id) {
562579
case 0xbf: /* STT flash. */
563-
rest_addr = 0x1fff;
564-
sec_mask = 0x3e000;
580+
if (flash_id == 0x8e) {
581+
rest_addr = 0x3fff;
582+
sec_mask = 0x7c000;
583+
} else {
584+
rest_addr = 0x1fff;
585+
sec_mask = 0x7e000;
586+
}
565587
if (flash_id == 0x80)
566588
conf_addr = flash_conf_to_access_addr(0x0352);
567589
break;
568590
case 0x13: /* ST M25P80. */
569591
rest_addr = 0x3fff;
570-
sec_mask = 0x3c000;
592+
sec_mask = 0x7c000;
571593
break;
572594
case 0x1f: // Atmel 26DF081A
573-
rest_addr = 0x0fff;
574-
sec_mask = 0xff000;
575-
sec_end_mask = 0x003ff;
595+
rest_addr = 0x3fff;
596+
sec_mask = 0x7c000;
576597
conf_addr = flash_conf_to_access_addr(0x0320);
577598
break;
578599
default:
579600
/* Default to 64 kb sector size. */
580601
rest_addr = 0x3fff;
581-
sec_mask = 0x3c000;
602+
sec_mask = 0x7c000;
582603
break;
583604
}
584605

@@ -592,56 +613,81 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
592613
/* Some flash parts need an additional zero-write to clear bits.*/
593614
qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
594615

595-
do { /* Loop once to provide quick error exit. */
596-
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
597-
if (man_id == 0x1f) {
598-
findex = faddr << 2;
599-
fdata = findex & sec_mask;
600-
} else {
601-
findex = faddr;
602-
fdata = (findex & sec_mask) << 2;
603-
}
616+
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
617+
if (man_id == 0x1f) {
618+
findex = faddr << 2;
619+
fdata = findex & sec_mask;
620+
} else {
621+
findex = faddr;
622+
fdata = (findex & sec_mask) << 2;
623+
}
604624

605-
/* Are we at the beginning of a sector? */
606-
if ((findex & rest_addr) == 0) {
607-
/*
608-
* Do sector unprotect at 4K boundry for Atmel
609-
* part.
610-
*/
611-
if (man_id == 0x1f)
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) &
625+
/* Are we at the beginning of a sector? */
626+
if ((findex & rest_addr) == 0) {
627+
/* Do sector unprotect at 4K boundry for Atmel part. */
628+
if (man_id == 0x1f)
629+
qla24xx_write_flash_dword(ha,
630+
flash_conf_to_access_addr(0x0339),
631+
(fdata & 0xff00) | ((fdata << 16) &
618632
0xff0000) | ((fdata >> 16) & 0xff));
619-
if (ret != QLA_SUCCESS) {
620-
DEBUG9(printk("%s(%ld) Unable to flash "
621-
"sector: address=%x.\n", __func__,
622-
ha->host_no, faddr));
623-
break;
624-
}
633+
ret = qla24xx_write_flash_dword(ha, conf_addr,
634+
(fdata & 0xff00) |((fdata << 16) &
635+
0xff0000) | ((fdata >> 16) & 0xff));
636+
if (ret != QLA_SUCCESS) {
637+
DEBUG9(printk("%s(%ld) Unable to flash "
638+
"sector: address=%x.\n", __func__,
639+
ha->host_no, faddr));
640+
break;
625641
}
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,
627652
flash_data_to_access_addr(faddr),
628-
cpu_to_le32(*dwptr));
653+
OPTROM_BURST_DWORDS);
629654
if (ret != QLA_SUCCESS) {
630-
DEBUG9(printk("%s(%ld) Unable to program flash "
631-
"address=%x data=%x.\n", __func__,
632-
ha->host_no, faddr, *dwptr));
633-
break;
655+
qla_printk(KERN_WARNING, ha,
656+
"Unable to burst-write optrom segment "
657+
"(%x/%x/%llx).\n", ret,
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;
634671
}
672+
}
635673

636-
/* Do sector protect at 4K boundry for Atmel part. */
637-
if (man_id == 0x1f &&
638-
((faddr & sec_end_mask) == 0x3ff))
639-
qla24xx_write_flash_dword(ha,
640-
flash_conf_to_access_addr(0x0336),
641-
(fdata & 0xff00) | ((fdata << 16) &
642-
0xff0000) | ((fdata >> 16) & 0xff));
674+
ret = qla24xx_write_flash_dword(ha,
675+
flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr));
676+
if (ret != QLA_SUCCESS) {
677+
DEBUG9(printk("%s(%ld) Unable to program flash "
678+
"address=%x data=%x.\n", __func__,
679+
ha->host_no, faddr, *dwptr));
680+
break;
643681
}
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+
}
645691

646692
/* Enable flash write-protection. */
647693
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,
651697
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
652698
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
653699

700+
if (optrom)
701+
dma_free_coherent(&ha->pdev->dev,
702+
OPTROM_BURST_SIZE, optrom, optrom_dma);
703+
654704
return ret;
655705
}
656706

@@ -1728,15 +1778,13 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
17281778
{
17291779
/* Suspend HBA. */
17301780
scsi_block_requests(ha->host);
1731-
ha->isp_ops->disable_intrs(ha);
17321781
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
17331782

17341783
/* Go with read. */
17351784
qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2);
17361785

17371786
/* Resume HBA. */
17381787
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
1739-
ha->isp_ops->enable_intrs(ha);
17401788
scsi_unblock_requests(ha->host);
17411789

17421790
return buf;
@@ -1750,7 +1798,6 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
17501798

17511799
/* Suspend HBA. */
17521800
scsi_block_requests(ha->host);
1753-
ha->isp_ops->disable_intrs(ha);
17541801
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
17551802

17561803
/* Go with write. */
@@ -1767,6 +1814,70 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
17671814
return rval;
17681815
}
17691816

1817+
uint8_t *
1818+
qla25xx_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+
1877+
slow_read:
1878+
return qla24xx_read_optrom_data(ha, buf, offset, length);
1879+
}
1880+
17701881
/**
17711882
* qla2x00_get_fcode_version() - Determine an FCODE image's version.
17721883
* @ha: HA context

0 commit comments

Comments
 (0)