From: Taku Izumi <izumi.taku@jp.fujitsu.com>
To: netdev@vger.kernel.org, Bruce Allan <bruce.w.allan@intel.com>,
"David S. Miller" <davem@davemloft.net>,
Jesse Brandeburg <jesse.brandeburg@intel.com>,
John Ronciak <john.ronciak@intel
Cc: Koki Sanagi <sanagi.koki@jp.fujitsu.com>,
Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>,
chavey@google.com
Subject: [PATCH v2 2/3] igb: add registers etc. printout code just before resetting adapters
Date: Fri, 22 Jan 2010 14:49:34 +0900 [thread overview]
Message-ID: <4B593C6E.5050405@jp.fujitsu.com> (raw)
In-Reply-To: <4B593B74.2020601@jp.fujitsu.com>
This patch adds registers (,tx/rx rings' status and so on) printout
code just before resetting adapters. This will be helpful for detecting
the root cause of adapters reset.
The default output is netdevice status (transstart, last_rx), registers,
and tx/rx rings' simple information. TX/RX descriptors information and
buffer_info can be output by changing the dump_flag module option, but,
of course, the amount of output becomes quite large.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
drivers/net/igb/e1000_hw.h | 7 +
drivers/net/igb/e1000_regs.h | 21 +++
drivers/net/igb/igb_main.c | 294 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 322 insertions(+)
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c
+++ net-next-2.6/drivers/net/igb/igb_main.c
@@ -60,6 +60,14 @@ static const struct e1000_info *igb_info
[board_82575] = &e1000_82575_info,
};
+static unsigned int dump_flag = 1;
+module_param(dump_flag, uint, 0644);
+MODULE_PARM_DESC(dump_flag, "Dump Flag");
+#define IGB_DUMP_REGS (1 << 0)
+#define IGB_DUMP_TX_RINGS (1 << 1)
+#define IGB_DUMP_RX_RINGS (1 << 2)
+#define IGB_DUMP_BUFFERS (1 << 3)
+
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 },
@@ -189,6 +197,291 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Eth
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+/*
+ * igb_regdump - register printout routine
+ */
+static void igb_regdump(struct e1000_hw *hw, u32 reg,
+ char *name, u32 (*get_regofs)(int))
+{
+ printk(KERN_ERR "%-15s %08x\n", name, rd32(reg));
+}
+
+/*
+ * igb_regdump_n - register printout routine
+ */
+static void igb_regdump_n(struct e1000_hw *hw, u32 reg,
+ char *name, u32 (*get_regofs)(int))
+{
+ int n = 0;
+ char rname[16];
+
+ if (!get_regofs)
+ return;
+
+ snprintf(rname, 16, "%s%s", name, "[0-3]");
+ printk(KERN_ERR "%-15s ", rname);
+ for (n = 0; n < 4; n++)
+ printk("%08x ", rd32(get_regofs(n)));
+ printk("\n");
+}
+
+static const struct igb_reg_info igb_reg_info_tbl[] = {
+
+ /* General Registers */
+ {E1000_CTRL, "CTRL", NULL, igb_regdump},
+ {E1000_STATUS, "STATUS", NULL, igb_regdump},
+ {E1000_CTRL_EXT, "CTRL_EXT", NULL, igb_regdump},
+
+ /* Interrupt Registers */
+ {E1000_ICR, "ICR", NULL, igb_regdump},
+
+ /* RX Registers */
+ {E1000_RCTL, "RCTL", NULL, igb_regdump},
+ {E1000_RDLEN(0), "RDLEN", get_regofs_RDLEN, igb_regdump_n},
+ {E1000_RDH(0), "RDH", get_regofs_RDH, igb_regdump_n},
+ {E1000_RDT(0), "RDT", get_regofs_RDT, igb_regdump_n},
+ {E1000_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, igb_regdump_n},
+ {E1000_RDBAL(0), "RDBAL", get_regofs_RDBAL, igb_regdump_n},
+ {E1000_RDBAH(0), "RDBAH", get_regofs_RDBAH, igb_regdump_n},
+
+ /* TX Registers */
+ {E1000_TCTL, "TCTL", NULL, igb_regdump},
+ {E1000_TDBAL(0), "TDBAL", get_regofs_TDBAL, igb_regdump_n},
+ {E1000_TDBAH(0), "TDBAH", get_regofs_TDBAH, igb_regdump_n},
+ {E1000_TDLEN(0), "TDLEN", get_regofs_TDLEN, igb_regdump_n},
+ {E1000_TDH(0), "TDH", get_regofs_TDH, igb_regdump_n},
+ {E1000_TDT(0), "TDT", get_regofs_TDT, igb_regdump_n},
+ {E1000_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, igb_regdump_n},
+ {E1000_TDFH, "TDFH", NULL, igb_regdump},
+ {E1000_TDFT, "TDFT", NULL, igb_regdump},
+ {E1000_TDFHS, "TDFHS", NULL, igb_regdump},
+ {E1000_TDFPC, "TDFPC", NULL, igb_regdump},
+
+ /* List Terminator */
+ {}
+};
+
+/*
+ * igb_dump - Print registers, tx-rings and rx-rings
+ */
+static void igb_dump(struct igb_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
+ struct igb_reg_info *reginfo;
+ int n = 0;
+ struct igb_ring *tx_ring;
+ union e1000_adv_tx_desc *tx_desc;
+ struct my_u0 { u64 a; u64 b; } *u0;
+ struct igb_buffer *buffer_info;
+ struct igb_ring *rx_ring;
+ union e1000_adv_rx_desc *rx_desc;
+ u32 staterr;
+ int i = 0;
+
+ /* Print netdevice Info */
+ if (netdev) {
+ dev_err(&adapter->pdev->dev, "Net device Info\n");
+ printk(KERN_ERR "Device Name state "
+ "trans_start last_rx\n");
+ printk(KERN_ERR "%-15s %016lX %016lX %016lX\n",
+ netdev->name,
+ netdev->state,
+ netdev->trans_start,
+ netdev->last_rx);
+ }
+
+ /* Print Registers */
+ if ((dump_flag & IGB_DUMP_REGS) == 0)
+ goto tx_ring_summary;
+
+ dev_err(&adapter->pdev->dev, "Register Dump\n");
+ printk(KERN_ERR " Register Name [value ]\n");
+ for (reginfo = (struct igb_reg_info *)igb_reg_info_tbl;
+ reginfo->name; reginfo++) {
+ reginfo->dump_reg(hw, reginfo->reg, reginfo->name,
+ reginfo->get_regofs);
+ }
+
+ /* Print TX Ring Summary */
+tx_ring_summary:
+ if (!netdev || !netif_running(netdev))
+ goto exit;
+
+ dev_err(&adapter->pdev->dev, "TX Rings Summary\n");
+ printk(KERN_ERR "Queue [NTU] [NTC] [bi(ntc)->dma ]"
+ " leng ntw timestamp\n");
+ for (n = 0; n < adapter->num_tx_queues; n++) {
+ tx_ring = &adapter->tx_ring[n];
+ buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
+ printk(KERN_ERR " %5d %5X %5X %016llX %04X %3X %016llX\n",
+ n, tx_ring->next_to_use, tx_ring->next_to_clean,
+ (u64)buffer_info->dma,
+ buffer_info->length,
+ buffer_info->next_to_watch,
+ (u64)buffer_info->time_stamp);
+ }
+
+ /* Print TX Rings */
+ if ((dump_flag & IGB_DUMP_TX_RINGS) == 0)
+ goto rx_ring_summary;
+
+ dev_err(&adapter->pdev->dev, "TX Rings Dump\n");
+
+ /* Transmit Descriptor Formats
+ *
+ * Advanced Transmit Descriptor
+ * +--------------------------------------------------------------+
+ * 0 | Buffer Address [63:0] |
+ * +--------------------------------------------------------------+
+ * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
+ * +--------------------------------------------------------------+
+ * 63 46 45 40 39 38 36 35 32 31 24 15 0
+ */
+
+ for (n = 0; n < adapter->num_tx_queues; n++) {
+ tx_ring = &adapter->tx_ring[n];
+ printk(KERN_ERR "------------------------------------\n");
+ printk(KERN_ERR "TX QUEUE INDEX = %d\n", tx_ring->queue_index);
+ printk(KERN_ERR "------------------------------------\n");
+ printk(KERN_ERR "T [desc] [address 63:0 ] "
+ "[PlPOCIStDDM Ln] [bi->dma ] "
+ "leng ntw timestamp bi->skb\n");
+
+ for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+ tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
+ u0 = (struct my_u0 *)tx_desc;
+ printk(KERN_ERR "T [0x%03X] %016llX %016llX %016llX"
+ " %04X %3X %016llX %p", i,
+ le64_to_cpu(u0->a),
+ le64_to_cpu(u0->b),
+ (u64)buffer_info->dma,
+ buffer_info->length,
+ buffer_info->next_to_watch,
+ (u64)buffer_info->time_stamp,
+ buffer_info->skb);
+ if (i == tx_ring->next_to_use &&
+ i == tx_ring->next_to_clean)
+ printk(" NTC/U\n");
+ else if (i == tx_ring->next_to_use)
+ printk(" NTU\n");
+ else if (i == tx_ring->next_to_clean)
+ printk(" NTC\n");
+ else
+ printk("\n");
+
+ if ((dump_flag & IGB_DUMP_BUFFERS) &&
+ buffer_info->dma != 0)
+ print_hex_dump(KERN_ERR, "",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1, phys_to_virt(buffer_info->dma),
+ buffer_info->length, true);
+ }
+ }
+
+ /* Print RX Rings Summary */
+rx_ring_summary:
+ dev_err(&adapter->pdev->dev, "RX Rings Summary\n");
+ printk(KERN_ERR "Queue [NTU] [NTC]\n");
+ for (n = 0; n < adapter->num_rx_queues; n++) {
+ rx_ring = &adapter->rx_ring[n];
+ printk(KERN_ERR " %5d %5X %5X\n", n,
+ rx_ring->next_to_use, rx_ring->next_to_clean);
+ }
+
+ /* Print RX Rings */
+ if ((dump_flag & IGB_DUMP_RX_RINGS) == 0)
+ goto exit;
+
+ dev_err(&adapter->pdev->dev, "RX Rings Dump\n");
+
+ /* Advanced Receive Descriptor (Read) Format
+ * 63 1 0
+ * +-----------------------------------------------------+
+ * 0 | Packet Buffer Address [63:1] |A0/NSE|
+ * +----------------------------------------------+------+
+ * 8 | Header Buffer Address [63:1] | DD |
+ * +-----------------------------------------------------+
+ *
+ *
+ * Advanced Receive Descriptor (Write-Back) Format
+ *
+ * 63 48 47 32 31 30 21 20 17 16 4 3 0
+ * +------------------------------------------------------+
+ * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
+ * | Checksum Ident | | | | Type | Type |
+ * +------------------------------------------------------+
+ * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+ * +------------------------------------------------------+
+ * 63 48 47 32 31 20 19 0
+ */
+
+ for (n = 0; n < adapter->num_rx_queues; n++) {
+ rx_ring = &adapter->rx_ring[n];
+ printk(KERN_ERR "------------------------------------\n");
+ printk(KERN_ERR "RX QUEUE INDEX = %d\n", rx_ring->queue_index);
+ printk(KERN_ERR "------------------------------------\n");
+ printk(KERN_ERR "R [desc] [ PktBuf A0] "
+ "[ HeadBuf DD] [bi->dma ] [bi->skb] "
+ "<-- Adv Rx Read format\n");
+ printk(KERN_ERR "RWB[desc] [PcsmIpSHl PtRs] "
+ "[vl er S cks ln] ---------------- [bi->skb] "
+ "<-- Adv Rx Write-Back format\n");
+
+ for (i = 0; i < rx_ring->count; i++) {
+ buffer_info = &rx_ring->buffer_info[i];
+ rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
+ u0 = (struct my_u0 *)rx_desc;
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ if (staterr & E1000_RXD_STAT_DD) {
+ /* Descriptor Done */
+ printk(KERN_ERR "RWB[0x%03X] %016llX "
+ "%016llX ---------------- %p", i,
+ le64_to_cpu(u0->a),
+ le64_to_cpu(u0->b),
+ buffer_info->skb);
+ } else {
+ printk(KERN_ERR "R [0x%03X] %016llX "
+ "%016llX %016llX %p", i,
+ le64_to_cpu(u0->a),
+ le64_to_cpu(u0->b),
+ (u64)buffer_info->dma,
+ buffer_info->skb);
+
+ if (dump_flag & IGB_DUMP_BUFFERS) {
+ print_hex_dump(KERN_ERR, "",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1,
+ phys_to_virt(buffer_info->dma),
+ rx_ring->rx_buffer_len, true);
+ if (rx_ring->rx_buffer_len
+ < IGB_RXBUFFER_1024)
+ print_hex_dump(KERN_ERR, "",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1,
+ phys_to_virt(
+ buffer_info->page_dma +
+ buffer_info->page_offset),
+ PAGE_SIZE/2, true);
+ }
+ }
+
+ if (i == rx_ring->next_to_use)
+ printk(" NTU\n");
+ else if (i == rx_ring->next_to_clean)
+ printk(" NTC\n");
+ else
+ printk("\n");
+
+ }
+ }
+
+exit:
+ return;
+}
+
+
/**
* igb_read_clock - read raw cycle counter (to be used by time counter)
*/
@@ -3854,6 +4147,7 @@ static void igb_reset_task(struct work_s
struct igb_adapter *adapter;
adapter = container_of(work, struct igb_adapter, reset_task);
+ igb_dump(adapter);
igb_reinit_locked(adapter);
}
Index: net-next-2.6/drivers/net/igb/e1000_regs.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_regs.h
+++ net-next-2.6/drivers/net/igb/e1000_regs.h
@@ -322,4 +322,25 @@
/* DMA Coalescing registers */
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
+
+
+#define IGB_GET_REGOFS_FUNC(name) \
+static inline u32 get_regofs_##name(int n) \
+{ \
+ return E1000_##name(n); \
+} \
+
+IGB_GET_REGOFS_FUNC(RDLEN)
+IGB_GET_REGOFS_FUNC(RDH)
+IGB_GET_REGOFS_FUNC(RDT)
+IGB_GET_REGOFS_FUNC(RXDCTL)
+IGB_GET_REGOFS_FUNC(RDBAL)
+IGB_GET_REGOFS_FUNC(RDBAH)
+IGB_GET_REGOFS_FUNC(TDBAL)
+IGB_GET_REGOFS_FUNC(TDBAH)
+IGB_GET_REGOFS_FUNC(TDLEN)
+IGB_GET_REGOFS_FUNC(TDH)
+IGB_GET_REGOFS_FUNC(TDT)
+IGB_GET_REGOFS_FUNC(TXDCTL)
+
#endif
Index: net-next-2.6/drivers/net/igb/e1000_hw.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_hw.h
+++ net-next-2.6/drivers/net/igb/e1000_hw.h
@@ -508,6 +508,13 @@ struct e1000_hw {
u8 revision_id;
};
+struct igb_reg_info {
+ u32 reg;
+ char *name;
+ u32 (*get_regofs)(int);
+ void (*dump_reg)(struct e1000_hw *, u32, char *, u32 (*)(int));
+};
+
#ifdef DEBUG
extern char *igb_get_hw_dev_name(struct e1000_hw *hw);
#define hw_dbg(format, arg...) \
next prev parent reply other threads:[~2010-01-22 5:49 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-22 5:45 [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters Taku Izumi
2010-01-22 5:48 ` [PATCH v2 1/3] e1000e: " Taku Izumi
2010-01-22 8:48 ` Taku Izumi
2010-02-19 19:19 ` Laurent Chavey
2010-01-22 5:49 ` Taku Izumi [this message]
2010-01-22 8:49 ` [PATCH v2 2/3] igb: " Taku Izumi
2010-01-22 5:50 ` [PATCH v2 3/3] ixgbe: " Taku Izumi
2010-01-22 8:50 ` Taku Izumi
2010-01-22 6:25 ` [PATCH v2 0/3] e1000e,igb,ixgbe: " Joe Perches
2010-01-22 8:46 ` Taku Izumi
2010-01-22 21:54 ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Brandeburg, Jesse
2010-01-26 10:21 ` [PATCH v2 0/3] e1000e,igb,ixgbe: " Taku Izumi
2010-02-17 19:10 ` Brandeburg, Jesse
2010-02-17 19:32 ` Brandeburg, Jesse
2010-02-19 8:16 ` Taku Izumi
2010-02-19 11:20 ` Jeff Kirsher
2010-02-24 19:36 ` Laurent Chavey
2010-02-25 0:24 ` Taku Izumi
2010-02-25 0:30 ` Taku Izumi
2010-02-26 9:05 ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Taku Izumi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B593C6E.5050405@jp.fujitsu.com \
--to=izumi.taku@jp.fujitsu.com \
--cc=bruce.w.allan@intel.com \
--cc=chavey@google.com \
--cc=davem@davemloft.net \
--cc=jesse.brandeburg@intel.com \
--cc=john.ronciak@intel \
--cc=kaneshige.kenji@jp.fujitsu.com \
--cc=netdev@vger.kernel.org \
--cc=sanagi.koki@jp.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.