aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
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
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')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h14
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c15
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c23
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c168
8 files changed, 229 insertions, 25 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 35c730a3f0da..13ffedaf8cba 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2118,6 +2118,7 @@ struct qla_msix_entry {
2118/* Work events. */ 2118/* Work events. */
2119enum qla_work_type { 2119enum qla_work_type {
2120 QLA_EVT_AEN, 2120 QLA_EVT_AEN,
2121 QLA_EVT_HWE_LOG,
2121}; 2122};
2122 2123
2123 2124
@@ -2132,6 +2133,10 @@ struct qla_work_evt {
2132 enum fc_host_event_code code; 2133 enum fc_host_event_code code;
2133 u32 data; 2134 u32 data;
2134 } aen; 2135 } aen;
2136 struct {
2137 uint16_t code;
2138 uint16_t d1, d2, d3;
2139 } hwe;
2135 } u; 2140 } u;
2136}; 2141};
2137 2142
@@ -2173,6 +2178,7 @@ typedef struct scsi_qla_host {
2173 uint32_t vsan_enabled :1; 2178 uint32_t vsan_enabled :1;
2174 uint32_t npiv_supported :1; 2179 uint32_t npiv_supported :1;
2175 uint32_t fce_enabled :1; 2180 uint32_t fce_enabled :1;
2181 uint32_t hw_event_marker_found :1;
2176 } flags; 2182 } flags;
2177 2183
2178 atomic_t loop_state; 2184 atomic_t loop_state;
@@ -2478,6 +2484,10 @@ typedef struct scsi_qla_host {
2478 uint64_t fce_wr, fce_rd; 2484 uint64_t fce_wr, fce_rd;
2479 struct mutex fce_mutex; 2485 struct mutex fce_mutex;
2480 2486
2487 uint32_t hw_event_start;
2488 uint32_t hw_event_ptr;
2489 uint32_t hw_event_pause_errors;
2490
2481 uint8_t host_str[16]; 2491 uint8_t host_str[16];
2482 uint32_t pci_attr; 2492 uint32_t pci_attr;
2483 uint16_t chip_revision; 2493 uint16_t chip_revision;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 4ae26533fe12..5d19b0e49a62 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -793,7 +793,19 @@ struct device_reg_24xx {
793#define FA_VPD_NVRAM_ADDR 0x48000 793#define FA_VPD_NVRAM_ADDR 0x48000
794#define FA_FEATURE_ADDR 0x4C000 794#define FA_FEATURE_ADDR 0x4C000
795#define FA_FLASH_DESCR_ADDR 0x50000 795#define FA_FLASH_DESCR_ADDR 0x50000
796#define FA_HW_EVENT_ADDR 0x54000 796#define FA_HW_EVENT0_ADDR 0x54000
797#define FA_HW_EVENT1_ADDR 0x54200
798#define FA_HW_EVENT_SIZE 0x200
799#define FA_HW_EVENT_ENTRY_SIZE 4
800/*
801 * Flash Error Log Event Codes.
802 */
803#define HW_EVENT_RESET_ERR 0xF00B
804#define HW_EVENT_ISP_ERR 0xF020
805#define HW_EVENT_PARITY_ERR 0xF022
806#define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023
807#define HW_EVENT_FLASH_FW_ERR 0xF024
808
797#define FA_BOOT_LOG_ADDR 0x58000 809#define FA_BOOT_LOG_ADDR 0x58000
798#define FA_FW_DUMP0_ADDR 0x60000 810#define FA_FW_DUMP0_ADDR 0x60000
799#define FA_FW_DUMP1_ADDR 0x70000 811#define FA_FW_DUMP1_ADDR 0x70000
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index ee52f3e51cc6..276bd26c0c8e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -69,6 +69,8 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
69extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); 69extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
70extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum 70extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
71 fc_host_event_code, u32); 71 fc_host_event_code, u32);
72extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
73 uint16_t, uint16_t);
72 74
73/* 75/*
74 * Global Functions in qla_mid.c source file. 76 * Global Functions in qla_mid.c source file.
@@ -298,6 +300,9 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
298extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); 300extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
299extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); 301extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
300 302
303extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
304 uint16_t, uint16_t);
305
301/* 306/*
302 * Global Function Prototypes in qla_dbg.c source file. 307 * Global Function Prototypes in qla_dbg.c source file.
303 */ 308 */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e773697cd8d5..e9a7c2d13855 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -500,6 +500,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
500static inline void 500static inline void
501qla24xx_reset_risc(scsi_qla_host_t *ha) 501qla24xx_reset_risc(scsi_qla_host_t *ha)
502{ 502{
503 int hw_evt = 0;
503 unsigned long flags = 0; 504 unsigned long flags = 0;
504 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 505 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
505 uint32_t cnt, d2; 506 uint32_t cnt, d2;
@@ -528,6 +529,8 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
528 d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0); 529 d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
529 barrier(); 530 barrier();
530 } 531 }
532 if (cnt == 0)
533 hw_evt = 1;
531 534
532 /* Wait for soft-reset to complete. */ 535 /* Wait for soft-reset to complete. */
533 d2 = RD_REG_DWORD(&reg->ctrl_status); 536 d2 = RD_REG_DWORD(&reg->ctrl_status);
@@ -536,6 +539,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
536 d2 = RD_REG_DWORD(&reg->ctrl_status); 539 d2 = RD_REG_DWORD(&reg->ctrl_status);
537 barrier(); 540 barrier();
538 } 541 }
542 if (cnt == 0 || hw_evt)
543 qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR,
544 RD_REG_WORD(&reg->mailbox1), RD_REG_WORD(&reg->mailbox2),
545 RD_REG_WORD(&reg->mailbox3));
539 546
540 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET); 547 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
541 RD_REG_DWORD(&reg->hccr); 548 RD_REG_DWORD(&reg->hccr);
@@ -1555,6 +1562,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
1555 qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " 1562 qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
1556 "invalid -- WWPN) defaults.\n"); 1563 "invalid -- WWPN) defaults.\n");
1557 1564
1565 if (chksum)
1566 qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
1567 MSW(chksum), LSW(chksum));
1568
1558 /* 1569 /*
1559 * Set default initialization control block. 1570 * Set default initialization control block.
1560 */ 1571 */
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index e9d8a79dd6a4..088464251d7e 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -349,6 +349,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
349 "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", 349 "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
350 mb[1], mb[2], mb[3]); 350 mb[1], mb[2], mb[3]);
351 351
352 qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
352 ha->isp_ops->fw_dump(ha, 1); 353 ha->isp_ops->fw_dump(ha, 1);
353 354
354 if (IS_FWI2_CAPABLE(ha)) { 355 if (IS_FWI2_CAPABLE(ha)) {
@@ -373,6 +374,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
373 ha->host_no)); 374 ha->host_no));
374 qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n"); 375 qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
375 376
377 qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
376 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); 378 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
377 break; 379 break;
378 380
@@ -381,6 +383,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
381 ha->host_no)); 383 ha->host_no));
382 qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n"); 384 qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
383 385
386 qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
384 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); 387 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
385 break; 388 break;
386 389
@@ -1558,6 +1561,12 @@ qla24xx_intr_handler(int irq, void *dev_id)
1558 if (pci_channel_offline(ha->pdev)) 1561 if (pci_channel_offline(ha->pdev))
1559 break; 1562 break;
1560 1563
1564 if (ha->hw_event_pause_errors == 0)
1565 qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
1566 0, MSW(stat), LSW(stat));
1567 else if (ha->hw_event_pause_errors < 0xffffffff)
1568 ha->hw_event_pause_errors++;
1569
1561 hccr = RD_REG_DWORD(&reg->hccr); 1570 hccr = RD_REG_DWORD(&reg->hccr);
1562 1571
1563 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " 1572 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1693,6 +1702,12 @@ qla24xx_msix_default(int irq, void *dev_id)
1693 if (pci_channel_offline(ha->pdev)) 1702 if (pci_channel_offline(ha->pdev))
1694 break; 1703 break;
1695 1704
1705 if (ha->hw_event_pause_errors == 0)
1706 qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
1707 0, MSW(stat), LSW(stat));
1708 else if (ha->hw_event_pause_errors < 0xffffffff)
1709 ha->hw_event_pause_errors++;
1710
1696 hccr = RD_REG_DWORD(&reg->hccr); 1711 hccr = RD_REG_DWORD(&reg->hccr);
1697 1712
1698 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " 1713 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 898847e4b363..b25c15a86c7f 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -587,6 +587,14 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
587 if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A || 587 if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
588 mcp->mb[7] != 0x2525) 588 mcp->mb[7] != 0x2525)
589 rval = QLA_FUNCTION_FAILED; 589 rval = QLA_FUNCTION_FAILED;
590 if (rval == QLA_FUNCTION_FAILED) {
591 struct device_reg_24xx __iomem *reg =
592 &ha->iobase->isp24;
593
594 qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
595 LSW(RD_REG_DWORD(&reg->hccr)),
596 LSW(RD_REG_DWORD(&reg->istatus)));
597 }
590 } 598 }
591 599
592 if (rval != QLA_SUCCESS) { 600 if (rval != QLA_SUCCESS) {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index eb77067533ab..3d290417bfc6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1690,6 +1690,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
1690 ha->gid_list_info_size = 8; 1690 ha->gid_list_info_size = 8;
1691 ha->optrom_size = OPTROM_SIZE_25XX; 1691 ha->optrom_size = OPTROM_SIZE_25XX;
1692 ha->isp_ops = &qla25xx_isp_ops; 1692 ha->isp_ops = &qla25xx_isp_ops;
1693 ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
1694 FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
1693 } 1695 }
1694 host->can_queue = ha->request_q_length + 128; 1696 host->can_queue = ha->request_q_length + 128;
1695 1697
@@ -2244,6 +2246,23 @@ qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
2244 return qla2x00_post_work(ha, e, 1); 2246 return qla2x00_post_work(ha, e, 1);
2245} 2247}
2246 2248
2249int
2250qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
2251 uint16_t d2, uint16_t d3)
2252{
2253 struct qla_work_evt *e;
2254
2255 e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
2256 if (!e)
2257 return QLA_FUNCTION_FAILED;
2258
2259 e->u.hwe.code = code;
2260 e->u.hwe.d1 = d1;
2261 e->u.hwe.d2 = d2;
2262 e->u.hwe.d3 = d3;
2263 return qla2x00_post_work(ha, e, 1);
2264}
2265
2247static void 2266static void
2248qla2x00_do_work(struct scsi_qla_host *ha) 2267qla2x00_do_work(struct scsi_qla_host *ha)
2249{ 2268{
@@ -2260,6 +2279,10 @@ qla2x00_do_work(struct scsi_qla_host *ha)
2260 fc_host_post_event(ha->host, fc_get_event_number(), 2279 fc_host_post_event(ha->host, fc_get_event_number(),
2261 e->u.aen.code, e->u.aen.data); 2280 e->u.aen.code, e->u.aen.data);
2262 break; 2281 break;
2282 case QLA_EVT_HWE_LOG:
2283 qla2xxx_hw_event_log(ha, e->u.hwe.code, e->u.hwe.d1,
2284 e->u.hwe.d2, e->u.hwe.d3);
2285 break;
2263 } 2286 }
2264 if (e->flags & QLA_EVT_FLAG_FREE) 2287 if (e->flags & QLA_EVT_FLAG_FREE)
2265 kfree(e); 2288 kfree(e);
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}