diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2011-04-13 07:05:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-13 20:10:05 -0400 |
commit | 97bd8e491d1786f0020372a5a470bb8b3184856f (patch) | |
tree | a6c09f541895883107fa9dce458c8aa614c37736 | |
parent | 4d42d417be75d750b82798922b6e775915e11bce (diff) |
tg3: Provide full regdump on tx timeout
The current amount of information provided in the output of a tx timeout
is insufficient to determine a root cause. This patch replaces the
terse, four-register status output with a more complete body of
information. For PCIe devices, the full register space is dumped. For
other devices, select registers are dumped instead.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 189 | ||||
-rw-r--r-- | drivers/net/tg3.h | 2 |
2 files changed, 123 insertions, 68 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9d7defc2628d..72744353b1cb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4459,6 +4459,123 @@ static inline int tg3_irq_sync(struct tg3 *tp) | |||
4459 | return tp->irq_sync; | 4459 | return tp->irq_sync; |
4460 | } | 4460 | } |
4461 | 4461 | ||
4462 | static inline void tg3_rd32_loop(struct tg3 *tp, u32 *dst, u32 off, u32 len) | ||
4463 | { | ||
4464 | int i; | ||
4465 | |||
4466 | dst = (u32 *)((u8 *)dst + off); | ||
4467 | for (i = 0; i < len; i += sizeof(u32)) | ||
4468 | *dst++ = tr32(off + i); | ||
4469 | } | ||
4470 | |||
4471 | static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs) | ||
4472 | { | ||
4473 | tg3_rd32_loop(tp, regs, TG3PCI_VENDOR, 0xb0); | ||
4474 | tg3_rd32_loop(tp, regs, MAILBOX_INTERRUPT_0, 0x200); | ||
4475 | tg3_rd32_loop(tp, regs, MAC_MODE, 0x4f0); | ||
4476 | tg3_rd32_loop(tp, regs, SNDDATAI_MODE, 0xe0); | ||
4477 | tg3_rd32_loop(tp, regs, SNDDATAC_MODE, 0x04); | ||
4478 | tg3_rd32_loop(tp, regs, SNDBDS_MODE, 0x80); | ||
4479 | tg3_rd32_loop(tp, regs, SNDBDI_MODE, 0x48); | ||
4480 | tg3_rd32_loop(tp, regs, SNDBDC_MODE, 0x04); | ||
4481 | tg3_rd32_loop(tp, regs, RCVLPC_MODE, 0x20); | ||
4482 | tg3_rd32_loop(tp, regs, RCVLPC_SELLST_BASE, 0x15c); | ||
4483 | tg3_rd32_loop(tp, regs, RCVDBDI_MODE, 0x0c); | ||
4484 | tg3_rd32_loop(tp, regs, RCVDBDI_JUMBO_BD, 0x3c); | ||
4485 | tg3_rd32_loop(tp, regs, RCVDBDI_BD_PROD_IDX_0, 0x44); | ||
4486 | tg3_rd32_loop(tp, regs, RCVDCC_MODE, 0x04); | ||
4487 | tg3_rd32_loop(tp, regs, RCVBDI_MODE, 0x20); | ||
4488 | tg3_rd32_loop(tp, regs, RCVCC_MODE, 0x14); | ||
4489 | tg3_rd32_loop(tp, regs, RCVLSC_MODE, 0x08); | ||
4490 | tg3_rd32_loop(tp, regs, MBFREE_MODE, 0x08); | ||
4491 | tg3_rd32_loop(tp, regs, HOSTCC_MODE, 0x100); | ||
4492 | |||
4493 | if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) | ||
4494 | tg3_rd32_loop(tp, regs, HOSTCC_RXCOL_TICKS_VEC1, 0x180); | ||
4495 | |||
4496 | tg3_rd32_loop(tp, regs, MEMARB_MODE, 0x10); | ||
4497 | tg3_rd32_loop(tp, regs, BUFMGR_MODE, 0x58); | ||
4498 | tg3_rd32_loop(tp, regs, RDMAC_MODE, 0x08); | ||
4499 | tg3_rd32_loop(tp, regs, WDMAC_MODE, 0x08); | ||
4500 | tg3_rd32_loop(tp, regs, RX_CPU_MODE, 0x04); | ||
4501 | tg3_rd32_loop(tp, regs, RX_CPU_STATE, 0x04); | ||
4502 | tg3_rd32_loop(tp, regs, RX_CPU_PGMCTR, 0x04); | ||
4503 | tg3_rd32_loop(tp, regs, RX_CPU_HWBKPT, 0x04); | ||
4504 | |||
4505 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { | ||
4506 | tg3_rd32_loop(tp, regs, TX_CPU_MODE, 0x04); | ||
4507 | tg3_rd32_loop(tp, regs, TX_CPU_STATE, 0x04); | ||
4508 | tg3_rd32_loop(tp, regs, TX_CPU_PGMCTR, 0x04); | ||
4509 | } | ||
4510 | |||
4511 | tg3_rd32_loop(tp, regs, GRCMBOX_INTERRUPT_0, 0x110); | ||
4512 | tg3_rd32_loop(tp, regs, FTQ_RESET, 0x120); | ||
4513 | tg3_rd32_loop(tp, regs, MSGINT_MODE, 0x0c); | ||
4514 | tg3_rd32_loop(tp, regs, DMAC_MODE, 0x04); | ||
4515 | tg3_rd32_loop(tp, regs, GRC_MODE, 0x4c); | ||
4516 | |||
4517 | if (tp->tg3_flags & TG3_FLAG_NVRAM) | ||
4518 | tg3_rd32_loop(tp, regs, NVRAM_CMD, 0x24); | ||
4519 | } | ||
4520 | |||
4521 | static void tg3_dump_state(struct tg3 *tp) | ||
4522 | { | ||
4523 | int i; | ||
4524 | u32 *regs; | ||
4525 | |||
4526 | regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC); | ||
4527 | if (!regs) { | ||
4528 | netdev_err(tp->dev, "Failed allocating register dump buffer\n"); | ||
4529 | return; | ||
4530 | } | ||
4531 | |||
4532 | if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { | ||
4533 | /* Read up to but not including private PCI registers */ | ||
4534 | for (i = 0; i < TG3_PCIE_TLDLPL_PORT; i += sizeof(u32)) | ||
4535 | regs[i / sizeof(u32)] = tr32(i); | ||
4536 | } else | ||
4537 | tg3_dump_legacy_regs(tp, regs); | ||
4538 | |||
4539 | for (i = 0; i < TG3_REG_BLK_SIZE / sizeof(u32); i += 4) { | ||
4540 | if (!regs[i + 0] && !regs[i + 1] && | ||
4541 | !regs[i + 2] && !regs[i + 3]) | ||
4542 | continue; | ||
4543 | |||
4544 | netdev_err(tp->dev, "0x%08x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", | ||
4545 | i * 4, | ||
4546 | regs[i + 0], regs[i + 1], regs[i + 2], regs[i + 3]); | ||
4547 | } | ||
4548 | |||
4549 | kfree(regs); | ||
4550 | |||
4551 | for (i = 0; i < tp->irq_cnt; i++) { | ||
4552 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
4553 | |||
4554 | /* SW status block */ | ||
4555 | netdev_err(tp->dev, | ||
4556 | "%d: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n", | ||
4557 | i, | ||
4558 | tnapi->hw_status->status, | ||
4559 | tnapi->hw_status->status_tag, | ||
4560 | tnapi->hw_status->rx_jumbo_consumer, | ||
4561 | tnapi->hw_status->rx_consumer, | ||
4562 | tnapi->hw_status->rx_mini_consumer, | ||
4563 | tnapi->hw_status->idx[0].rx_producer, | ||
4564 | tnapi->hw_status->idx[0].tx_consumer); | ||
4565 | |||
4566 | netdev_err(tp->dev, | ||
4567 | "%d: NAPI info [%08x:%08x:(%04x:%04x:%04x):%04x:(%04x:%04x:%04x:%04x)]\n", | ||
4568 | i, | ||
4569 | tnapi->last_tag, tnapi->last_irq_tag, | ||
4570 | tnapi->tx_prod, tnapi->tx_cons, tnapi->tx_pending, | ||
4571 | tnapi->rx_rcb_ptr, | ||
4572 | tnapi->prodring.rx_std_prod_idx, | ||
4573 | tnapi->prodring.rx_std_cons_idx, | ||
4574 | tnapi->prodring.rx_jmb_prod_idx, | ||
4575 | tnapi->prodring.rx_jmb_cons_idx); | ||
4576 | } | ||
4577 | } | ||
4578 | |||
4462 | /* This is called whenever we suspect that the system chipset is re- | 4579 | /* This is called whenever we suspect that the system chipset is re- |
4463 | * ordering the sequence of MMIO to the tx send mailbox. The symptom | 4580 | * ordering the sequence of MMIO to the tx send mailbox. The symptom |
4464 | * is bogus tx completions. We try to recover by setting the | 4581 | * is bogus tx completions. We try to recover by setting the |
@@ -5516,21 +5633,13 @@ out: | |||
5516 | tg3_phy_start(tp); | 5633 | tg3_phy_start(tp); |
5517 | } | 5634 | } |
5518 | 5635 | ||
5519 | static void tg3_dump_short_state(struct tg3 *tp) | ||
5520 | { | ||
5521 | netdev_err(tp->dev, "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n", | ||
5522 | tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS)); | ||
5523 | netdev_err(tp->dev, "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n", | ||
5524 | tr32(RDMAC_STATUS), tr32(WDMAC_STATUS)); | ||
5525 | } | ||
5526 | |||
5527 | static void tg3_tx_timeout(struct net_device *dev) | 5636 | static void tg3_tx_timeout(struct net_device *dev) |
5528 | { | 5637 | { |
5529 | struct tg3 *tp = netdev_priv(dev); | 5638 | struct tg3 *tp = netdev_priv(dev); |
5530 | 5639 | ||
5531 | if (netif_msg_tx_err(tp)) { | 5640 | if (netif_msg_tx_err(tp)) { |
5532 | netdev_err(dev, "transmit timed out, resetting\n"); | 5641 | netdev_err(dev, "transmit timed out, resetting\n"); |
5533 | tg3_dump_short_state(tp); | 5642 | tg3_dump_state(tp); |
5534 | } | 5643 | } |
5535 | 5644 | ||
5536 | schedule_work(&tp->reset_task); | 5645 | schedule_work(&tp->reset_task); |
@@ -9624,82 +9733,26 @@ static void tg3_set_rx_mode(struct net_device *dev) | |||
9624 | tg3_full_unlock(tp); | 9733 | tg3_full_unlock(tp); |
9625 | } | 9734 | } |
9626 | 9735 | ||
9627 | #define TG3_REGDUMP_LEN (32 * 1024) | ||
9628 | |||
9629 | static int tg3_get_regs_len(struct net_device *dev) | 9736 | static int tg3_get_regs_len(struct net_device *dev) |
9630 | { | 9737 | { |
9631 | return TG3_REGDUMP_LEN; | 9738 | return TG3_REG_BLK_SIZE; |
9632 | } | 9739 | } |
9633 | 9740 | ||
9634 | static void tg3_get_regs(struct net_device *dev, | 9741 | static void tg3_get_regs(struct net_device *dev, |
9635 | struct ethtool_regs *regs, void *_p) | 9742 | struct ethtool_regs *regs, void *_p) |
9636 | { | 9743 | { |
9637 | u32 *p = _p; | ||
9638 | struct tg3 *tp = netdev_priv(dev); | 9744 | struct tg3 *tp = netdev_priv(dev); |
9639 | u8 *orig_p = _p; | ||
9640 | int i; | ||
9641 | 9745 | ||
9642 | regs->version = 0; | 9746 | regs->version = 0; |
9643 | 9747 | ||
9644 | memset(p, 0, TG3_REGDUMP_LEN); | 9748 | memset(_p, 0, TG3_REG_BLK_SIZE); |
9645 | 9749 | ||
9646 | if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) | 9750 | if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) |
9647 | return; | 9751 | return; |
9648 | 9752 | ||
9649 | tg3_full_lock(tp, 0); | 9753 | tg3_full_lock(tp, 0); |
9650 | 9754 | ||
9651 | #define __GET_REG32(reg) (*(p)++ = tr32(reg)) | 9755 | tg3_dump_legacy_regs(tp, (u32 *)_p); |
9652 | #define GET_REG32_LOOP(base, len) \ | ||
9653 | do { p = (u32 *)(orig_p + (base)); \ | ||
9654 | for (i = 0; i < len; i += 4) \ | ||
9655 | __GET_REG32((base) + i); \ | ||
9656 | } while (0) | ||
9657 | #define GET_REG32_1(reg) \ | ||
9658 | do { p = (u32 *)(orig_p + (reg)); \ | ||
9659 | __GET_REG32((reg)); \ | ||
9660 | } while (0) | ||
9661 | |||
9662 | GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0); | ||
9663 | GET_REG32_LOOP(MAILBOX_INTERRUPT_0, 0x200); | ||
9664 | GET_REG32_LOOP(MAC_MODE, 0x4f0); | ||
9665 | GET_REG32_LOOP(SNDDATAI_MODE, 0xe0); | ||
9666 | GET_REG32_1(SNDDATAC_MODE); | ||
9667 | GET_REG32_LOOP(SNDBDS_MODE, 0x80); | ||
9668 | GET_REG32_LOOP(SNDBDI_MODE, 0x48); | ||
9669 | GET_REG32_1(SNDBDC_MODE); | ||
9670 | GET_REG32_LOOP(RCVLPC_MODE, 0x20); | ||
9671 | GET_REG32_LOOP(RCVLPC_SELLST_BASE, 0x15c); | ||
9672 | GET_REG32_LOOP(RCVDBDI_MODE, 0x0c); | ||
9673 | GET_REG32_LOOP(RCVDBDI_JUMBO_BD, 0x3c); | ||
9674 | GET_REG32_LOOP(RCVDBDI_BD_PROD_IDX_0, 0x44); | ||
9675 | GET_REG32_1(RCVDCC_MODE); | ||
9676 | GET_REG32_LOOP(RCVBDI_MODE, 0x20); | ||
9677 | GET_REG32_LOOP(RCVCC_MODE, 0x14); | ||
9678 | GET_REG32_LOOP(RCVLSC_MODE, 0x08); | ||
9679 | GET_REG32_1(MBFREE_MODE); | ||
9680 | GET_REG32_LOOP(HOSTCC_MODE, 0x100); | ||
9681 | GET_REG32_LOOP(MEMARB_MODE, 0x10); | ||
9682 | GET_REG32_LOOP(BUFMGR_MODE, 0x58); | ||
9683 | GET_REG32_LOOP(RDMAC_MODE, 0x08); | ||
9684 | GET_REG32_LOOP(WDMAC_MODE, 0x08); | ||
9685 | GET_REG32_1(RX_CPU_MODE); | ||
9686 | GET_REG32_1(RX_CPU_STATE); | ||
9687 | GET_REG32_1(RX_CPU_PGMCTR); | ||
9688 | GET_REG32_1(RX_CPU_HWBKPT); | ||
9689 | GET_REG32_1(TX_CPU_MODE); | ||
9690 | GET_REG32_1(TX_CPU_STATE); | ||
9691 | GET_REG32_1(TX_CPU_PGMCTR); | ||
9692 | GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110); | ||
9693 | GET_REG32_LOOP(FTQ_RESET, 0x120); | ||
9694 | GET_REG32_LOOP(MSGINT_MODE, 0x0c); | ||
9695 | GET_REG32_1(DMAC_MODE); | ||
9696 | GET_REG32_LOOP(GRC_MODE, 0x4c); | ||
9697 | if (tp->tg3_flags & TG3_FLAG_NVRAM) | ||
9698 | GET_REG32_LOOP(NVRAM_CMD, 0x24); | ||
9699 | |||
9700 | #undef __GET_REG32 | ||
9701 | #undef GET_REG32_LOOP | ||
9702 | #undef GET_REG32_1 | ||
9703 | 9756 | ||
9704 | tg3_full_unlock(tp); | 9757 | tg3_full_unlock(tp); |
9705 | } | 9758 | } |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 829a84ad80f2..99120100bf6a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -1954,6 +1954,8 @@ | |||
1954 | #define TG3_PCIE_PL_LO_PHYCTL5 0x00000014 | 1954 | #define TG3_PCIE_PL_LO_PHYCTL5 0x00000014 |
1955 | #define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ 0x80000000 | 1955 | #define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ 0x80000000 |
1956 | 1956 | ||
1957 | #define TG3_REG_BLK_SIZE 0x00008000 | ||
1958 | |||
1957 | /* OTP bit definitions */ | 1959 | /* OTP bit definitions */ |
1958 | #define TG3_OTP_AGCTGT_MASK 0x000000e0 | 1960 | #define TG3_OTP_AGCTGT_MASK 0x000000e0 |
1959 | #define TG3_OTP_AGCTGT_SHIFT 1 | 1961 | #define TG3_OTP_AGCTGT_SHIFT 1 |