aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_sup.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2008-04-03 16:13:19 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:13 -0400
commitcb8dacbf1110d8bd39413f3116ff1720f757854e (patch)
tree8d58f215c7a1091f7e760359c56d1316d9c80f7d /drivers/scsi/qla2xxx/qla_sup.c
parent0971de7f56f809f40edae6fd372745e429e970e9 (diff)
[SCSI] qla2xxx: Add hardware trace-logging support.
Recent ISPs have a region within FLASH which acts as a repository for the logging of serious hardware and software failures. Currently, the region is large enough to support up to 255 entries. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c168
1 files changed, 144 insertions, 24 deletions
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 317cd8f96340..c10ccc75c398 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -543,6 +543,43 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
543 } 543 }
544} 544}
545 545
546static void
547qla24xx_unprotect_flash(scsi_qla_host_t *ha)
548{
549 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
550
551 /* Enable flash write. */
552 WRT_REG_DWORD(&reg->ctrl_status,
553 RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
554 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
555
556 /* Disable flash write-protection. */
557 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
558 /* Some flash parts need an additional zero-write to clear bits.*/
559 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
560}
561
562static void
563qla24xx_protect_flash(scsi_qla_host_t *ha)
564{
565 uint32_t cnt;
566 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
567
568 /* Enable flash write-protection and wait for completion. */
569 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
570 for (cnt = 300; cnt &&
571 qla24xx_read_flash_dword(ha,
572 flash_conf_to_access_addr(0x005)) & BIT_0;
573 cnt--) {
574 udelay(10);
575 }
576
577 /* Disable flash write. */
578 WRT_REG_DWORD(&reg->ctrl_status,
579 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
580 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
581}
582
546static int 583static int
547qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, 584qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
548 uint32_t dwords) 585 uint32_t dwords)
@@ -550,9 +587,8 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
550 int ret; 587 int ret;
551 uint32_t liter, miter; 588 uint32_t liter, miter;
552 uint32_t sec_mask, rest_addr, conf_addr; 589 uint32_t sec_mask, rest_addr, conf_addr;
553 uint32_t fdata, findex, cnt; 590 uint32_t fdata, findex;
554 uint8_t man_id, flash_id; 591 uint8_t man_id, flash_id;
555 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
556 dma_addr_t optrom_dma; 592 dma_addr_t optrom_dma;
557 void *optrom = NULL; 593 void *optrom = NULL;
558 uint32_t *s, *d; 594 uint32_t *s, *d;
@@ -604,15 +640,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
604 break; 640 break;
605 } 641 }
606 642
607 /* Enable flash write. */ 643 qla24xx_unprotect_flash(ha);
608 WRT_REG_DWORD(&reg->ctrl_status,
609 RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
610 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
611
612 /* Disable flash write-protection. */
613 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
614 /* Some flash parts need an additional zero-write to clear bits.*/
615 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
616 644
617 for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { 645 for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
618 if (man_id == 0x1f) { 646 if (man_id == 0x1f) {
@@ -690,19 +718,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
690 0xff0000) | ((fdata >> 16) & 0xff)); 718 0xff0000) | ((fdata >> 16) & 0xff));
691 } 719 }
692 720
693 /* Enable flash write-protection and wait for completion. */ 721 qla24xx_protect_flash(ha);
694 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
695 for (cnt = 300; cnt &&
696 qla24xx_read_flash_dword(ha,
697 flash_conf_to_access_addr(0x005)) & BIT_0;
698 cnt--) {
699 udelay(10);
700 }
701
702 /* Disable flash write. */
703 WRT_REG_DWORD(&reg->ctrl_status,
704 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
705 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
706 722
707 if (optrom) 723 if (optrom)
708 dma_free_coherent(&ha->pdev->dev, 724 dma_free_coherent(&ha->pdev->dev,
@@ -2221,3 +2237,107 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
2221 2237
2222 return ret; 2238 return ret;
2223} 2239}
2240
2241static int
2242qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
2243{
2244 uint32_t d[2], faddr;
2245
2246 /* Locate first empty entry. */
2247 for (;;) {
2248 if (ha->hw_event_ptr >=
2249 ha->hw_event_start + FA_HW_EVENT_SIZE) {
2250 DEBUG2(qla_printk(KERN_WARNING, ha,
2251 "HW event -- Log Full!\n"));
2252 return QLA_MEMORY_ALLOC_FAILED;
2253 }
2254
2255 qla24xx_read_flash_data(ha, d, ha->hw_event_ptr, 2);
2256 faddr = flash_data_to_access_addr(ha->hw_event_ptr);
2257 ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
2258 if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
2259 d[1] == __constant_cpu_to_le32(0xffffffff)) {
2260 qla24xx_unprotect_flash(ha);
2261
2262 qla24xx_write_flash_dword(ha, faddr++,
2263 cpu_to_le32(jiffies));
2264 qla24xx_write_flash_dword(ha, faddr++, 0);
2265 qla24xx_write_flash_dword(ha, faddr++, *fdata++);
2266 qla24xx_write_flash_dword(ha, faddr++, *fdata);
2267
2268 qla24xx_protect_flash(ha);
2269 break;
2270 }
2271 }
2272 return QLA_SUCCESS;
2273}
2274
2275int
2276qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
2277 uint16_t d2, uint16_t d3)
2278{
2279#define QMARK(a, b, c, d) \
2280 cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
2281
2282 int rval;
2283 uint32_t marker[2], fdata[4];
2284
2285 if (ha->hw_event_start == 0)
2286 return QLA_FUNCTION_FAILED;
2287
2288 DEBUG2(qla_printk(KERN_WARNING, ha,
2289 "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
2290
2291 /* If marker not already found, locate or write. */
2292 if (!ha->flags.hw_event_marker_found) {
2293 /* Create marker. */
2294 marker[0] = QMARK('L', ha->fw_major_version,
2295 ha->fw_minor_version, ha->fw_subminor_version);
2296 marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
2297 QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
2298
2299 /* Locate marker. */
2300 ha->hw_event_ptr = ha->hw_event_start;
2301 for (;;) {
2302 qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
2303 4);
2304 if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
2305 fdata[1] == __constant_cpu_to_le32(0xffffffff))
2306 break;
2307 ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
2308 if (ha->hw_event_ptr >=
2309 ha->hw_event_start + FA_HW_EVENT_SIZE) {
2310 DEBUG2(qla_printk(KERN_WARNING, ha,
2311 "HW event -- Log Full!\n"));
2312 return QLA_MEMORY_ALLOC_FAILED;
2313 }
2314 if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
2315 ha->flags.hw_event_marker_found = 1;
2316 break;
2317 }
2318 }
2319 /* No marker, write it. */
2320 if (!ha->flags.hw_event_marker_found) {
2321 rval = qla2xxx_hw_event_store(ha, marker);
2322 if (rval != QLA_SUCCESS) {
2323 DEBUG2(qla_printk(KERN_WARNING, ha,
2324 "HW event -- Failed marker write=%x.!\n",
2325 rval));
2326 return rval;
2327 }
2328 ha->flags.hw_event_marker_found = 1;
2329 }
2330 }
2331
2332 /* Store error. */
2333 fdata[0] = cpu_to_le32(code << 16 | d1);
2334 fdata[1] = cpu_to_le32(d2 << 16 | d3);
2335 rval = qla2xxx_hw_event_store(ha, fdata);
2336 if (rval != QLA_SUCCESS) {
2337 DEBUG2(qla_printk(KERN_WARNING, ha,
2338 "HW event -- Failed error write=%x.!\n",
2339 rval));
2340 }
2341
2342 return rval;
2343}