qlge: Add RAM dump to firmware dump.
authorRon Mercer <ron.mercer@qlogic.com>
Fri, 15 Jan 2010 13:31:30 +0000 (13:31 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 Jan 2010 09:01:53 +0000 (01:01 -0800)
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_dbg.c
drivers/net/qlge/qlge_mpi.c

index bbdd388aa9b7ad8420e1fea5df8f72c1586a7a4c..05feb03e9da6c442b5f37dea4f1ac98305a66d61 100644 (file)
@@ -2225,6 +2225,9 @@ int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
 int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data);
 int ql_unpause_mpi_risc(struct ql_adapter *qdev);
 int ql_pause_mpi_risc(struct ql_adapter *qdev);
+int ql_hard_reset_mpi_risc(struct ql_adapter *qdev);
+int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf,
+               u32 ram_addr, int word_count);
 int ql_core_dump(struct ql_adapter *qdev,
                struct ql_mpi_coredump *mpi_coredump);
 int ql_mb_about_fw(struct ql_adapter *qdev);
index 913ca1e10e3e510566c6d40b36dee2501cfd2d63..833cfd7a22c1634619ed72f147a5c2e46178ef1f 100644 (file)
@@ -647,6 +647,41 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
                        "Failed RISC unpause. Status = 0x%.08x\n", status);
                goto err;
        }
+
+       /* Reset the RISC so we can dump RAM */
+       status = ql_hard_reset_mpi_risc(qdev);
+       if (status) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Failed RISC reset. Status = 0x%.08x\n", status);
+               goto err;
+       }
+
+       ql_build_coredump_seg_header(&mpi_coredump->code_ram_seg_hdr,
+                               WCS_RAM_SEG_NUM,
+                               sizeof(struct mpi_coredump_segment_header)
+                               + sizeof(mpi_coredump->code_ram),
+                               "WCS RAM");
+       status = ql_dump_risc_ram_area(qdev, &mpi_coredump->code_ram[0],
+                                       CODE_RAM_ADDR, CODE_RAM_CNT);
+       if (status) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Failed Dump of CODE RAM. Status = 0x%.08x\n", status);
+               goto err;
+       }
+
+       /* Insert the segment header */
+       ql_build_coredump_seg_header(&mpi_coredump->memc_ram_seg_hdr,
+                               MEMC_RAM_SEG_NUM,
+                               sizeof(struct mpi_coredump_segment_header)
+                               + sizeof(mpi_coredump->memc_ram),
+                               "MEMC RAM");
+       status = ql_dump_risc_ram_area(qdev, &mpi_coredump->memc_ram[0],
+                                       MEMC_RAM_ADDR, MEMC_RAM_CNT);
+       if (status) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Failed Dump of MEMC RAM. Status = 0x%.08x\n", status);
+               goto err;
+       }
 err:
        ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */
        return status;
index 242b1ea955e4cd569d0462bf56994be9dc4e72b8..3304eb7df581961afba323ec14b41e614823d16c 100644 (file)
@@ -30,6 +30,25 @@ int ql_pause_mpi_risc(struct ql_adapter *qdev)
        return (count == 0) ? -ETIMEDOUT : 0;
 }
 
+int ql_hard_reset_mpi_risc(struct ql_adapter *qdev)
+{
+       u32 tmp;
+       int count = UDELAY_COUNT;
+
+       /* Reset the RISC */
+       ql_write32(qdev, CSR, CSR_CMD_SET_RST);
+       do {
+               tmp = ql_read32(qdev, CSR);
+               if (tmp & CSR_RR) {
+                       ql_write32(qdev, CSR, CSR_CMD_CLR_RST);
+                       break;
+               }
+               mdelay(UDELAY_DELAY);
+               count--;
+       } while (count);
+       return (count == 0) ? -ETIMEDOUT : 0;
+}
+
 int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
 {
        int status;
@@ -728,6 +747,63 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev)
        return status;
 }
 
+int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr,
+       u32 size)
+{
+       int status = 0;
+       struct mbox_params mbc;
+       struct mbox_params *mbcp = &mbc;
+
+       memset(mbcp, 0, sizeof(struct mbox_params));
+
+       mbcp->in_count = 9;
+       mbcp->out_count = 1;
+
+       mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM;
+       mbcp->mbox_in[1] = LSW(addr);
+       mbcp->mbox_in[2] = MSW(req_dma);
+       mbcp->mbox_in[3] = LSW(req_dma);
+       mbcp->mbox_in[4] = MSW(size);
+       mbcp->mbox_in[5] = LSW(size);
+       mbcp->mbox_in[6] = MSW(MSD(req_dma));
+       mbcp->mbox_in[7] = LSW(MSD(req_dma));
+       mbcp->mbox_in[8] = MSW(addr);
+
+
+       status = ql_mailbox_command(qdev, mbcp);
+       if (status)
+               return status;
+
+       if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Failed to dump risc RAM.\n");
+               status = -EIO;
+       }
+       return status;
+}
+
+/* Issue a mailbox command to dump RISC RAM. */
+int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf,
+               u32 ram_addr, int word_count)
+{
+       int status;
+       char *my_buf;
+       dma_addr_t buf_dma;
+
+       my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32),
+                                       &buf_dma);
+       if (!my_buf)
+               return -EIO;
+
+       status = ql_mb_dump_ram(qdev, buf_dma, ram_addr, word_count);
+       if (!status)
+               memcpy(buf, my_buf, word_count * sizeof(u32));
+
+       pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf,
+                               buf_dma);
+       return status;
+}
+
 /* Get link settings and maximum frame size settings
  * for the current port.
  * Most likely will block.