"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)) {
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;
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;
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(®->hccr);
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
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(®->hccr);
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
}
}
+static void
+qla24xx_unprotect_flash(scsi_qla_host_t *ha)
+{
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ /* Enable flash write. */
+ WRT_REG_DWORD(®->ctrl_status,
+ RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
+ RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+
+ /* Disable flash write-protection. */
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+ /* Some flash parts need an additional zero-write to clear bits.*/
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+}
+
+static void
+qla24xx_protect_flash(scsi_qla_host_t *ha)
+{
+ uint32_t cnt;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ /* Enable flash write-protection and wait for completion. */
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+ for (cnt = 300; cnt &&
+ qla24xx_read_flash_dword(ha,
+ flash_conf_to_access_addr(0x005)) & BIT_0;
+ cnt--) {
+ udelay(10);
+ }
+
+ /* Disable flash write. */
+ WRT_REG_DWORD(®->ctrl_status,
+ RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
+ RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+}
+
static int
qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
int ret;
uint32_t liter, miter;
uint32_t sec_mask, rest_addr, conf_addr;
- uint32_t fdata, findex, cnt;
+ uint32_t fdata, findex;
uint8_t man_id, flash_id;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t optrom_dma;
void *optrom = NULL;
uint32_t *s, *d;
break;
}
- /* Enable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
-
- /* Disable flash write-protection. */
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
- /* Some flash parts need an additional zero-write to clear bits.*/
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+ qla24xx_unprotect_flash(ha);
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
if (man_id == 0x1f) {
0xff0000) | ((fdata >> 16) & 0xff));
}
- /* Enable flash write-protection and wait for completion. */
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
- for (cnt = 300; cnt &&
- qla24xx_read_flash_dword(ha,
- flash_conf_to_access_addr(0x005)) & BIT_0;
- cnt--) {
- udelay(10);
- }
-
- /* Disable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+ qla24xx_protect_flash(ha);
if (optrom)
dma_free_coherent(&ha->pdev->dev,
return ret;
}
+
+static int
+qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
+{
+ uint32_t d[2], faddr;
+
+ /* Locate first empty entry. */
+ for (;;) {
+ if (ha->hw_event_ptr >=
+ ha->hw_event_start + FA_HW_EVENT_SIZE) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "HW event -- Log Full!\n"));
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+
+ qla24xx_read_flash_data(ha, d, ha->hw_event_ptr, 2);
+ faddr = flash_data_to_access_addr(ha->hw_event_ptr);
+ ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
+ if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
+ d[1] == __constant_cpu_to_le32(0xffffffff)) {
+ qla24xx_unprotect_flash(ha);
+
+ qla24xx_write_flash_dword(ha, faddr++,
+ cpu_to_le32(jiffies));
+ qla24xx_write_flash_dword(ha, faddr++, 0);
+ qla24xx_write_flash_dword(ha, faddr++, *fdata++);
+ qla24xx_write_flash_dword(ha, faddr++, *fdata);
+
+ qla24xx_protect_flash(ha);
+ break;
+ }
+ }
+ return QLA_SUCCESS;
+}
+
+int
+qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
+ uint16_t d2, uint16_t d3)
+{
+#define QMARK(a, b, c, d) \
+ cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
+
+ int rval;
+ uint32_t marker[2], fdata[4];
+
+ if (ha->hw_event_start == 0)
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
+
+ /* If marker not already found, locate or write. */
+ if (!ha->flags.hw_event_marker_found) {
+ /* Create marker. */
+ marker[0] = QMARK('L', ha->fw_major_version,
+ ha->fw_minor_version, ha->fw_subminor_version);
+ marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
+ QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
+
+ /* Locate marker. */
+ ha->hw_event_ptr = ha->hw_event_start;
+ for (;;) {
+ qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
+ 4);
+ if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
+ fdata[1] == __constant_cpu_to_le32(0xffffffff))
+ break;
+ ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
+ if (ha->hw_event_ptr >=
+ ha->hw_event_start + FA_HW_EVENT_SIZE) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "HW event -- Log Full!\n"));
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+ if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
+ ha->flags.hw_event_marker_found = 1;
+ break;
+ }
+ }
+ /* No marker, write it. */
+ if (!ha->flags.hw_event_marker_found) {
+ rval = qla2xxx_hw_event_store(ha, marker);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "HW event -- Failed marker write=%x.!\n",
+ rval));
+ return rval;
+ }
+ ha->flags.hw_event_marker_found = 1;
+ }
+ }
+
+ /* Store error. */
+ fdata[0] = cpu_to_le32(code << 16 | d1);
+ fdata[1] = cpu_to_le32(d2 << 16 | d3);
+ rval = qla2xxx_hw_event_store(ha, fdata);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "HW event -- Failed error write=%x.!\n",
+ rval));
+ }
+
+ return rval;
+}