Skip to content

Commit

Permalink
qlge: Add RAM dump to firmware dump.
Browse files Browse the repository at this point in the history
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ron Mercer authored and David S. Miller committed Jan 16, 2010
1 parent c89ec8b commit 2c1f73c
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/net/qlge/qlge.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
35 changes: 35 additions & 0 deletions drivers/net/qlge/qlge_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
76 changes: 76 additions & 0 deletions drivers/net/qlge/qlge_mpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 2c1f73c

Please sign in to comment.