Skip to content

Commit

Permalink
[SCSI] qla2xxx: Add hardware trace-logging support.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andrew Vasquez authored and James Bottomley committed Apr 7, 2008
1 parent 0971de7 commit cb8dacb
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 25 deletions.
10 changes: 10 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2118,6 +2118,7 @@ struct qla_msix_entry {
/* Work events. */
enum qla_work_type {
QLA_EVT_AEN,
QLA_EVT_HWE_LOG,
};


Expand All @@ -2132,6 +2133,10 @@ struct qla_work_evt {
enum fc_host_event_code code;
u32 data;
} aen;
struct {
uint16_t code;
uint16_t d1, d2, d3;
} hwe;
} u;
};

Expand Down Expand Up @@ -2173,6 +2178,7 @@ typedef struct scsi_qla_host {
uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
uint32_t fce_enabled :1;
uint32_t hw_event_marker_found :1;
} flags;

atomic_t loop_state;
Expand Down Expand Up @@ -2478,6 +2484,10 @@ typedef struct scsi_qla_host {
uint64_t fce_wr, fce_rd;
struct mutex fce_mutex;

uint32_t hw_event_start;
uint32_t hw_event_ptr;
uint32_t hw_event_pause_errors;

uint8_t host_str[16];
uint32_t pci_attr;
uint16_t chip_revision;
Expand Down
14 changes: 13 additions & 1 deletion drivers/scsi/qla2xxx/qla_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,19 @@ struct device_reg_24xx {
#define FA_VPD_NVRAM_ADDR 0x48000
#define FA_FEATURE_ADDR 0x4C000
#define FA_FLASH_DESCR_ADDR 0x50000
#define FA_HW_EVENT_ADDR 0x54000
#define FA_HW_EVENT0_ADDR 0x54000
#define FA_HW_EVENT1_ADDR 0x54200
#define FA_HW_EVENT_SIZE 0x200
#define FA_HW_EVENT_ENTRY_SIZE 4
/*
* Flash Error Log Event Codes.
*/
#define HW_EVENT_RESET_ERR 0xF00B
#define HW_EVENT_ISP_ERR 0xF020
#define HW_EVENT_PARITY_ERR 0xF022
#define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023
#define HW_EVENT_FLASH_FW_ERR 0xF024

#define FA_BOOT_LOG_ADDR 0x58000
#define FA_FW_DUMP0_ADDR 0x60000
#define FA_FW_DUMP1_ADDR 0x70000
Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
uint16_t, uint16_t);

/*
* Global Functions in qla_mid.c source file.
Expand Down Expand Up @@ -298,6 +300,9 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);

extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
uint16_t, uint16_t);

/*
* Global Function Prototypes in qla_dbg.c source file.
*/
Expand Down
11 changes: 11 additions & 0 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
static inline void
qla24xx_reset_risc(scsi_qla_host_t *ha)
{
int hw_evt = 0;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
uint32_t cnt, d2;
Expand Down Expand Up @@ -528,6 +529,8 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
barrier();
}
if (cnt == 0)
hw_evt = 1;

/* Wait for soft-reset to complete. */
d2 = RD_REG_DWORD(&reg->ctrl_status);
Expand All @@ -536,6 +539,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
d2 = RD_REG_DWORD(&reg->ctrl_status);
barrier();
}
if (cnt == 0 || hw_evt)
qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR,
RD_REG_WORD(&reg->mailbox1), RD_REG_WORD(&reg->mailbox2),
RD_REG_WORD(&reg->mailbox3));

WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
RD_REG_DWORD(&reg->hccr);
Expand Down Expand Up @@ -1555,6 +1562,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
"invalid -- WWPN) defaults.\n");

if (chksum)
qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
MSW(chksum), LSW(chksum));

/*
* Set default initialization control block.
*/
Expand Down
15 changes: 15 additions & 0 deletions drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
mb[1], mb[2], mb[3]);

qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
ha->isp_ops->fw_dump(ha, 1);

if (IS_FWI2_CAPABLE(ha)) {
Expand All @@ -373,6 +374,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->host_no));
qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");

qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;

Expand All @@ -381,6 +383,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->host_no));
qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");

qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;

Expand Down Expand Up @@ -1558,6 +1561,12 @@ qla24xx_intr_handler(int irq, void *dev_id)
if (pci_channel_offline(ha->pdev))
break;

if (ha->hw_event_pause_errors == 0)
qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
0, MSW(stat), LSW(stat));
else if (ha->hw_event_pause_errors < 0xffffffff)
ha->hw_event_pause_errors++;

hccr = RD_REG_DWORD(&reg->hccr);

qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
Expand Down Expand Up @@ -1693,6 +1702,12 @@ qla24xx_msix_default(int irq, void *dev_id)
if (pci_channel_offline(ha->pdev))
break;

if (ha->hw_event_pause_errors == 0)
qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
0, MSW(stat), LSW(stat));
else if (ha->hw_event_pause_errors < 0xffffffff)
ha->hw_event_pause_errors++;

hccr = RD_REG_DWORD(&reg->hccr);

qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
Expand Down
8 changes: 8 additions & 0 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,14 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
mcp->mb[7] != 0x2525)
rval = QLA_FUNCTION_FAILED;
if (rval == QLA_FUNCTION_FAILED) {
struct device_reg_24xx __iomem *reg =
&ha->iobase->isp24;

qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
LSW(RD_REG_DWORD(&reg->hccr)),
LSW(RD_REG_DWORD(&reg->istatus)));
}
}

if (rval != QLA_SUCCESS) {
Expand Down
23 changes: 23 additions & 0 deletions drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->gid_list_info_size = 8;
ha->optrom_size = OPTROM_SIZE_25XX;
ha->isp_ops = &qla25xx_isp_ops;
ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
}
host->can_queue = ha->request_q_length + 128;

Expand Down Expand Up @@ -2244,6 +2246,23 @@ qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
return qla2x00_post_work(ha, e, 1);
}

int
qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
uint16_t d2, uint16_t d3)
{
struct qla_work_evt *e;

e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
if (!e)
return QLA_FUNCTION_FAILED;

e->u.hwe.code = code;
e->u.hwe.d1 = d1;
e->u.hwe.d2 = d2;
e->u.hwe.d3 = d3;
return qla2x00_post_work(ha, e, 1);
}

static void
qla2x00_do_work(struct scsi_qla_host *ha)
{
Expand All @@ -2260,6 +2279,10 @@ qla2x00_do_work(struct scsi_qla_host *ha)
fc_host_post_event(ha->host, fc_get_event_number(),
e->u.aen.code, e->u.aen.data);
break;
case QLA_EVT_HWE_LOG:
qla2xxx_hw_event_log(ha, e->u.hwe.code, e->u.hwe.d1,
e->u.hwe.d2, e->u.hwe.d3);
break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
Expand Down
Loading

0 comments on commit cb8dacb

Please sign in to comment.