qlge: Add ethtool register dump function.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bc083ce98e
commit
a61f802613
|
@ -1400,6 +1400,153 @@ struct nic_stats {
|
|||
u64 rx_nic_fifo_drop;
|
||||
};
|
||||
|
||||
/* Address/Length pairs for the coredump. */
|
||||
enum {
|
||||
MPI_CORE_REGS_ADDR = 0x00030000,
|
||||
MPI_CORE_REGS_CNT = 127,
|
||||
MPI_CORE_SH_REGS_CNT = 16,
|
||||
TEST_REGS_ADDR = 0x00001000,
|
||||
TEST_REGS_CNT = 23,
|
||||
RMII_REGS_ADDR = 0x00001040,
|
||||
RMII_REGS_CNT = 64,
|
||||
FCMAC1_REGS_ADDR = 0x00001080,
|
||||
FCMAC2_REGS_ADDR = 0x000010c0,
|
||||
FCMAC_REGS_CNT = 64,
|
||||
FC1_MBX_REGS_ADDR = 0x00001100,
|
||||
FC2_MBX_REGS_ADDR = 0x00001240,
|
||||
FC_MBX_REGS_CNT = 64,
|
||||
IDE_REGS_ADDR = 0x00001140,
|
||||
IDE_REGS_CNT = 64,
|
||||
NIC1_MBX_REGS_ADDR = 0x00001180,
|
||||
NIC2_MBX_REGS_ADDR = 0x00001280,
|
||||
NIC_MBX_REGS_CNT = 64,
|
||||
SMBUS_REGS_ADDR = 0x00001200,
|
||||
SMBUS_REGS_CNT = 64,
|
||||
I2C_REGS_ADDR = 0x00001fc0,
|
||||
I2C_REGS_CNT = 64,
|
||||
MEMC_REGS_ADDR = 0x00003000,
|
||||
MEMC_REGS_CNT = 256,
|
||||
PBUS_REGS_ADDR = 0x00007c00,
|
||||
PBUS_REGS_CNT = 256,
|
||||
MDE_REGS_ADDR = 0x00010000,
|
||||
MDE_REGS_CNT = 6,
|
||||
CODE_RAM_ADDR = 0x00020000,
|
||||
CODE_RAM_CNT = 0x2000,
|
||||
MEMC_RAM_ADDR = 0x00100000,
|
||||
MEMC_RAM_CNT = 0x2000,
|
||||
};
|
||||
|
||||
#define MPI_COREDUMP_COOKIE 0x5555aaaa
|
||||
struct mpi_coredump_global_header {
|
||||
u32 cookie;
|
||||
u8 idString[16];
|
||||
u32 timeLo;
|
||||
u32 timeHi;
|
||||
u32 imageSize;
|
||||
u32 headerSize;
|
||||
u8 info[220];
|
||||
};
|
||||
|
||||
struct mpi_coredump_segment_header {
|
||||
u32 cookie;
|
||||
u32 segNum;
|
||||
u32 segSize;
|
||||
u32 extra;
|
||||
u8 description[16];
|
||||
};
|
||||
|
||||
/* Reg dump segment numbers. */
|
||||
enum {
|
||||
CORE_SEG_NUM = 1,
|
||||
TEST_LOGIC_SEG_NUM = 2,
|
||||
RMII_SEG_NUM = 3,
|
||||
FCMAC1_SEG_NUM = 4,
|
||||
FCMAC2_SEG_NUM = 5,
|
||||
FC1_MBOX_SEG_NUM = 6,
|
||||
IDE_SEG_NUM = 7,
|
||||
NIC1_MBOX_SEG_NUM = 8,
|
||||
SMBUS_SEG_NUM = 9,
|
||||
FC2_MBOX_SEG_NUM = 10,
|
||||
NIC2_MBOX_SEG_NUM = 11,
|
||||
I2C_SEG_NUM = 12,
|
||||
MEMC_SEG_NUM = 13,
|
||||
PBUS_SEG_NUM = 14,
|
||||
MDE_SEG_NUM = 15,
|
||||
NIC1_CONTROL_SEG_NUM = 16,
|
||||
NIC2_CONTROL_SEG_NUM = 17,
|
||||
NIC1_XGMAC_SEG_NUM = 18,
|
||||
NIC2_XGMAC_SEG_NUM = 19,
|
||||
WCS_RAM_SEG_NUM = 20,
|
||||
MEMC_RAM_SEG_NUM = 21,
|
||||
XAUI_AN_SEG_NUM = 22,
|
||||
XAUI_HSS_PCS_SEG_NUM = 23,
|
||||
XFI_AN_SEG_NUM = 24,
|
||||
XFI_TRAIN_SEG_NUM = 25,
|
||||
XFI_HSS_PCS_SEG_NUM = 26,
|
||||
XFI_HSS_TX_SEG_NUM = 27,
|
||||
XFI_HSS_RX_SEG_NUM = 28,
|
||||
XFI_HSS_PLL_SEG_NUM = 29,
|
||||
MISC_NIC_INFO_SEG_NUM = 30,
|
||||
INTR_STATES_SEG_NUM = 31,
|
||||
CAM_ENTRIES_SEG_NUM = 32,
|
||||
ROUTING_WORDS_SEG_NUM = 33,
|
||||
ETS_SEG_NUM = 34,
|
||||
PROBE_DUMP_SEG_NUM = 35,
|
||||
ROUTING_INDEX_SEG_NUM = 36,
|
||||
MAC_PROTOCOL_SEG_NUM = 37,
|
||||
XAUI2_AN_SEG_NUM = 38,
|
||||
XAUI2_HSS_PCS_SEG_NUM = 39,
|
||||
XFI2_AN_SEG_NUM = 40,
|
||||
XFI2_TRAIN_SEG_NUM = 41,
|
||||
XFI2_HSS_PCS_SEG_NUM = 42,
|
||||
XFI2_HSS_TX_SEG_NUM = 43,
|
||||
XFI2_HSS_RX_SEG_NUM = 44,
|
||||
XFI2_HSS_PLL_SEG_NUM = 45,
|
||||
SEM_REGS_SEG_NUM = 50
|
||||
|
||||
};
|
||||
|
||||
struct ql_nic_misc {
|
||||
u32 rx_ring_count;
|
||||
u32 tx_ring_count;
|
||||
u32 intr_count;
|
||||
u32 function;
|
||||
};
|
||||
|
||||
struct ql_reg_dump {
|
||||
|
||||
/* segment 0 */
|
||||
struct mpi_coredump_global_header mpi_global_header;
|
||||
|
||||
/* segment 16 */
|
||||
struct mpi_coredump_segment_header nic_regs_seg_hdr;
|
||||
u32 nic_regs[64];
|
||||
|
||||
/* segment 30 */
|
||||
struct mpi_coredump_segment_header misc_nic_seg_hdr;
|
||||
struct ql_nic_misc misc_nic_info;
|
||||
|
||||
/* segment 31 */
|
||||
/* one interrupt state for each CQ */
|
||||
struct mpi_coredump_segment_header intr_states_seg_hdr;
|
||||
u32 intr_states[MAX_CPUS];
|
||||
|
||||
/* segment 32 */
|
||||
/* 3 cam words each for 16 unicast,
|
||||
* 2 cam words for each of 32 multicast.
|
||||
*/
|
||||
struct mpi_coredump_segment_header cam_entries_seg_hdr;
|
||||
u32 cam_entries[(16 * 3) + (32 * 3)];
|
||||
|
||||
/* segment 33 */
|
||||
struct mpi_coredump_segment_header nic_routing_words_seg_hdr;
|
||||
u32 nic_routing_words[16];
|
||||
|
||||
/* segment 34 */
|
||||
struct mpi_coredump_segment_header ets_seg_hdr;
|
||||
u32 ets[8+2];
|
||||
};
|
||||
|
||||
/*
|
||||
* intr_context structure is used during initialization
|
||||
* to hook the interrupts. It is also used in a single
|
||||
|
@ -1658,6 +1805,8 @@ int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control);
|
|||
int ql_mb_get_port_cfg(struct ql_adapter *qdev);
|
||||
int ql_mb_set_port_cfg(struct ql_adapter *qdev);
|
||||
int ql_wait_fifo_empty(struct ql_adapter *qdev);
|
||||
void ql_gen_reg_dump(struct ql_adapter *qdev,
|
||||
struct ql_reg_dump *mpi_coredump);
|
||||
|
||||
#if 1
|
||||
#define QL_ALL_DUMP
|
||||
|
|
|
@ -1,5 +1,185 @@
|
|||
#include "qlge.h"
|
||||
|
||||
|
||||
static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
|
||||
{
|
||||
int status = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++, buf++) {
|
||||
ql_write32(qdev, NIC_ETS, i << 29 | 0x08000000);
|
||||
*buf = ql_read32(qdev, NIC_ETS);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++, buf++) {
|
||||
ql_write32(qdev, CNA_ETS, i << 29 | 0x08000000);
|
||||
*buf = ql_read32(qdev, CNA_ETS);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < qdev->rx_ring_count; i++, buf++) {
|
||||
ql_write32(qdev, INTR_EN,
|
||||
qdev->intr_context[i].intr_read_mask);
|
||||
*buf = ql_read32(qdev, INTR_EN);
|
||||
}
|
||||
}
|
||||
|
||||
static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
|
||||
{
|
||||
int i, status;
|
||||
u32 value[3];
|
||||
|
||||
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
status = ql_get_mac_addr_reg(qdev,
|
||||
MAC_ADDR_TYPE_CAM_MAC, i, value);
|
||||
if (status) {
|
||||
QPRINTK(qdev, DRV, ERR,
|
||||
"Failed read of mac index register.\n");
|
||||
goto err;
|
||||
}
|
||||
*buf++ = value[0]; /* lower MAC address */
|
||||
*buf++ = value[1]; /* upper MAC address */
|
||||
*buf++ = value[2]; /* output */
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
status = ql_get_mac_addr_reg(qdev,
|
||||
MAC_ADDR_TYPE_MULTI_MAC, i, value);
|
||||
if (status) {
|
||||
QPRINTK(qdev, DRV, ERR,
|
||||
"Failed read of mac index register.\n");
|
||||
goto err;
|
||||
}
|
||||
*buf++ = value[0]; /* lower Mcast address */
|
||||
*buf++ = value[1]; /* upper Mcast address */
|
||||
}
|
||||
err:
|
||||
ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf)
|
||||
{
|
||||
int status;
|
||||
u32 value, i;
|
||||
|
||||
status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
status = ql_get_routing_reg(qdev, i, &value);
|
||||
if (status) {
|
||||
QPRINTK(qdev, DRV, ERR,
|
||||
"Failed read of routing index register.\n");
|
||||
goto err;
|
||||
} else {
|
||||
*buf++ = value;
|
||||
}
|
||||
}
|
||||
err:
|
||||
ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Create a coredump segment header */
|
||||
static void ql_build_coredump_seg_header(
|
||||
struct mpi_coredump_segment_header *seg_hdr,
|
||||
u32 seg_number, u32 seg_size, u8 *desc)
|
||||
{
|
||||
memset(seg_hdr, 0, sizeof(struct mpi_coredump_segment_header));
|
||||
seg_hdr->cookie = MPI_COREDUMP_COOKIE;
|
||||
seg_hdr->segNum = seg_number;
|
||||
seg_hdr->segSize = seg_size;
|
||||
memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1);
|
||||
}
|
||||
|
||||
void ql_gen_reg_dump(struct ql_adapter *qdev,
|
||||
struct ql_reg_dump *mpi_coredump)
|
||||
{
|
||||
int i, status;
|
||||
|
||||
|
||||
memset(&(mpi_coredump->mpi_global_header), 0,
|
||||
sizeof(struct mpi_coredump_global_header));
|
||||
mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
|
||||
mpi_coredump->mpi_global_header.headerSize =
|
||||
sizeof(struct mpi_coredump_global_header);
|
||||
mpi_coredump->mpi_global_header.imageSize =
|
||||
sizeof(struct ql_reg_dump);
|
||||
memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
|
||||
sizeof(mpi_coredump->mpi_global_header.idString));
|
||||
|
||||
|
||||
/* segment 16 */
|
||||
ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr,
|
||||
MISC_NIC_INFO_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->misc_nic_info),
|
||||
"MISC NIC INFO");
|
||||
mpi_coredump->misc_nic_info.rx_ring_count = qdev->rx_ring_count;
|
||||
mpi_coredump->misc_nic_info.tx_ring_count = qdev->tx_ring_count;
|
||||
mpi_coredump->misc_nic_info.intr_count = qdev->intr_count;
|
||||
mpi_coredump->misc_nic_info.function = qdev->func;
|
||||
|
||||
/* Segment 16, Rev C. Step 18 */
|
||||
ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr,
|
||||
NIC1_CONTROL_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->nic_regs),
|
||||
"NIC Registers");
|
||||
/* Get generic reg dump */
|
||||
for (i = 0; i < 64; i++)
|
||||
mpi_coredump->nic_regs[i] = ql_read32(qdev, i * sizeof(u32));
|
||||
|
||||
/* Segment 31 */
|
||||
/* Get indexed register values. */
|
||||
ql_build_coredump_seg_header(&mpi_coredump->intr_states_seg_hdr,
|
||||
INTR_STATES_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->intr_states),
|
||||
"INTR States");
|
||||
ql_get_intr_states(qdev, &mpi_coredump->intr_states[0]);
|
||||
|
||||
ql_build_coredump_seg_header(&mpi_coredump->cam_entries_seg_hdr,
|
||||
CAM_ENTRIES_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->cam_entries),
|
||||
"CAM Entries");
|
||||
status = ql_get_cam_entries(qdev, &mpi_coredump->cam_entries[0]);
|
||||
if (status)
|
||||
return;
|
||||
|
||||
ql_build_coredump_seg_header(&mpi_coredump->nic_routing_words_seg_hdr,
|
||||
ROUTING_WORDS_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->nic_routing_words),
|
||||
"Routing Words");
|
||||
status = ql_get_routing_entries(qdev,
|
||||
&mpi_coredump->nic_routing_words[0]);
|
||||
if (status)
|
||||
return;
|
||||
|
||||
/* Segment 34 (Rev C. step 23) */
|
||||
ql_build_coredump_seg_header(&mpi_coredump->ets_seg_hdr,
|
||||
ETS_SEG_NUM,
|
||||
sizeof(struct mpi_coredump_segment_header)
|
||||
+ sizeof(mpi_coredump->ets),
|
||||
"ETS Registers");
|
||||
status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]);
|
||||
if (status)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef QL_REG_DUMP
|
||||
static void ql_dump_intr_states(struct ql_adapter *qdev)
|
||||
{
|
||||
|
|
|
@ -428,6 +428,20 @@ static int ql_phys_id(struct net_device *ndev, u32 data)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ql_get_regs_len(struct net_device *ndev)
|
||||
{
|
||||
return sizeof(struct ql_reg_dump);
|
||||
}
|
||||
|
||||
static void ql_get_regs(struct net_device *ndev,
|
||||
struct ethtool_regs *regs, void *p)
|
||||
{
|
||||
struct ql_adapter *qdev = netdev_priv(ndev);
|
||||
|
||||
ql_gen_reg_dump(qdev, p);
|
||||
}
|
||||
|
||||
static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
|
||||
{
|
||||
struct ql_adapter *qdev = netdev_priv(dev);
|
||||
|
@ -555,6 +569,8 @@ const struct ethtool_ops qlge_ethtool_ops = {
|
|||
.get_drvinfo = ql_get_drvinfo,
|
||||
.get_wol = ql_get_wol,
|
||||
.set_wol = ql_set_wol,
|
||||
.get_regs_len = ql_get_regs_len,
|
||||
.get_regs = ql_get_regs,
|
||||
.get_msglevel = ql_get_msglevel,
|
||||
.set_msglevel = ql_set_msglevel,
|
||||
.get_link = ethtool_op_get_link,
|
||||
|
|
Loading…
Reference in a new issue