diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-03-02 03:01:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-03 01:32:48 -0500 |
commit | 0a64ea57486acd9e17b80bb70b966e81d904b61c (patch) | |
tree | 54c1ba2cf230f8c51f6d73bb27e40767e33ebeef /drivers/net/bnx2x_main.c | |
parent | c3eefaf676646281c07f93cb523a7be4eab67f8c (diff) |
bnx2x: Register dump
Adding "ethtool -d" support. Due to the complexity of the FW and HW, there are a
lot of different regions in the chip - to keep the code as clean as possible,
the ranges were put in an H file. Some areas cannot be read if the driver is
running - so by default, the driver will not access those areas - but any
programmer facing a problem will be able to easily manipulate the driver to
extract full dump. The full dump can also be used with kernel dump modules in
case of kernel panic.
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x_main.c')
-rw-r--r-- | drivers/net/bnx2x_main.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index e5952c57b40d..09d802ab0041 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | #include "bnx2x.h" | 54 | #include "bnx2x.h" |
55 | #include "bnx2x_init.h" | 55 | #include "bnx2x_init.h" |
56 | #include "bnx2x_dump.h" | ||
56 | 57 | ||
57 | #define DRV_MODULE_VERSION "1.48.102" | 58 | #define DRV_MODULE_VERSION "1.48.102" |
58 | #define DRV_MODULE_RELDATE "2009/02/12" | 59 | #define DRV_MODULE_RELDATE "2009/02/12" |
@@ -8471,6 +8472,84 @@ static void bnx2x_get_drvinfo(struct net_device *dev, | |||
8471 | info->regdump_len = 0; | 8472 | info->regdump_len = 0; |
8472 | } | 8473 | } |
8473 | 8474 | ||
8475 | #define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE) | ||
8476 | #define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE) | ||
8477 | |||
8478 | static int bnx2x_get_regs_len(struct net_device *dev) | ||
8479 | { | ||
8480 | static u32 regdump_len; | ||
8481 | struct bnx2x *bp = netdev_priv(dev); | ||
8482 | int i; | ||
8483 | |||
8484 | if (regdump_len) | ||
8485 | return regdump_len; | ||
8486 | |||
8487 | if (CHIP_IS_E1(bp)) { | ||
8488 | for (i = 0; i < REGS_COUNT; i++) | ||
8489 | if (IS_E1_ONLINE(reg_addrs[i].info)) | ||
8490 | regdump_len += reg_addrs[i].size; | ||
8491 | |||
8492 | for (i = 0; i < WREGS_COUNT_E1; i++) | ||
8493 | if (IS_E1_ONLINE(wreg_addrs_e1[i].info)) | ||
8494 | regdump_len += wreg_addrs_e1[i].size * | ||
8495 | (1 + wreg_addrs_e1[i].read_regs_count); | ||
8496 | |||
8497 | } else { /* E1H */ | ||
8498 | for (i = 0; i < REGS_COUNT; i++) | ||
8499 | if (IS_E1H_ONLINE(reg_addrs[i].info)) | ||
8500 | regdump_len += reg_addrs[i].size; | ||
8501 | |||
8502 | for (i = 0; i < WREGS_COUNT_E1H; i++) | ||
8503 | if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info)) | ||
8504 | regdump_len += wreg_addrs_e1h[i].size * | ||
8505 | (1 + wreg_addrs_e1h[i].read_regs_count); | ||
8506 | } | ||
8507 | regdump_len *= 4; | ||
8508 | regdump_len += sizeof(struct dump_hdr); | ||
8509 | |||
8510 | return regdump_len; | ||
8511 | } | ||
8512 | |||
8513 | static void bnx2x_get_regs(struct net_device *dev, | ||
8514 | struct ethtool_regs *regs, void *_p) | ||
8515 | { | ||
8516 | u32 *p = _p, i, j; | ||
8517 | struct bnx2x *bp = netdev_priv(dev); | ||
8518 | struct dump_hdr dump_hdr = {0}; | ||
8519 | |||
8520 | regs->version = 0; | ||
8521 | memset(p, 0, regs->len); | ||
8522 | |||
8523 | if (!netif_running(bp->dev)) | ||
8524 | return; | ||
8525 | |||
8526 | dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1; | ||
8527 | dump_hdr.dump_sign = dump_sign_all; | ||
8528 | dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR); | ||
8529 | dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR); | ||
8530 | dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR); | ||
8531 | dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR); | ||
8532 | dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE; | ||
8533 | |||
8534 | memcpy(p, &dump_hdr, sizeof(struct dump_hdr)); | ||
8535 | p += dump_hdr.hdr_size + 1; | ||
8536 | |||
8537 | if (CHIP_IS_E1(bp)) { | ||
8538 | for (i = 0; i < REGS_COUNT; i++) | ||
8539 | if (IS_E1_ONLINE(reg_addrs[i].info)) | ||
8540 | for (j = 0; j < reg_addrs[i].size; j++) | ||
8541 | *p++ = REG_RD(bp, | ||
8542 | reg_addrs[i].addr + j*4); | ||
8543 | |||
8544 | } else { /* E1H */ | ||
8545 | for (i = 0; i < REGS_COUNT; i++) | ||
8546 | if (IS_E1H_ONLINE(reg_addrs[i].info)) | ||
8547 | for (j = 0; j < reg_addrs[i].size; j++) | ||
8548 | *p++ = REG_RD(bp, | ||
8549 | reg_addrs[i].addr + j*4); | ||
8550 | } | ||
8551 | } | ||
8552 | |||
8474 | static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | 8553 | static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) |
8475 | { | 8554 | { |
8476 | struct bnx2x *bp = netdev_priv(dev); | 8555 | struct bnx2x *bp = netdev_priv(dev); |
@@ -9926,6 +10005,8 @@ static struct ethtool_ops bnx2x_ethtool_ops = { | |||
9926 | .get_settings = bnx2x_get_settings, | 10005 | .get_settings = bnx2x_get_settings, |
9927 | .set_settings = bnx2x_set_settings, | 10006 | .set_settings = bnx2x_set_settings, |
9928 | .get_drvinfo = bnx2x_get_drvinfo, | 10007 | .get_drvinfo = bnx2x_get_drvinfo, |
10008 | .get_regs_len = bnx2x_get_regs_len, | ||
10009 | .get_regs = bnx2x_get_regs, | ||
9929 | .get_wol = bnx2x_get_wol, | 10010 | .get_wol = bnx2x_get_wol, |
9930 | .set_wol = bnx2x_set_wol, | 10011 | .set_wol = bnx2x_set_wol, |
9931 | .get_msglevel = bnx2x_get_msglevel, | 10012 | .get_msglevel = bnx2x_get_msglevel, |