All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
@ 2010-01-22  5:45 Taku Izumi
  2010-01-22  5:48 ` [PATCH v2 1/3] e1000e: " Taku Izumi
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  5:45 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey

Hi Jeff,

This patchset is the update version of "register etc. printout code" patch. (sorry
for late reply)
The old one is http://marc.info/?l=linux-netdev&m=126286127208276&w=2

v1 -> v2:
 - replaced hexdump() with print_hex_dump()
 - changed the register printout inplementation (for-switch-case -> data-driven-table)

However the default value of "dump_flag" is not changed (still 1).
The reason I didn't change is
 - I think HW index (TDH,TDT..) and SW index (NTC,NTU) are at least necessary
 - the amount of default output is not so large (see bellow)
 - the adapter resetting problem doesn't happen frequently


The default output sample (NOT the actual hangup case) is as follows:

Jan 22 14:17:14 fedora11 kernel: igb 0000:03:00.0: Net device Info
Jan 22 14:17:14 fedora11 kernel: Device Name     state            trans_start
last_rx
Jan 22 14:17:14 fedora11 kernel: eth1            0000000000000003 00000000FFFB922A
0000000000000000
Jan 22 14:17:14 fedora11 kernel: igb 0000:03:00.0: Register Dump
Jan 22 14:17:14 fedora11 kernel: Register Name   [value ]
Jan 22 14:17:14 fedora11 kernel: CTRL            18c00241
Jan 22 14:17:14 fedora11 kernel: STATUS          00080783
Jan 22 14:17:14 fedora11 kernel: CTRL_EXT        10180c00
Jan 22 14:17:14 fedora11 kernel: ICR             00000081
Jan 22 14:17:14 fedora11 kernel: RCTL            0400803a
Jan 22 14:17:14 fedora11 kernel: RDLEN[0-3]      00001000 00001000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: RDH[0-3]        000000bc 00000000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: RDT[0-3]        000000ba 000000fe 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: RXDCTL[0-3]     02010810 02010810 00010000 00010000
Jan 22 14:17:14 fedora11 kernel: RDBAL[0-3]      35e48000 35f68000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: RDBAH[0-3]      00000000 00000000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TCTL            a503f0fa
Jan 22 14:17:14 fedora11 kernel: TDBAL[0-3]      35e4c000 35ef1000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TDBAH[0-3]      00000000 00000000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TDLEN[0-3]      00001000 00001000 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TDH[0-3]        00000000 0000001e 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TDT[0-3]        00000000 0000001e 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TXDCTL[0-3]     02000108 02000108 00000000 00000000
Jan 22 14:17:14 fedora11 kernel: TDFH            40020272
Jan 22 14:17:14 fedora11 kernel: TDFT            00000270
Jan 22 14:17:14 fedora11 kernel: TDFHS           00000272
Jan 22 14:17:14 fedora11 kernel: TDFPC           00000000
Jan 22 14:17:14 fedora11 kernel: igb 0000:03:00.0: TX Rings Summary
Jan 22 14:17:14 fedora11 kernel: Queue [NTU] [NTC] [bi(ntc)->dma  ] leng ntw timestamp
Jan 22 14:17:14 fedora11 kernel:     0     0     0 0000000000000000 0000   0
0000000000000000
Jan 22 14:17:14 fedora11 kernel:     1    1E    1E 0000000000000000 0000   0
0000000000000000
Jan 22 14:17:14 fedora11 kernel: igb 0000:03:00.0: RX Rings Summary
Jan 22 14:17:14 fedora11 kernel: Queue [NTU] [NTC]
Jan 22 14:17:14 fedora11 kernel:     0    BB    BC
Jan 22 14:17:14 fedora11 kernel:     1    FF     0


Best regards,
Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/3] e1000e: add registers etc. printout code just before resetting adapters
  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 ` Taku Izumi
  2010-01-22  8:48   ` Taku Izumi
  2010-02-19 19:19   ` Laurent Chavey
  2010-01-22  5:49 ` [PATCH v2 2/3] igb: " Taku Izumi
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  5:48 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey


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/e1000e/hw.h     |   27 +++
 drivers/net/e1000e/netdev.c |  341 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 368 insertions(+)
Index: net-next-2.6/drivers/net/e1000e/netdev.c
===================================================================
--- net-next-2.6.orig/drivers/net/e1000e/netdev.c
+++ net-next-2.6/drivers/net/e1000e/netdev.c
@@ -52,6 +52,14 @@
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;

+static unsigned int dump_flag = 1;
+module_param(dump_flag, uint, 0644);
+MODULE_PARM_DESC(dump_flag, "Dump Flag");
+#define E1000_DUMP_REGS		(1 << 0)
+#define E1000_DUMP_TX_RINGS	(1 << 1)
+#define E1000_DUMP_RX_RINGS	(1 << 2)
+#define E1000_DUMP_BUFFERS	(1 << 3)
+
 static const struct e1000_info *e1000_info_tbl[] = {
 	[board_82571]		= &e1000_82571_info,
 	[board_82572]		= &e1000_82572_info,
@@ -65,6 +73,338 @@ static const struct e1000_info *e1000_in
 	[board_pchlan]		= &e1000_pch_info,
 };

+/*
+ * e1000_regdump - register printout routine
+ */
+static void e1000_regdump(struct e1000_hw *hw, u32 reg,
+			  char *name, u32 (*get_regofs)(int))
+{
+	printk(KERN_ERR "%-15s %08x\n", name, __er32(hw, reg));
+}
+
+/*
+ * e1000_regdump_n - register printout routine
+ */
+static void e1000_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-1]");
+	printk(KERN_ERR "%-15s ", rname);
+	for (n = 0; n < 2; n++)
+		printk("%08x ", __er32(hw, get_regofs(n)));
+	printk("\n");
+}
+
+static const struct e1000_reg_info e1000_reg_info_tbl[] = {
+
+	/* General Registers */
+	{E1000_CTRL, "CTRL", NULL, e1000_regdump},
+	{E1000_STATUS, "STATUS", NULL, e1000_regdump},
+	{E1000_CTRL_EXT, "CTRL_EXT", NULL, e1000_regdump},
+
+	/* Interrupt Registers */
+	{E1000_ICR, "ICR", NULL, e1000_regdump},
+
+	/* RX Registers */
+	{E1000_RCTL, "RCTL", NULL, e1000_regdump},
+	{E1000_RDLEN, "RDLEN", NULL, e1000_regdump},
+	{E1000_RDH, "RDH", NULL, e1000_regdump},
+	{E1000_RDT, "RDT", NULL, e1000_regdump},
+	{E1000_RDTR, "RDTR", NULL, e1000_regdump},
+	{E1000_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, e1000_regdump_n},
+	{E1000_ERT, "ERT", NULL, e1000_regdump},
+	{E1000_RDBAL, "RDBAL", NULL, e1000_regdump},
+	{E1000_RDBAH, "RDBAH", NULL, e1000_regdump},
+	{E1000_RDFH, "RDFH", NULL, e1000_regdump},
+	{E1000_RDFT, "RDFT", NULL, e1000_regdump},
+	{E1000_RDFHS, "RDFHS", NULL, e1000_regdump},
+	{E1000_RDFTS, "RDFTS", NULL, e1000_regdump},
+	{E1000_RDFPC, "RDFPC", NULL, e1000_regdump},
+
+	/* TX Registers */
+	{E1000_TCTL, "TCTL", NULL, e1000_regdump},
+	{E1000_TDBAL, "TDBAL", NULL, e1000_regdump},
+	{E1000_TDBAH, "TDBAH", NULL, e1000_regdump},
+	{E1000_TDLEN, "TDLEN", NULL, e1000_regdump},
+	{E1000_TDH, "TDH", NULL, e1000_regdump},
+	{E1000_TDT, "TDT", NULL, e1000_regdump},
+	{E1000_TIDV, "TIDV", NULL, e1000_regdump},
+	{E1000_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, e1000_regdump_n},
+	{E1000_TADV, "TADV", NULL, e1000_regdump},
+	{E1000_TARC(0), "TARC", get_regofs_TARC, e1000_regdump_n},
+	{E1000_TDFH, "TDFH", NULL, e1000_regdump},
+	{E1000_TDFT, "TDFT", NULL, e1000_regdump},
+	{E1000_TDFHS, "TDFHS", NULL, e1000_regdump},
+	{E1000_TDFTS, "TDFTS", NULL, e1000_regdump},
+	{E1000_TDFPC, "TDFPC", NULL, e1000_regdump},
+
+	/* List Terminator */
+	{}
+};
+
+/*
+ * e1000e_dump - Print registers, tx-ring and rx-ring
+ */
+static void e1000e_dump(struct e1000_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct e1000_hw *hw = &adapter->hw;
+	struct e1000_reg_info *reginfo;
+	struct e1000_ring *tx_ring = adapter->tx_ring;
+	struct e1000_tx_desc *tx_desc;
+	struct my_u0 { u64 a; u64 b; } *u0;
+	struct e1000_buffer *buffer_info;
+	struct e1000_ring *rx_ring = adapter->rx_ring;
+	union e1000_rx_desc_packet_split *rx_desc_ps;
+	struct e1000_rx_desc *rx_desc;
+	struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1;
+	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 & E1000_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 e1000_reg_info *)e1000_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");
+	buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
+	printk(KERN_ERR " %5d %5X %5X %016llX %04X %3X %016llX\n",
+		0, 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 & E1000_DUMP_TX_RINGS) == 0)
+		goto rx_ring_summary;
+
+	dev_err(&adapter->pdev->dev, "TX Rings Dump\n");
+
+	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
+	 *
+	 * Legacy Transmit Descriptor
+	 *   +--------------------------------------------------------------+
+	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
+	 *   +--------------------------------------------------------------+
+	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
+	 *   +--------------------------------------------------------------+
+	 *   63       48 47        36 35    32 31     24 23    16 15        0
+	 *
+	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
+	 *   63      48 47    40 39       32 31             16 15    8 7      0
+	 *   +----------------------------------------------------------------+
+	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
+	 *   +----------------------------------------------------------------+
+	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
+	 *   +----------------------------------------------------------------+
+	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
+	 *
+	 * Extended Data Descriptor (DTYP=0x1)
+	 *   +----------------------------------------------------------------+
+	 * 0 |                     Buffer Address [63:0]                      |
+	 *   +----------------------------------------------------------------+
+	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
+	 *   +----------------------------------------------------------------+
+	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
+	 */
+	printk(KERN_ERR "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Legacy format\n");
+	printk(KERN_ERR "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Ext Context format\n");
+	printk(KERN_ERR "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Ext Data format\n");
+	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+		tx_desc = E1000_TX_DESC(*tx_ring, i);
+		buffer_info = &tx_ring->buffer_info[i];
+		u0 = (struct my_u0 *)tx_desc;
+		printk(KERN_ERR "T%c[0x%03X]    %016llX %016llX %016llX "
+			"%04X  %3X %016llX %p",
+		       (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
+			((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), 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 & E1000_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");
+	printk(KERN_ERR " %5d %5X %5X\n", 0,
+		rx_ring->next_to_use, rx_ring->next_to_clean);
+
+	/* Print RX Rings */
+	if ((dump_flag & E1000_DUMP_RX_RINGS) == 0)
+		goto exit;
+
+	dev_err(&adapter->pdev->dev, "RX Rings Dump\n");
+	switch (adapter->rx_ps_pages) {
+	case 1:
+	case 2:
+	case 3:
+		/* [Extended] Packet Split Receive Descriptor Format
+		 *
+		 *    +-----------------------------------------------------+
+		 *  0 |                Buffer Address 0 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 *  8 |                Buffer Address 1 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 16 |                Buffer Address 2 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 24 |                Buffer Address 3 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 */
+		printk(KERN_ERR "R  [desc]      [buffer 0 63:0 ] "
+			"[buffer 1 63:0 ] "
+		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
+		       "[bi->skb] <-- Ext Pkt Split format\n");
+		/* [Extended] Receive Descriptor (Write-Back) Format
+		 *
+		 *   63       48 47    32 31     13 12    8 7    4 3        0
+		 *   +------------------------------------------------------+
+		 * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
+		 *   | Checksum | Ident  |         | Queue |      |  Type   |
+		 *   +------------------------------------------------------+
+		 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+		 *   +------------------------------------------------------+
+		 *   63       48 47    32 31            20 19               0
+		 */
+		printk(KERN_ERR "RWB[desc]      [ck ipid mrqhsh] "
+			"[vl   l0 ee  es] "
+		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
+		       "[bi->skb] <-- Ext Rx Write-Back format\n");
+		for (i = 0; i < rx_ring->count; i++) {
+			buffer_info = &rx_ring->buffer_info[i];
+			rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
+			u1 = (struct my_u1 *)rx_desc_ps;
+			staterr =
+				le32_to_cpu(rx_desc_ps->wb.middle.status_error);
+			if (staterr & E1000_RXD_STAT_DD) {
+				/* Descriptor Done */
+				printk(KERN_ERR "RWB[0x%03X]     %016llX "
+					"%016llX %016llX %016llX "
+					"---------------- %p", i,
+					le64_to_cpu(u1->a),
+					le64_to_cpu(u1->b),
+					le64_to_cpu(u1->c),
+					le64_to_cpu(u1->d),
+					buffer_info->skb);
+			} else {
+				printk(KERN_ERR "R  [0x%03X]     %016llX "
+					"%016llX %016llX %016llX %016llX %p", i,
+					le64_to_cpu(u1->a),
+					le64_to_cpu(u1->b),
+					le64_to_cpu(u1->c),
+					le64_to_cpu(u1->d),
+					(u64)buffer_info->dma,
+					buffer_info->skb);
+
+				if (dump_flag & E1000_DUMP_BUFFERS)
+					print_hex_dump(KERN_ERR, "",
+						DUMP_PREFIX_ADDRESS, 16, 1,
+						phys_to_virt(buffer_info->dma),
+						adapter->rx_ps_bsize0, 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");
+		}
+		break;
+	default:
+	case 0:
+		/* Legacy Receive Descriptor Format
+		 *
+		 * +-----------------------------------------------------+
+		 * |                Buffer Address [63:0]                |
+		 * +-----------------------------------------------------+
+		 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
+		 * +-----------------------------------------------------+
+		 * 63       48 47    40 39      32 31         16 15      0
+		 */
+		printk(KERN_ERR "Rl[desc]     [address 63:0  ] "
+			"[vl er S cks ln] [bi->dma       ] [bi->skb] "
+			"<-- Legacy format\n");
+		for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
+			rx_desc = E1000_RX_DESC(*rx_ring, i);
+			buffer_info = &rx_ring->buffer_info[i];
+			u0 = (struct my_u0 *)rx_desc;
+			printk(KERN_ERR "Rl[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 (i == rx_ring->next_to_use)
+				printk(" NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(" NTC\n");
+			else
+				printk("\n");
+
+			if (dump_flag & E1000_DUMP_BUFFERS)
+				print_hex_dump(KERN_ERR, "",
+					DUMP_PREFIX_ADDRESS,
+					16, 1, phys_to_virt(buffer_info->dma),
+					adapter->rx_buffer_len, true);
+		}
+	}
+
+exit:
+	return;
+}
+
 /**
  * e1000_desc_unused - calculate if we have unused descriptors
  **/
@@ -4247,6 +4587,7 @@ static void e1000_reset_task(struct work
 	struct e1000_adapter *adapter;
 	adapter = container_of(work, struct e1000_adapter, reset_task);

+	e1000e_dump(adapter);
 	e1000e_reinit_locked(adapter);
 }

Index: net-next-2.6/drivers/net/e1000e/hw.h
===================================================================
--- net-next-2.6.orig/drivers/net/e1000e/hw.h
+++ net-next-2.6/drivers/net/e1000e/hw.h
@@ -92,6 +92,11 @@ enum e1e_registers {
 	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
 	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
 	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
+	E1000_RDFH     = 0x02410, /* Rx Data FIFO Head - RW */
+	E1000_RDFT     = 0x02418, /* Rx Data FIFO Tail - RW */
+	E1000_RDFHS    = 0x02420, /* Rx Data FIFO Head Saved - RW */
+	E1000_RDFTS    = 0x02428, /* Rx Data FIFO Tail Saved - RW */
+	E1000_RDFPC    = 0x02430, /* Rx Data FIFO Packet Count - RW */
 	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
 	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
 	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
@@ -101,6 +106,11 @@ enum e1e_registers {
 	E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
 #define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
 	E1000_RADV     = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
+	E1000_TDFH     = 0x03410, /* Tx Data FIFO Head - RW */
+	E1000_TDFT     = 0x03418, /* Tx Data FIFO Tail - RW */
+	E1000_TDFHS    = 0x03420, /* Tx Data FIFO Head Saved - RW */
+	E1000_TDFTS    = 0x03428, /* Tx Data FIFO Tail Saved - RW */
+	E1000_TDFPC    = 0x03430, /* Tx Data FIFO Packet Count - RW */

 /* Convenience macros
  *
@@ -219,6 +229,23 @@ enum e1e_registers {
 	E1000_HICR      = 0x08F00, /* Host Interface Control */
 };

+struct e1000_reg_info {
+	u32 reg;
+	char *name;
+	u32 (*get_regofs)(int);
+	void (*dump_reg)(struct e1000_hw *, u32, char *, u32 (*)(int));
+};
+
+#define E1000_GET_REGOFS_FUNC(name)				\
+static inline u32 get_regofs_##name(int n)			\
+{								\
+	return E1000_##name(n);						\
+}								\
+
+E1000_GET_REGOFS_FUNC(RXDCTL)
+E1000_GET_REGOFS_FUNC(TXDCTL)
+E1000_GET_REGOFS_FUNC(TARC)
+
 #define E1000_MAX_PHY_ADDR		4

 /* IGP01E1000 Specific Registers */


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 2/3] igb: add registers etc. printout code just before resetting adapters
  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  5:49 ` Taku Izumi
  2010-01-22  8:49   ` Taku Izumi
  2010-01-22  5:50 ` [PATCH v2 3/3] ixgbe: " Taku Izumi
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  5:49 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey


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...) \



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 3/3] ixgbe: add registers etc. printout code just before resetting adapters
  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  5:49 ` [PATCH v2 2/3] igb: " Taku Izumi
@ 2010-01-22  5:50 ` 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 21:54 ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Brandeburg, Jesse
  4 siblings, 1 reply; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  5:50 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey


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/ixgbe/ixgbe_main.c |  293 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_type.h |   29 ++++
 2 files changed, 322 insertions(+)

Index: net-next-2.6/drivers/net/ixgbe/ixgbe_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/ixgbe/ixgbe_main.c
+++ net-next-2.6/drivers/net/ixgbe/ixgbe_main.c
@@ -60,6 +60,15 @@ static const struct ixgbe_info *ixgbe_in
 	[board_82599] = &ixgbe_82599_info,
 };

+
+static unsigned int dump_flag = 1;
+module_param(dump_flag, uint, 0644);
+MODULE_PARM_DESC(dump_flag, "Dump Flag");
+#define IXGBE_DUMP_REGS		(1 << 0)
+#define IXGBE_DUMP_TX_RINGS	(1 << 1)
+#define IXGBE_DUMP_RX_RINGS	(1 << 2)
+#define IXGBE_DUMP_BUFFERS	(1 << 3)
+
 /* ixgbe_pci_tbl - PCI Device ID Table
  *
  * Wildcard entries (PCI_ANY_ID) should come last
@@ -174,6 +183,289 @@ static inline void ixgbe_disable_sriov(s
 	adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
 }

+/*
+ * ixgbe_regdump - register printout routine
+ */
+static void ixgbe_regdump(struct ixgbe_hw *hw, u32 reg,
+			  char *name, u32 (*get_regofs)(int))
+{
+	printk(KERN_ERR "%-15s %08x\n", name, IXGBE_READ_REG(hw, reg));
+}
+
+/*
+ * ixgbe_regdump_n - register printout routine
+ */
+static void ixgbe_regdump_n(struct ixgbe_hw *hw, u32 reg,
+			    char *name, u32 (*get_regofs)(int))
+{
+	int i = 0, j = 0;
+	char rname[16];
+
+	if (!get_regofs)
+		return;
+
+	for (i = 0; i < 8; i++) {
+		snprintf(rname, 16, "%s[%d-%d]", name, i*8, i*8+7);
+		printk(KERN_ERR "%-15s ", rname);
+		for (j = 0; j < 8; j++)
+			printk("%08x ", IXGBE_READ_REG(hw, get_regofs(i*8+j)));
+		printk("\n");
+	}
+}
+
+static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
+
+	/* General Registers */
+	{IXGBE_CTRL, "CTRL", NULL, ixgbe_regdump},
+	{IXGBE_STATUS, "STATUS", NULL, ixgbe_regdump},
+	{IXGBE_CTRL_EXT, "CTRL_EXT", NULL, ixgbe_regdump},
+
+	/* Interrupt Registers */
+	{IXGBE_EICR, "EICR", NULL, ixgbe_regdump},
+
+	/* RX Registers */
+	{IXGBE_SRRCTL(0), "SRRCTL", get_regofs_SRRCTL, ixgbe_regdump_n},
+	{IXGBE_DCA_RXCTRL(0), "DRXCTL", get_regofs_DCA_RXCTRL, ixgbe_regdump_n},
+	{IXGBE_RDLEN(0), "RDLEN", get_regofs_RDLEN, ixgbe_regdump_n},
+	{IXGBE_RDH(0), "RDH", get_regofs_RDH, ixgbe_regdump_n},
+	{IXGBE_RDT(0), "RDT", get_regofs_RDT, ixgbe_regdump_n},
+	{IXGBE_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, ixgbe_regdump_n},
+	{IXGBE_RDBAL(0), "RDBAL", get_regofs_RDBAL, ixgbe_regdump_n},
+	{IXGBE_RDBAH(0), "RDBAH", get_regofs_RDBAH, ixgbe_regdump_n},
+
+	/* TX Registers */
+	{IXGBE_TDBAL(0), "TDBAL", get_regofs_TDBAL, ixgbe_regdump_n},
+	{IXGBE_TDBAH(0), "TDBAH", get_regofs_TDBAH, ixgbe_regdump_n},
+	{IXGBE_TDLEN(0), "TDLEN", get_regofs_TDLEN, ixgbe_regdump_n},
+	{IXGBE_TDH(0), "TDH", get_regofs_TDH, ixgbe_regdump_n},
+	{IXGBE_TDT(0), "TDT", get_regofs_TDT, ixgbe_regdump_n},
+	{IXGBE_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, ixgbe_regdump_n},
+
+	/* List Terminator */
+	{}
+};
+
+/*
+ * ixgbe_dump - Print registers, tx-rings and rx-rings
+ */
+static void ixgbe_dump(struct ixgbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_reg_info *reginfo;
+	int n = 0;
+	struct ixgbe_ring *tx_ring;
+	struct ixgbe_tx_buffer *tx_buffer_info;
+	union ixgbe_adv_tx_desc *tx_desc;
+	struct my_u0 { u64 a; u64 b; } *u0;
+	struct ixgbe_ring *rx_ring;
+	union ixgbe_adv_rx_desc *rx_desc;
+	struct ixgbe_rx_buffer *rx_buffer_info;
+	u32 staterr;
+	int i = 0;
+
+	/* Print netdevice Info */
+	dev_err(&adapter->pdev->dev, "Net device Info\n");
+	if (netdev) {
+		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 & IXGBE_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 ixgbe_reg_info *)ixgbe_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];
+		tx_buffer_info =
+			&tx_ring->tx_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)tx_buffer_info->dma,
+			   tx_buffer_info->length,
+			   tx_buffer_info->next_to_watch,
+			   (u64)tx_buffer_info->time_stamp);
+	}
+
+	/* Print TX Rings */
+	if ((dump_flag & IXGBE_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  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
+	 *   +--------------------------------------------------------------+
+	 *   63       46 45    40 39 36 35 32 31   24 23 20 19              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  ] "
+			"[PlPOIdStDDt Ln] [bi->dma       ] "
+			"leng  ntw timestamp        bi->skb\n");
+
+		for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+			tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+			tx_buffer_info = &tx_ring->tx_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)tx_buffer_info->dma,
+				tx_buffer_info->length,
+				tx_buffer_info->next_to_watch,
+				(u64)tx_buffer_info->time_stamp,
+				tx_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 & IXGBE_DUMP_BUFFERS) &&
+				tx_buffer_info->dma != 0)
+				print_hex_dump(KERN_ERR, "",
+					DUMP_PREFIX_ADDRESS, 16, 1,
+					phys_to_virt(tx_buffer_info->dma),
+					tx_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 & IXGBE_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 16 15   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++) {
+			rx_buffer_info = &rx_ring->rx_buffer_info[i];
+			rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+			u0 = (struct my_u0 *)rx_desc;
+			staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+			if (staterr & IXGBE_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),
+					rx_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)rx_buffer_info->dma,
+					rx_buffer_info->skb);
+
+				if (dump_flag & IXGBE_DUMP_BUFFERS) {
+					print_hex_dump(KERN_ERR, "",
+					   DUMP_PREFIX_ADDRESS, 16, 1,
+					   phys_to_virt(rx_buffer_info->dma),
+					   rx_ring->rx_buf_len, true);
+
+					if (rx_ring->rx_buf_len
+						< IXGBE_RXBUFFER_2048)
+						print_hex_dump(KERN_ERR, "",
+						  DUMP_PREFIX_ADDRESS, 16, 1,
+						  phys_to_virt(
+						    rx_buffer_info->page_dma +
+						    rx_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;
+}
+
 static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
 {
 	u32 ctrl_ext;
@@ -3306,6 +3598,7 @@ static void ixgbe_reset_task(struct work

 	adapter->tx_timeout_count++;

+	ixgbe_dump(adapter);
 	ixgbe_reinit_locked(adapter);
 }

Index: net-next-2.6/drivers/net/ixgbe/ixgbe_type.h
===================================================================
--- net-next-2.6.orig/drivers/net/ixgbe/ixgbe_type.h
+++ net-next-2.6/drivers/net/ixgbe/ixgbe_type.h
@@ -2568,4 +2568,33 @@ struct ixgbe_info {
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF

+
+struct ixgbe_reg_info {
+	u32 reg;
+	char *name;
+	u32 (*get_regofs)(int);
+	void (*dump_reg)(struct ixgbe_hw *, u32, char *, u32 (*)(int));
+};
+
+#define IXGBE_GET_REGOFS_FUNC(name)				\
+static inline u32 get_regofs_##name(int n)			\
+{								\
+	return IXGBE_##name(n);					\
+}								\
+
+IXGBE_GET_REGOFS_FUNC(SRRCTL)
+IXGBE_GET_REGOFS_FUNC(DCA_RXCTRL)
+IXGBE_GET_REGOFS_FUNC(RDLEN)
+IXGBE_GET_REGOFS_FUNC(RDH)
+IXGBE_GET_REGOFS_FUNC(RDT)
+IXGBE_GET_REGOFS_FUNC(RXDCTL)
+IXGBE_GET_REGOFS_FUNC(RDBAL)
+IXGBE_GET_REGOFS_FUNC(RDBAH)
+IXGBE_GET_REGOFS_FUNC(TDBAL)
+IXGBE_GET_REGOFS_FUNC(TDBAH)
+IXGBE_GET_REGOFS_FUNC(TDLEN)
+IXGBE_GET_REGOFS_FUNC(TDH)
+IXGBE_GET_REGOFS_FUNC(TDT)
+IXGBE_GET_REGOFS_FUNC(TXDCTL)
+
 #endif /* _IXGBE_TYPE_H_ */


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  2010-01-22  5:45 [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters Taku Izumi
                   ` (2 preceding siblings ...)
  2010-01-22  5:50 ` [PATCH v2 3/3] ixgbe: " Taku Izumi
@ 2010-01-22  6:25 ` Joe Perches
  2010-01-22  8:46   ` Taku Izumi
  2010-01-22 21:54 ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Brandeburg, Jesse
  4 siblings, 1 reply; 20+ messages in thread
From: Joe Perches @ 2010-01-22  6:25 UTC (permalink / raw)
  To: Taku Izumi
  Cc: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg,
	John Ronciak, Kirsher, Jeffrey T, PJ Waskiewicz, Koki Sanagi,
	Kenji Kaneshige, chavey

Trivial:

All of the printks without KERN_<level> should be KERN_CONT

For example:

> +	printk(KERN_ERR "%-15s ", rname);
> +	for (n = 0; n < 2; n++)
> +		printk("%08x ", __er32(hw, get_regofs(n)));
> +	printk("\n");

This should be:

	printk(KERN_ERR etc...)
	for (n = 0...)
		printk(KERN_CONT "%08x ", etc...
	printk(KERN_CONT "\n")

or perhaps written without the for loop

	printk(KERN_ERR "%-15s %08x %08x\n",
	       name, __er32(hw, get_regofs(0)), __er32(hw, get_regofs(1)));


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  2010-01-22  6:25 ` [PATCH v2 0/3] e1000e,igb,ixgbe: " Joe Perches
@ 2010-01-22  8:46   ` Taku Izumi
  0 siblings, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  8:46 UTC (permalink / raw)
  To: Joe Perches
  Cc: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg,
	John Ronciak, Kirsher, Jeffrey T, PJ Waskiewicz, Koki Sanagi,
	Kenji Kaneshige, chavey


(2010/01/22 15:25), Joe Perches wrote:
> Trivial:
> 
> All of the printks without KERN_<level>  should be KERN_CONT
> 
> For example:
> 
>> +	printk(KERN_ERR "%-15s ", rname);
>> +	for (n = 0; n<  2; n++)
>> +		printk("%08x ", __er32(hw, get_regofs(n)));
>> +	printk("\n");
> 
> This should be:
> 
> 	printk(KERN_ERR etc...)
> 	for (n = 0...)
> 		printk(KERN_CONT "%08x ", etc...
> 	printk(KERN_CONT "\n")
> 
> or perhaps written without the for loop
> 
> 	printk(KERN_ERR "%-15s %08x %08x\n",
> 	       name, __er32(hw, get_regofs(0)), __er32(hw, get_regofs(1)));
> 

Thank you for good information! I didn't realize that.
I'll rewrite all.

Best regards,
Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/3] e1000e: add registers etc. printout code just before resetting adapters
  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
  1 sibling, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  8:48 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey, joe


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/e1000e/hw.h     |   27 +++
 drivers/net/e1000e/netdev.c |  341 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 368 insertions(+)
Index: net-next-2.6/drivers/net/e1000e/netdev.c
===================================================================
--- net-next-2.6.orig/drivers/net/e1000e/netdev.c
+++ net-next-2.6/drivers/net/e1000e/netdev.c
@@ -52,6 +52,14 @@
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;

+static unsigned int dump_flag = 1;
+module_param(dump_flag, uint, 0644);
+MODULE_PARM_DESC(dump_flag, "Dump Flag");
+#define E1000_DUMP_REGS		(1 << 0)
+#define E1000_DUMP_TX_RINGS	(1 << 1)
+#define E1000_DUMP_RX_RINGS	(1 << 2)
+#define E1000_DUMP_BUFFERS	(1 << 3)
+
 static const struct e1000_info *e1000_info_tbl[] = {
 	[board_82571]		= &e1000_82571_info,
 	[board_82572]		= &e1000_82572_info,
@@ -65,6 +73,338 @@ static const struct e1000_info *e1000_in
 	[board_pchlan]		= &e1000_pch_info,
 };

+/*
+ * e1000_regdump - register printout routine
+ */
+static void e1000_regdump(struct e1000_hw *hw, u32 reg,
+			  char *name, u32 (*get_regofs)(int))
+{
+	printk(KERN_ERR "%-15s %08x\n", name, __er32(hw, reg));
+}
+
+/*
+ * e1000_regdump_n - register printout routine
+ */
+static void e1000_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-1]");
+	printk(KERN_ERR "%-15s ", rname);
+	for (n = 0; n < 2; n++)
+		printk(KERN_CONT "%08x ", __er32(hw, get_regofs(n)));
+	printk(KERN_CONT "\n");
+}
+
+static const struct e1000_reg_info e1000_reg_info_tbl[] = {
+
+	/* General Registers */
+	{E1000_CTRL, "CTRL", NULL, e1000_regdump},
+	{E1000_STATUS, "STATUS", NULL, e1000_regdump},
+	{E1000_CTRL_EXT, "CTRL_EXT", NULL, e1000_regdump},
+
+	/* Interrupt Registers */
+	{E1000_ICR, "ICR", NULL, e1000_regdump},
+
+	/* RX Registers */
+	{E1000_RCTL, "RCTL", NULL, e1000_regdump},
+	{E1000_RDLEN, "RDLEN", NULL, e1000_regdump},
+	{E1000_RDH, "RDH", NULL, e1000_regdump},
+	{E1000_RDT, "RDT", NULL, e1000_regdump},
+	{E1000_RDTR, "RDTR", NULL, e1000_regdump},
+	{E1000_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, e1000_regdump_n},
+	{E1000_ERT, "ERT", NULL, e1000_regdump},
+	{E1000_RDBAL, "RDBAL", NULL, e1000_regdump},
+	{E1000_RDBAH, "RDBAH", NULL, e1000_regdump},
+	{E1000_RDFH, "RDFH", NULL, e1000_regdump},
+	{E1000_RDFT, "RDFT", NULL, e1000_regdump},
+	{E1000_RDFHS, "RDFHS", NULL, e1000_regdump},
+	{E1000_RDFTS, "RDFTS", NULL, e1000_regdump},
+	{E1000_RDFPC, "RDFPC", NULL, e1000_regdump},
+
+	/* TX Registers */
+	{E1000_TCTL, "TCTL", NULL, e1000_regdump},
+	{E1000_TDBAL, "TDBAL", NULL, e1000_regdump},
+	{E1000_TDBAH, "TDBAH", NULL, e1000_regdump},
+	{E1000_TDLEN, "TDLEN", NULL, e1000_regdump},
+	{E1000_TDH, "TDH", NULL, e1000_regdump},
+	{E1000_TDT, "TDT", NULL, e1000_regdump},
+	{E1000_TIDV, "TIDV", NULL, e1000_regdump},
+	{E1000_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, e1000_regdump_n},
+	{E1000_TADV, "TADV", NULL, e1000_regdump},
+	{E1000_TARC(0), "TARC", get_regofs_TARC, e1000_regdump_n},
+	{E1000_TDFH, "TDFH", NULL, e1000_regdump},
+	{E1000_TDFT, "TDFT", NULL, e1000_regdump},
+	{E1000_TDFHS, "TDFHS", NULL, e1000_regdump},
+	{E1000_TDFTS, "TDFTS", NULL, e1000_regdump},
+	{E1000_TDFPC, "TDFPC", NULL, e1000_regdump},
+
+	/* List Terminator */
+	{}
+};
+
+/*
+ * e1000e_dump - Print registers, tx-ring and rx-ring
+ */
+static void e1000e_dump(struct e1000_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct e1000_hw *hw = &adapter->hw;
+	struct e1000_reg_info *reginfo;
+	struct e1000_ring *tx_ring = adapter->tx_ring;
+	struct e1000_tx_desc *tx_desc;
+	struct my_u0 { u64 a; u64 b; } *u0;
+	struct e1000_buffer *buffer_info;
+	struct e1000_ring *rx_ring = adapter->rx_ring;
+	union e1000_rx_desc_packet_split *rx_desc_ps;
+	struct e1000_rx_desc *rx_desc;
+	struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1;
+	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 & E1000_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 e1000_reg_info *)e1000_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");
+	buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
+	printk(KERN_ERR " %5d %5X %5X %016llX %04X %3X %016llX\n",
+		0, 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 & E1000_DUMP_TX_RINGS) == 0)
+		goto rx_ring_summary;
+
+	dev_err(&adapter->pdev->dev, "TX Rings Dump\n");
+
+	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
+	 *
+	 * Legacy Transmit Descriptor
+	 *   +--------------------------------------------------------------+
+	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
+	 *   +--------------------------------------------------------------+
+	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
+	 *   +--------------------------------------------------------------+
+	 *   63       48 47        36 35    32 31     24 23    16 15        0
+	 *
+	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
+	 *   63      48 47    40 39       32 31             16 15    8 7      0
+	 *   +----------------------------------------------------------------+
+	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
+	 *   +----------------------------------------------------------------+
+	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
+	 *   +----------------------------------------------------------------+
+	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
+	 *
+	 * Extended Data Descriptor (DTYP=0x1)
+	 *   +----------------------------------------------------------------+
+	 * 0 |                     Buffer Address [63:0]                      |
+	 *   +----------------------------------------------------------------+
+	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
+	 *   +----------------------------------------------------------------+
+	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
+	 */
+	printk(KERN_ERR "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Legacy format\n");
+	printk(KERN_ERR "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Ext Context format\n");
+	printk(KERN_ERR "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
+		" [bi->dma       ] leng  ntw timestamp        bi->skb "
+		"<-- Ext Data format\n");
+	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+		tx_desc = E1000_TX_DESC(*tx_ring, i);
+		buffer_info = &tx_ring->buffer_info[i];
+		u0 = (struct my_u0 *)tx_desc;
+		printk(KERN_ERR "T%c[0x%03X]    %016llX %016llX %016llX "
+			"%04X  %3X %016llX %p",
+		       (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
+			((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), 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(KERN_CONT " NTC/U\n");
+		else if (i == tx_ring->next_to_use)
+			printk(KERN_CONT " NTU\n");
+		else if (i == tx_ring->next_to_clean)
+			printk(KERN_CONT " NTC\n");
+		else
+			printk(KERN_CONT "\n");
+
+		if ((dump_flag & E1000_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");
+	printk(KERN_ERR " %5d %5X %5X\n", 0,
+		rx_ring->next_to_use, rx_ring->next_to_clean);
+
+	/* Print RX Rings */
+	if ((dump_flag & E1000_DUMP_RX_RINGS) == 0)
+		goto exit;
+
+	dev_err(&adapter->pdev->dev, "RX Rings Dump\n");
+	switch (adapter->rx_ps_pages) {
+	case 1:
+	case 2:
+	case 3:
+		/* [Extended] Packet Split Receive Descriptor Format
+		 *
+		 *    +-----------------------------------------------------+
+		 *  0 |                Buffer Address 0 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 *  8 |                Buffer Address 1 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 16 |                Buffer Address 2 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 24 |                Buffer Address 3 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 */
+		printk(KERN_ERR "R  [desc]      [buffer 0 63:0 ] "
+			"[buffer 1 63:0 ] "
+		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
+		       "[bi->skb] <-- Ext Pkt Split format\n");
+		/* [Extended] Receive Descriptor (Write-Back) Format
+		 *
+		 *   63       48 47    32 31     13 12    8 7    4 3        0
+		 *   +------------------------------------------------------+
+		 * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
+		 *   | Checksum | Ident  |         | Queue |      |  Type   |
+		 *   +------------------------------------------------------+
+		 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+		 *   +------------------------------------------------------+
+		 *   63       48 47    32 31            20 19               0
+		 */
+		printk(KERN_ERR "RWB[desc]      [ck ipid mrqhsh] "
+			"[vl   l0 ee  es] "
+		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
+		       "[bi->skb] <-- Ext Rx Write-Back format\n");
+		for (i = 0; i < rx_ring->count; i++) {
+			buffer_info = &rx_ring->buffer_info[i];
+			rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
+			u1 = (struct my_u1 *)rx_desc_ps;
+			staterr =
+				le32_to_cpu(rx_desc_ps->wb.middle.status_error);
+			if (staterr & E1000_RXD_STAT_DD) {
+				/* Descriptor Done */
+				printk(KERN_ERR "RWB[0x%03X]     %016llX "
+					"%016llX %016llX %016llX "
+					"---------------- %p", i,
+					le64_to_cpu(u1->a),
+					le64_to_cpu(u1->b),
+					le64_to_cpu(u1->c),
+					le64_to_cpu(u1->d),
+					buffer_info->skb);
+			} else {
+				printk(KERN_ERR "R  [0x%03X]     %016llX "
+					"%016llX %016llX %016llX %016llX %p", i,
+					le64_to_cpu(u1->a),
+					le64_to_cpu(u1->b),
+					le64_to_cpu(u1->c),
+					le64_to_cpu(u1->d),
+					(u64)buffer_info->dma,
+					buffer_info->skb);
+
+				if (dump_flag & E1000_DUMP_BUFFERS)
+					print_hex_dump(KERN_ERR, "",
+						DUMP_PREFIX_ADDRESS, 16, 1,
+						phys_to_virt(buffer_info->dma),
+						adapter->rx_ps_bsize0, true);
+			}
+
+			if (i == rx_ring->next_to_use)
+				printk(KERN_CONT " NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\n");
+		}
+		break;
+	default:
+	case 0:
+		/* Legacy Receive Descriptor Format
+		 *
+		 * +-----------------------------------------------------+
+		 * |                Buffer Address [63:0]                |
+		 * +-----------------------------------------------------+
+		 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
+		 * +-----------------------------------------------------+
+		 * 63       48 47    40 39      32 31         16 15      0
+		 */
+		printk(KERN_ERR "Rl[desc]     [address 63:0  ] "
+			"[vl er S cks ln] [bi->dma       ] [bi->skb] "
+			"<-- Legacy format\n");
+		for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
+			rx_desc = E1000_RX_DESC(*rx_ring, i);
+			buffer_info = &rx_ring->buffer_info[i];
+			u0 = (struct my_u0 *)rx_desc;
+			printk(KERN_ERR "Rl[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 (i == rx_ring->next_to_use)
+				printk(KERN_CONT " NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\n");
+
+			if (dump_flag & E1000_DUMP_BUFFERS)
+				print_hex_dump(KERN_ERR, "",
+					DUMP_PREFIX_ADDRESS,
+					16, 1, phys_to_virt(buffer_info->dma),
+					adapter->rx_buffer_len, true);
+		}
+	}
+
+exit:
+	return;
+}
+
 /**
  * e1000_desc_unused - calculate if we have unused descriptors
  **/
@@ -4247,6 +4587,7 @@ static void e1000_reset_task(struct work
 	struct e1000_adapter *adapter;
 	adapter = container_of(work, struct e1000_adapter, reset_task);

+	e1000e_dump(adapter);
 	e1000e_reinit_locked(adapter);
 }

Index: net-next-2.6/drivers/net/e1000e/hw.h
===================================================================
--- net-next-2.6.orig/drivers/net/e1000e/hw.h
+++ net-next-2.6/drivers/net/e1000e/hw.h
@@ -92,6 +92,11 @@ enum e1e_registers {
 	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
 	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
 	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
+	E1000_RDFH     = 0x02410, /* Rx Data FIFO Head - RW */
+	E1000_RDFT     = 0x02418, /* Rx Data FIFO Tail - RW */
+	E1000_RDFHS    = 0x02420, /* Rx Data FIFO Head Saved - RW */
+	E1000_RDFTS    = 0x02428, /* Rx Data FIFO Tail Saved - RW */
+	E1000_RDFPC    = 0x02430, /* Rx Data FIFO Packet Count - RW */
 	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
 	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
 	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
@@ -101,6 +106,11 @@ enum e1e_registers {
 	E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
 #define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
 	E1000_RADV     = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
+	E1000_TDFH     = 0x03410, /* Tx Data FIFO Head - RW */
+	E1000_TDFT     = 0x03418, /* Tx Data FIFO Tail - RW */
+	E1000_TDFHS    = 0x03420, /* Tx Data FIFO Head Saved - RW */
+	E1000_TDFTS    = 0x03428, /* Tx Data FIFO Tail Saved - RW */
+	E1000_TDFPC    = 0x03430, /* Tx Data FIFO Packet Count - RW */

 /* Convenience macros
  *
@@ -219,6 +229,23 @@ enum e1e_registers {
 	E1000_HICR      = 0x08F00, /* Host Interface Control */
 };

+struct e1000_reg_info {
+	u32 reg;
+	char *name;
+	u32 (*get_regofs)(int);
+	void (*dump_reg)(struct e1000_hw *, u32, char *, u32 (*)(int));
+};
+
+#define E1000_GET_REGOFS_FUNC(name)				\
+static inline u32 get_regofs_##name(int n)			\
+{								\
+	return E1000_##name(n);					\
+}								\
+
+E1000_GET_REGOFS_FUNC(RXDCTL)
+E1000_GET_REGOFS_FUNC(TXDCTL)
+E1000_GET_REGOFS_FUNC(TARC)
+
 #define E1000_MAX_PHY_ADDR		4

 /* IGP01E1000 Specific Registers */



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 2/3] igb: add registers etc. printout code just before resetting adapters
  2010-01-22  5:49 ` [PATCH v2 2/3] igb: " Taku Izumi
@ 2010-01-22  8:49   ` Taku Izumi
  0 siblings, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  8:49 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey, joe


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(KERN_CONT "%08x ", rd32(get_regofs(n)));
+	printk(KERN_CONT "\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(KERN_CONT " NTC/U\n");
+			else if (i == tx_ring->next_to_use)
+				printk(KERN_CONT " NTU\n");
+			else if (i == tx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\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(KERN_CONT " NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\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...) \



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/3] ixgbe: add registers etc. printout code just before resetting adapters
  2010-01-22  5:50 ` [PATCH v2 3/3] ixgbe: " Taku Izumi
@ 2010-01-22  8:50   ` Taku Izumi
  0 siblings, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-01-22  8:50 UTC (permalink / raw)
  To: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg, John Ronciak
  Cc: Koki Sanagi, Kenji Kaneshige, chavey, joe


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/ixgbe/ixgbe_main.c |  294 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_type.h |   29 ++++
 2 files changed, 323 insertions(+)

Index: net-next-2.6/drivers/net/ixgbe/ixgbe_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/ixgbe/ixgbe_main.c
+++ net-next-2.6/drivers/net/ixgbe/ixgbe_main.c
@@ -60,6 +60,15 @@ static const struct ixgbe_info *ixgbe_in
 	[board_82599] = &ixgbe_82599_info,
 };

+
+static unsigned int dump_flag = 1;
+module_param(dump_flag, uint, 0644);
+MODULE_PARM_DESC(dump_flag, "Dump Flag");
+#define IXGBE_DUMP_REGS		(1 << 0)
+#define IXGBE_DUMP_TX_RINGS	(1 << 1)
+#define IXGBE_DUMP_RX_RINGS	(1 << 2)
+#define IXGBE_DUMP_BUFFERS	(1 << 3)
+
 /* ixgbe_pci_tbl - PCI Device ID Table
  *
  * Wildcard entries (PCI_ANY_ID) should come last
@@ -174,6 +183,290 @@ static inline void ixgbe_disable_sriov(s
 	adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
 }

+/*
+ * ixgbe_regdump - register printout routine
+ */
+static void ixgbe_regdump(struct ixgbe_hw *hw, u32 reg,
+			  char *name, u32 (*get_regofs)(int))
+{
+	printk(KERN_ERR "%-15s %08x\n", name, IXGBE_READ_REG(hw, reg));
+}
+
+/*
+ * ixgbe_regdump_n - register printout routine
+ */
+static void ixgbe_regdump_n(struct ixgbe_hw *hw, u32 reg,
+			    char *name, u32 (*get_regofs)(int))
+{
+	int i = 0, j = 0;
+	char rname[16];
+
+	if (!get_regofs)
+		return;
+
+	for (i = 0; i < 8; i++) {
+		snprintf(rname, 16, "%s[%d-%d]", name, i*8, i*8+7);
+		printk(KERN_ERR "%-15s ", rname);
+		for (j = 0; j < 8; j++)
+			printk(KERN_CONT "%08x ",
+				IXGBE_READ_REG(hw, get_regofs(i*8+j)));
+		printk(KERN_CONT "\n");
+	}
+}
+
+static const struct ixgbe_reg_info ixgbe_reg_info_tbl[] = {
+
+	/* General Registers */
+	{IXGBE_CTRL, "CTRL", NULL, ixgbe_regdump},
+	{IXGBE_STATUS, "STATUS", NULL, ixgbe_regdump},
+	{IXGBE_CTRL_EXT, "CTRL_EXT", NULL, ixgbe_regdump},
+
+	/* Interrupt Registers */
+	{IXGBE_EICR, "EICR", NULL, ixgbe_regdump},
+
+	/* RX Registers */
+	{IXGBE_SRRCTL(0), "SRRCTL", get_regofs_SRRCTL, ixgbe_regdump_n},
+	{IXGBE_DCA_RXCTRL(0), "DRXCTL", get_regofs_DCA_RXCTRL, ixgbe_regdump_n},
+	{IXGBE_RDLEN(0), "RDLEN", get_regofs_RDLEN, ixgbe_regdump_n},
+	{IXGBE_RDH(0), "RDH", get_regofs_RDH, ixgbe_regdump_n},
+	{IXGBE_RDT(0), "RDT", get_regofs_RDT, ixgbe_regdump_n},
+	{IXGBE_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, ixgbe_regdump_n},
+	{IXGBE_RDBAL(0), "RDBAL", get_regofs_RDBAL, ixgbe_regdump_n},
+	{IXGBE_RDBAH(0), "RDBAH", get_regofs_RDBAH, ixgbe_regdump_n},
+
+	/* TX Registers */
+	{IXGBE_TDBAL(0), "TDBAL", get_regofs_TDBAL, ixgbe_regdump_n},
+	{IXGBE_TDBAH(0), "TDBAH", get_regofs_TDBAH, ixgbe_regdump_n},
+	{IXGBE_TDLEN(0), "TDLEN", get_regofs_TDLEN, ixgbe_regdump_n},
+	{IXGBE_TDH(0), "TDH", get_regofs_TDH, ixgbe_regdump_n},
+	{IXGBE_TDT(0), "TDT", get_regofs_TDT, ixgbe_regdump_n},
+	{IXGBE_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, ixgbe_regdump_n},
+
+	/* List Terminator */
+	{}
+};
+
+/*
+ * ixgbe_dump - Print registers, tx-rings and rx-rings
+ */
+static void ixgbe_dump(struct ixgbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_reg_info *reginfo;
+	int n = 0;
+	struct ixgbe_ring *tx_ring;
+	struct ixgbe_tx_buffer *tx_buffer_info;
+	union ixgbe_adv_tx_desc *tx_desc;
+	struct my_u0 { u64 a; u64 b; } *u0;
+	struct ixgbe_ring *rx_ring;
+	union ixgbe_adv_rx_desc *rx_desc;
+	struct ixgbe_rx_buffer *rx_buffer_info;
+	u32 staterr;
+	int i = 0;
+
+	/* Print netdevice Info */
+	dev_err(&adapter->pdev->dev, "Net device Info\n");
+	if (netdev) {
+		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 & IXGBE_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 ixgbe_reg_info *)ixgbe_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];
+		tx_buffer_info =
+			&tx_ring->tx_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)tx_buffer_info->dma,
+			   tx_buffer_info->length,
+			   tx_buffer_info->next_to_watch,
+			   (u64)tx_buffer_info->time_stamp);
+	}
+
+	/* Print TX Rings */
+	if ((dump_flag & IXGBE_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  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
+	 *   +--------------------------------------------------------------+
+	 *   63       46 45    40 39 36 35 32 31   24 23 20 19              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  ] "
+			"[PlPOIdStDDt Ln] [bi->dma       ] "
+			"leng  ntw timestamp        bi->skb\n");
+
+		for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+			tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+			tx_buffer_info = &tx_ring->tx_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)tx_buffer_info->dma,
+				tx_buffer_info->length,
+				tx_buffer_info->next_to_watch,
+				(u64)tx_buffer_info->time_stamp,
+				tx_buffer_info->skb);
+			if (i == tx_ring->next_to_use &&
+				i == tx_ring->next_to_clean)
+				printk(KERN_CONT " NTC/U\n");
+			else if (i == tx_ring->next_to_use)
+				printk(KERN_CONT " NTU\n");
+			else if (i == tx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\n");
+
+			if ((dump_flag & IXGBE_DUMP_BUFFERS) &&
+				tx_buffer_info->dma != 0)
+				print_hex_dump(KERN_ERR, "",
+					DUMP_PREFIX_ADDRESS, 16, 1,
+					phys_to_virt(tx_buffer_info->dma),
+					tx_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 & IXGBE_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 16 15   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++) {
+			rx_buffer_info = &rx_ring->rx_buffer_info[i];
+			rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+			u0 = (struct my_u0 *)rx_desc;
+			staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+			if (staterr & IXGBE_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),
+					rx_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)rx_buffer_info->dma,
+					rx_buffer_info->skb);
+
+				if (dump_flag & IXGBE_DUMP_BUFFERS) {
+					print_hex_dump(KERN_ERR, "",
+					   DUMP_PREFIX_ADDRESS, 16, 1,
+					   phys_to_virt(rx_buffer_info->dma),
+					   rx_ring->rx_buf_len, true);
+
+					if (rx_ring->rx_buf_len
+						< IXGBE_RXBUFFER_2048)
+						print_hex_dump(KERN_ERR, "",
+						  DUMP_PREFIX_ADDRESS, 16, 1,
+						  phys_to_virt(
+						    rx_buffer_info->page_dma +
+						    rx_buffer_info->page_offset
+						  ),
+						  PAGE_SIZE/2, true);
+				}
+			}
+
+			if (i == rx_ring->next_to_use)
+				printk(KERN_CONT " NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(KERN_CONT " NTC\n");
+			else
+				printk(KERN_CONT "\n");
+
+		}
+	}
+
+exit:
+	return;
+}
+
 static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
 {
 	u32 ctrl_ext;
@@ -3306,6 +3599,7 @@ static void ixgbe_reset_task(struct work

 	adapter->tx_timeout_count++;

+	ixgbe_dump(adapter);
 	ixgbe_reinit_locked(adapter);
 }

Index: net-next-2.6/drivers/net/ixgbe/ixgbe_type.h
===================================================================
--- net-next-2.6.orig/drivers/net/ixgbe/ixgbe_type.h
+++ net-next-2.6/drivers/net/ixgbe/ixgbe_type.h
@@ -2568,4 +2568,33 @@ struct ixgbe_info {
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF

+
+struct ixgbe_reg_info {
+	u32 reg;
+	char *name;
+	u32 (*get_regofs)(int);
+	void (*dump_reg)(struct ixgbe_hw *, u32, char *, u32 (*)(int));
+};
+
+#define IXGBE_GET_REGOFS_FUNC(name)				\
+static inline u32 get_regofs_##name(int n)			\
+{								\
+	return IXGBE_##name(n);					\
+}								\
+
+IXGBE_GET_REGOFS_FUNC(SRRCTL)
+IXGBE_GET_REGOFS_FUNC(DCA_RXCTRL)
+IXGBE_GET_REGOFS_FUNC(RDLEN)
+IXGBE_GET_REGOFS_FUNC(RDH)
+IXGBE_GET_REGOFS_FUNC(RDT)
+IXGBE_GET_REGOFS_FUNC(RXDCTL)
+IXGBE_GET_REGOFS_FUNC(RDBAL)
+IXGBE_GET_REGOFS_FUNC(RDBAH)
+IXGBE_GET_REGOFS_FUNC(TDBAL)
+IXGBE_GET_REGOFS_FUNC(TDBAH)
+IXGBE_GET_REGOFS_FUNC(TDLEN)
+IXGBE_GET_REGOFS_FUNC(TDH)
+IXGBE_GET_REGOFS_FUNC(TDT)
+IXGBE_GET_REGOFS_FUNC(TXDCTL)
+
 #endif /* _IXGBE_TYPE_H_ */



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e, igb, ixgbe: add registers etc. printout code just before resetting adapters
  2010-01-22  5:45 [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters Taku Izumi
                   ` (3 preceding siblings ...)
  2010-01-22  6:25 ` [PATCH v2 0/3] e1000e,igb,ixgbe: " Joe Perches
@ 2010-01-22 21:54 ` Brandeburg, Jesse
  2010-01-26 10:21   ` [PATCH v2 0/3] e1000e,igb,ixgbe: " Taku Izumi
  4 siblings, 1 reply; 20+ messages in thread
From: Brandeburg, Jesse @ 2010-01-22 21:54 UTC (permalink / raw)
  To: Taku Izumi
  Cc: Koki Sanagi, e1000-devel, netdev, Allan, Bruce W, chavey,
	Ronciak, John, Kirsher, Jeffrey T, Kenji Kaneshige,
	David S. Miller

On Thu, 21 Jan 2010, Taku Izumi wrote:
> This patchset is the update version of "register etc. printout code" patch. (sorry
> for late reply)
> The old one is http://marc.info/?l=linux-netdev&m=126286127208276&w=2
> 
> v1 -> v2:
>  - replaced hexdump() with print_hex_dump()
>  - changed the register printout inplementation (for-switch-case -> data-driven-table)
> 
> However the default value of "dump_flag" is not changed (still 1).
> The reason I didn't change is
>  - I think HW index (TDH,TDT..) and SW index (NTC,NTU) are at least necessary
>  - the amount of default output is not so large (see bellow)
>  - the adapter resetting problem doesn't happen frequently

Taku, thanks for these, we are talking the patches over and reviewing 
them.  While I agree with the idea of these patches is good, I still don't 
agree with the default being enabled.  Usually if someone is getting tx 
hangs they are repeatable and we can work with them to get the debug 
turned on.  I DO think it is useful to have the feature available by 
default but NOT enabled.

If we wanted to enable something by default it might be useful to print 
something that actually draws some conclusions from known failure modes, 
like if TDH!=TDT after some amount of time.  I think one or two lines 
maximum for default printing.

If you're working in this area I had an idea.  I had wanted to be able to 
print the large amount of ring information (especially in the ixgbe case 
with many rings) to the ftrace buffers in order to not overrun the syslog 
daemon.  Not sure if you're interested in more new features, it certainly 
is separate but related to this patch. 

------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  2010-01-22 21:54 ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Brandeburg, Jesse
@ 2010-01-26 10:21   ` Taku Izumi
  2010-02-17 19:10     ` Brandeburg, Jesse
  0 siblings, 1 reply; 20+ messages in thread
From: Taku Izumi @ 2010-01-26 10:21 UTC (permalink / raw)
  To: Brandeburg, Jesse
  Cc: netdev, Allan, Bruce W, David S. Miller, Ronciak, John, Kirsher,
	Jeffrey T, Waskiewicz Jr, Peter P, Koki Sanagi, Kenji Kaneshige,
	chavey, e1000-devel

Hi Jesse,

(2010/01/23 6:54), Brandeburg, Jesse wrote:
> Taku, thanks for these, we are talking the patches over and reviewing
> them.  While I agree with the idea of these patches is good, I still don't
> agree with the default being enabled.  Usually if someone is getting tx
> hangs they are repeatable and we can work with them to get the debug
> turned on.  I DO think it is useful to have the feature available by
> default but NOT enabled.
> 
> If we wanted to enable something by default it might be useful to print
> something that actually draws some conclusions from known failure modes,
> like if TDH!=TDT after some amount of time.  I think one or two lines
> maximum for default printing.
> 
> If you're working in this area I had an idea.  I had wanted to be able to
> print the large amount of ring information (especially in the ixgbe case
> with many rings) to the ftrace buffers in order to not overrun the syslog
> daemon.  Not sure if you're interested in more new features, it certainly
> is separate but related to this patch.

I thought similar things, that is, all information should be dumped to
the private ring buffer to avoid filling syslog up with driver messages.
But I didn't have any good idea to extract information from ring buffers,
so as the first step, I decided to printout it by using printk().
Is there the easy way to extract it from ring buffers?

Best regards,
Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  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
                         ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Brandeburg, Jesse @ 2010-02-17 19:10 UTC (permalink / raw)
  To: Taku Izumi
  Cc: netdev, Allan, Bruce W, David S. Miller, Ronciak, John, Kirsher,
	Jeffrey T, Waskiewicz Jr, Peter P, Koki Sanagi, Kenji Kaneshige,
	chavey, e1000-devel


On Tue, 26 Jan 2010, Taku Izumi wrote:
> (2010/01/23 6:54), Brandeburg, Jesse wrote:
> > Taku, thanks for these, we are talking the patches over and reviewing
> > them.  While I agree with the idea of these patches is good, I still don't
> > agree with the default being enabled.  Usually if someone is getting tx
> > hangs they are repeatable and we can work with them to get the debug
> > turned on.  I DO think it is useful to have the feature available by
> > default but NOT enabled.
> > 
> > If we wanted to enable something by default it might be useful to print
> > something that actually draws some conclusions from known failure modes,
> > like if TDH!=TDT after some amount of time.  I think one or two lines
> > maximum for default printing.
> > 
> > If you're working in this area I had an idea.  I had wanted to be able to
> > print the large amount of ring information (especially in the ixgbe case
> > with many rings) to the ftrace buffers in order to not overrun the syslog
> > daemon.  Not sure if you're interested in more new features, it certainly
> > is separate but related to this patch.
> 
> I thought similar things, that is, all information should be dumped to
> the private ring buffer to avoid filling syslog up with driver messages.
> But I didn't have any good idea to extract information from ring buffers,
> so as the first step, I decided to printout it by using printk().
> Is there the easy way to extract it from ring buffers?

First, I need to apologize for the delay, it's my fault.

I'm not sure about an easy way to use the private ring buffers yet, I know 
you can use the ftrace buffers directly, and then when someone read 
/sys/kernel/debug/tracing/trace they would get all the output.

Lets not do ftrace yet.

I have a counter proposal to make, here is a (incomplete) patch that we 
use all the time to debug tx hangs.  This example is for e1000e.  We are 
trying to avoid changes with other users' copyright to some of the files 
in our drivers so that we can ship them under multiple license.  We would 
much prefer something like this to be used, can you review?

I also have another patch I made for ixgb to show the use of sysfs and a 
module parameter, I'll reply again with that next.

---
From: Jesse Brandeburg <jesse.brandeburg@intel.com>

e1000e: dump code for descriptor rings

This is debug code for descriptor ring dumps, only enable if you really want a
lot of stuff in your syslog/dmesg when you get NETDEV WATCHDOG or tx hang
reports from the driver.

<not implemented> Code can be enabled at boot time with a module parameter or
via sysfs at runtime.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---

 drivers/net/e1000e/ethtool.c |    4 +
 drivers/net/e1000e/hw.h      |   10 +
 drivers/net/e1000e/netdev.c  |  298 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 311 insertions(+), 1 deletions(-)


diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 0aa50c2..bbcf5c7 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -434,6 +434,8 @@ static int e1000_get_regs_len(struct net_device *netdev)
 	return E1000_REGS_LEN * sizeof(u32);
 }
 
+extern void e1000e_dump(struct e1000_adapter *);
+
 static void e1000_get_regs(struct net_device *netdev,
 			   struct ethtool_regs *regs, void *p)
 {
@@ -443,6 +445,8 @@ static void e1000_get_regs(struct net_device *netdev,
 	u16 phy_data;
 	u8 revision_id;
 
+	e1000e_dump(adapter);
+
 	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
 
 	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index eccf29b..d23501d 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -92,6 +92,11 @@ enum e1e_registers {
 	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
 	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
 	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
+	E1000_RDFH     = 0x02410, /* Rx Data FIFO Head - RW */
+	E1000_RDFT     = 0x02418, /* Rx Data FIFO Tail - RW */
+	E1000_RDFHS    = 0x02420, /* Rx Data FIFO Head Saved - RW */
+	E1000_RDFTS    = 0x02428, /* Rx Data FIFO Tail Saved - RW */
+	E1000_RDFPC    = 0x02430, /* Rx Data FIFO Packet Count - RW */
 	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
 	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
 	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
@@ -112,6 +117,11 @@ enum e1e_registers {
  */
 #define E1000_RDBAL_REG(_n)   (E1000_RDBAL + (_n << 8))
 	E1000_KABGTXD  = 0x03004, /* AFE Band Gap Transmit Ref Data */
+	E1000_TDFH     = 0x03410, /* TX Data FIFO Head - RW */
+	E1000_TDFT     = 0x03418, /* TX Data FIFO Tail - RW */
+	E1000_TDFHS    = 0x03420, /* TX Data FIFO Head Saved - RW */
+	E1000_TDFTS    = 0x03428, /* Tx Data FIFO Tail Saved - RW */
+	E1000_TDFPC    = 0x03430, /* TX Data FIFO Packet Count - RW */
 	E1000_TDBAL    = 0x03800, /* Tx Descriptor Base Address Low - RW */
 	E1000_TDBAH    = 0x03804, /* Tx Descriptor Base Address High - RW */
 	E1000_TDLEN    = 0x03808, /* Tx Descriptor Length - RW */
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index c45965a..c990341 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -48,7 +48,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "1.0.2-k2"
+#define DRV_VERSION "1.0.2-k4"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -601,6 +601,301 @@ static void e1000_print_hw_hang(struct work_struct *work)
 	      pci_status);
 }
 
+#if 0
+static void hexdump(dma_addr_t dma, u16 len)
+{
+	u16 offset, i;
+	char str[80], byte[4];
+	void *va = phys_to_virt((unsigned long)dma);
+
+	printk("buffer at %016llX (%d)\n", (u64)dma, len);
+	for (offset = 0; offset < len; offset += 16) {
+		sprintf(str, "%04x: ", offset);
+		for (i = 0; i < 16; i++) {
+			if ((offset + i) < len)
+				sprintf(byte, "%02x ",
+				        ((unsigned char *)va)[offset + i]);
+			else
+				strcpy(byte, "   ");
+			strcat(str, byte);
+		}
+		printk("%s\n", str);
+	}
+}
+
+#endif
+void e1000e_dump(struct e1000_adapter *adapter)
+{
+	/* this code doesn't handle multiple rings */
+	struct e1000_ring *tx_ring = adapter->tx_ring;
+	struct e1000_ring *rx_ring = adapter->rx_ring;
+	struct e1000_hw *hw = &adapter->hw;
+	int i = 0;
+#define NUM_REGS 38 /* 1 based count */
+	u32 regs[NUM_REGS];
+	u32 *regs_buff = regs;
+
+	char *reg_name[] = {
+	"CTRL",  "STATUS",
+	"RCTL", "RDLEN", "RDH", "RDT", "RDTR",
+	"TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
+	"TIDV", "TXDCTL", "TADV", "TARC0",
+	"TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1",
+	"TXDCTL1", "TARC1",
+	"CTRL_EXT", "ERT", "RDBAL", "RDBAH",
+	 "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC",
+	 "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC",
+	};
+
+	//if (!e1000e_debug_dump)
+		//return;
+
+	regs_buff[0]  = er32(CTRL);
+	regs_buff[1]  = er32(STATUS);
+
+	regs_buff[2]  = er32(RCTL);
+	regs_buff[3]  = er32(RDLEN);
+	regs_buff[4]  = er32(RDH);
+	regs_buff[5]  = er32(RDT);
+	regs_buff[6]  = er32(RDTR);
+
+	regs_buff[7]  = er32(TCTL);
+	regs_buff[8]  = er32(TDBAL);
+	regs_buff[9]  = er32(TDBAH);
+	regs_buff[10] = er32(TDLEN);
+	regs_buff[11] = er32(TDH);
+	regs_buff[12] = er32(TDT);
+	regs_buff[13] = er32(TIDV);
+	regs_buff[14] = er32(TXDCTL(0));
+	regs_buff[15] = er32(TADV);
+	regs_buff[16] = er32(TARC(0));
+
+	regs_buff[22] = er32(TXDCTL(1));
+	regs_buff[23] = er32(TARC(1));
+	regs_buff[24] = er32(CTRL_EXT);
+	regs_buff[25] = er32(ERT);
+	regs_buff[26] = er32(RDBAL);
+	regs_buff[27] = er32(RDBAH);
+	regs_buff[28] = er32(TDFH);
+	regs_buff[29] = er32(TDFT);
+	regs_buff[30] = er32(TDFHS);
+	regs_buff[31] = er32(TDFTS);
+	regs_buff[32] = er32(TDFPC);
+	regs_buff[33] = er32(RDFH);
+	regs_buff[34] = er32(RDFT);
+	regs_buff[35] = er32(RDFHS);
+	regs_buff[36] = er32(RDFTS);
+	regs_buff[37] = er32(RDFPC);
+
+	e_err("Register dump\n");
+	for (i = 0; i < NUM_REGS; i++) {
+		printk("%-15s  %08x\n",
+		reg_name[i], regs_buff[i]);
+	}
+
+	/*
+	 * transmit dump
+	 */
+	printk(KERN_ERR"TX Desc ring0 dump\n");
+
+	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
+	 *
+	 * Legacy Transmit Descriptor
+	 *   +--------------------------------------------------------------+
+	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
+	 *   +--------------------------------------------------------------+
+	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
+	 *   +--------------------------------------------------------------+
+	 *   63       48 47        36 35    32 31     24 23    16 15        0
+	 *
+	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
+	 *   63      48 47    40 39       32 31             16 15    8 7      0
+	 *   +----------------------------------------------------------------+
+	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
+	 *   +----------------------------------------------------------------+
+	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
+	 *   +----------------------------------------------------------------+
+	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
+	 *
+	 * Extended Data Descriptor (DTYP=0x1)
+	 *   +----------------------------------------------------------------+
+	 * 0 |                     Buffer Address [63:0]                      |
+	 *   +----------------------------------------------------------------+
+	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
+	 *   +----------------------------------------------------------------+
+	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
+	 */
+	printk("Tl(Legacy)   [address 63:0  ] [SpeCssSCmCsLen] [buffer_info dma"
+	       " leng  ntw       time_stamp             skb]\n");
+	printk("Tc(ExtCont)  [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [buffer_info dma"
+	       " leng  ntw       time_stamp             skb]\n");
+	printk("Td(ExtData)  [address 63:0  ] [VlaPoRSCm1Dlen] [buffer_info dma"
+	       " leng  ntw       time_stamp             skb]\n");
+	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
+		struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
+		struct my_u { u64 a; u64 b; };
+		struct my_u *u = (struct my_u *)tx_desc;
+		printk("T%c[0x%03X]    %016llX %016llX %016llX %04X  %3X "
+		       "%016llX %p",
+		       (!(le64_to_cpu(u->b) & (1<<29)) ? 'l' :
+		         ((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c')), i,
+		       le64_to_cpu(u->a), le64_to_cpu(u->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 0
+		if (adapter->dump_buffers && (buffer_info->dma != 0))
+			hexdump(buffer_info->dma, buffer_info->length);
+#endif
+	}
+
+	/*
+	 * receive dump
+	 */
+	printk(KERN_ERR"\nRX Desc ring dump\n");
+
+	switch (adapter->rx_ps_pages) {
+	case 1:
+	case 2:
+	case 3:
+		/* [Extended] Packet Split Receive Descriptor Format
+		 *
+		 *    +-----------------------------------------------------+
+		 *  0 |                Buffer Address 0 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 *  8 |                Buffer Address 1 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 16 |                Buffer Address 2 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 * 24 |                Buffer Address 3 [63:0]              |
+		 *    +-----------------------------------------------------+
+		 */
+		printk("R  [desc]      [buffer 0 63:0 ] [buffer 1 63:0 ] "
+		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
+		       "[bi->skb] <-- Ext Pkt Split format\n");
+		/* [Extended] Receive Descriptor (Write-Back) Format
+		 *
+		 *   63       48 47    32 31     13 12    8 7    4 3        0
+		 *   +------------------------------------------------------+
+		 * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
+		 *   | Checksum | Ident  |         | Queue |      |  Type   |
+		 *   +------------------------------------------------------+
+		 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+		 *   +------------------------------------------------------+
+		 *   63       48 47    32 31            20 19               0
+		 */
+		printk("RWB[desc]      [ck ipid mrqhsh] [vl   l0 ee  es] "
+		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
+		       "[bi->skb] <-- Ext Rx Write-Back format\n");
+		for (i = 0; i < rx_ring->count; i++) {
+			struct e1000_buffer *buffer_info =
+						&rx_ring->buffer_info[i];
+			union e1000_rx_desc_packet_split *rx_desc =
+						E1000_RX_DESC_PS(*rx_ring, i);
+			struct my_u { u64 a; u64 b; u64 c; u64 d; };
+			struct my_u *u = (struct my_u *)rx_desc;
+			u32 staterr;
+			staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+			if (staterr & E1000_RXD_STAT_DD) {
+				/* Descriptor Done */
+				printk("RWB[0x%03X]     %016llX %016llX %016llX"
+				       " %016llX ---------------- %p",
+				       i, le64_to_cpu(u->a), le64_to_cpu(u->b),
+				       le64_to_cpu(u->c), le64_to_cpu(u->d),
+				       buffer_info->skb);
+			} else {
+				printk("R  [0x%03X]     %016llX %016llX %016llX"
+				       " %016llX %016llX %p",
+				       i, le64_to_cpu(u->a), le64_to_cpu(u->b),
+				       le64_to_cpu(u->c), le64_to_cpu(u->d),
+				       (u64)buffer_info->dma, buffer_info->skb);
+
+#if 0
+				if (adapter->dump_buffers)
+					hexdump(buffer_info->dma,
+					        adapter->rx_ps_bsize0);
+#endif
+			}
+
+			if (i == rx_ring->next_to_use)
+				printk(" NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(" NTC\n");
+			else
+				printk("\n");
+		}
+		break;
+	default:
+	case 0:
+		/* Legacy Receive Descriptor Format
+		 *
+		 * +-----------------------------------------------------+
+		 * |                Buffer Address [63:0]                |
+		 * +-----------------------------------------------------+
+		 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
+		 * +-----------------------------------------------------+
+		 * 63       48 47    40 39      32 31         16 15      0
+		 */
+		printk("Rl[desc]     [address 63:0  ] [vl er S cks ln] "
+		       "[bi->dma       ] [bi->skb] <-- Legacy format\n");
+		for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
+			struct e1000_rx_desc *rx_desc =
+						E1000_RX_DESC(*rx_ring, i);
+			struct e1000_buffer *buffer_info =
+						&rx_ring->buffer_info[i];
+			struct my_u { u64 a; u64 b; };
+			struct my_u *u = (struct my_u *)rx_desc;
+			printk("Rl[0x%03X]    %016llX %016llX %016llX %p",
+				i, le64_to_cpu(u->a), le64_to_cpu(u->b),
+				(u64)buffer_info->dma, buffer_info->skb);
+			if (i == rx_ring->next_to_use)
+				printk(" NTU\n");
+			else if (i == rx_ring->next_to_clean)
+				printk(" NTC\n");
+			else
+				printk("\n");
+
+#if 0
+			if (adapter->dump_buffers)
+				hexdump(buffer_info->dma,
+				        adapter->rx_buffer_len);
+#endif
+		} /* for */
+	} /* switch */
+
+	/* dump the descriptor caches */
+	/* rx */
+	printk("Rx descriptor cache in 64bit format\n");
+	for (i = 0x6000; i <= 0x63FF ; i += 0x10) {
+		printk("R%04X: %08X|%08X %08X|%08X\n",
+				i,
+				readl(adapter->hw.hw_addr + i+4),
+				readl(adapter->hw.hw_addr + i),
+				readl(adapter->hw.hw_addr + i+12),
+				readl(adapter->hw.hw_addr + i+8));
+	}
+	/* tx */
+	printk("Tx descriptor cache in 64bit format\n");
+	for (i = 0x7000; i <= 0x73FF ; i += 0x10) {
+		printk("T%04X: %08X|%08X %08X|%08X\n",
+				i,
+				readl(adapter->hw.hw_addr + i+4),
+				readl(adapter->hw.hw_addr + i),
+				readl(adapter->hw.hw_addr + i+12),
+				readl(adapter->hw.hw_addr + i+8));
+	}
+}
+
 /**
  * e1000_clean_tx_irq - Reclaim resources after transmit completes
  * @adapter: board private structure
@@ -682,6 +977,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 			       + (adapter->tx_timeout_factor * HZ)) &&
 		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
 			schedule_work(&adapter->print_hang_task);
+			e1000e_dump(adapter);
 			netif_stop_queue(netdev);
 		}
 	}

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  2010-02-17 19:10     ` Brandeburg, Jesse
@ 2010-02-17 19:32       ` Brandeburg, Jesse
  2010-02-19  8:16       ` Taku Izumi
  2010-02-26  9:05       ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Taku Izumi
  2 siblings, 0 replies; 20+ messages in thread
From: Brandeburg, Jesse @ 2010-02-17 19:32 UTC (permalink / raw)
  To: Taku Izumi
  Cc: netdev, Allan, Bruce W, David S. Miller, Ronciak, John, Kirsher,
	Jeffrey T, Waskiewicz Jr, Peter P, Koki Sanagi, Kenji Kaneshige,
	chavey, e1000-devel



On Wed, 17 Feb 2010, Brandeburg, Jesse wrote:
> I also have another patch I made for ixgb to show the use of sysfs and a
> module parameter, I'll reply again with that next.

---

ixgb: debug dump patch

this patch helps us debug tx hangs and other issues by dumping
the transmit and receive descriptor rings in the host memory
upon a tx hang event.  debug code is enabled with
echo 1 > /sys/module/ixgb/parameters/debug_dump

and on the next tx hang you'll get a *massive* amount of data
dumped into the kernel log.  yeah debugfs would be perfect for this.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---

 drivers/net/ixgb/ixgb_ethtool.c |    6 ++
 drivers/net/ixgb/ixgb_hw.h      |   15 ++++
 drivers/net/ixgb/ixgb_main.c    |  140 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 288ee1d..607a71f 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -258,6 +258,9 @@ ixgb_get_regs_len(struct net_device *netdev)
 	return IXGB_REG_DUMP_LEN;
 }
 
+extern void ixgb_dump(struct ixgb_adapter *);
+extern int debug_dump;
+
 static void
 ixgb_get_regs(struct net_device *netdev,
 		   struct ethtool_regs *regs, void *p)
@@ -268,6 +271,9 @@ ixgb_get_regs(struct net_device *netdev,
 	u32 *reg_start = reg;
 	u8 i;
 
+	if (debug_dump)
+		ixgb_dump(adapter);
+
 	/* the 1 (one) below indicates an attempt at versioning, if the
 	 * interface in ethtool or the driver changes, this 1 should be
 	 * incremented */
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index 831fe0c..ac0f895 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -243,6 +243,21 @@ typedef enum {
 #define IXGB_XOFFTXC 0x021D0	/* XOFF Transmitted Count */
 #define IXGB_RJC     0x021D8	/* Receive Jabber Count */
 
+/* Diagnostic */
+#define IXGB_RDFH    0x04000    /* RX Data FIFO Head - RO */
+#define IXGB_RDFT    0x04008    /* RX Data FIFO Tail - RO */
+#define IXGB_RDFTS   0x04018    /* RX Data FIFO Tail Saved - RO */
+#define IXGB_RDFPC   0x04020    /* RX Data Packet Count - RO */
+#define IXGB_TDFH    0x04028    /* TX Data FIFO Head - RO */
+#define IXGB_TDFT    0x04030    /* TX Data FIFO Tail - RO */
+#define IXGB_TDFTS   0x04040    /* TX Data FIFO Tail Saved - RO */
+#define IXGB_TDFPC   0x04048    /* TX Data FIFO Packet Count - RO */
+#define IXGB_TREG    0x04050    /* Test Register - RW */
+#define IXGB_RPR     0x04058    /* RX Page Register - RW */
+#define IXGB_TPR     0x04060    /* TX Page Register - RW */
+#define IXGB_RPDBM   0x05000    /* RX Packet or Descriptor Buffer Memory - RO */
+#define IXGB_TPDBM   0x06000    /* TX Packet or Descriptor Buffer Memory - RO */
+
 /* CTRL0 Bit Masks */
 #define IXGB_CTRL0_LRST     0x00000008
 #define IXGB_CTRL0_JFE      0x00000010
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index eee28d3..578832f 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -32,7 +32,7 @@ char ixgb_driver_name[] = "ixgb";
 static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 
 #define DRIVERNAPI "-NAPI"
-#define DRV_VERSION "1.0.135-k2" DRIVERNAPI
+#define DRV_VERSION "1.0.136-k2" DRIVERNAPI
 const char ixgb_driver_version[] = DRV_VERSION;
 static const char ixgb_copyright[] = "Copyright (c) 1999-2008 Intel Corporation.";
 
@@ -42,6 +42,11 @@ module_param(copybreak, uint, 0644);
 MODULE_PARM_DESC(copybreak,
 	"Maximum size of packet that is copied to a new buffer on receive");
 
+unsigned int debug_dump __read_mostly = 0;
+module_param(debug_dump, uint, 0644);
+MODULE_PARM_DESC(debug_dump, "[DEBUG OPTION] dump transmit and receive "
+                             "descriptor rings");
+
 /* ixgb_pci_tbl - PCI Device ID Table
  *
  * Wildcard entries (PCI_ANY_ID) should come last
@@ -1218,7 +1223,6 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 						| IXGB_CONTEXT_DESC_CMD_IDE
 						| (skb->len - (hdr_len)));
 
-
 		if (++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
 
@@ -1490,6 +1494,133 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	return NETDEV_TX_OK;
 }
 
+void ixgb_dump(struct ixgb_adapter* adapter)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct ixgb_hw *hw = &adapter->hw;
+	int i=0;
+#define NUM_REGS 20 // 1 based count
+	uint32_t regs[NUM_REGS];
+	uint32_t *regs_buff = regs;
+	
+	char *reg_name[] = {
+	"CTRL0",  "STATUS", 
+	"RCTL", "RDLEN", "RDH", "RDT", "RDTR",
+	"TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
+	"TIDV", "TXDCTL", "RXDCTL",
+	"TDFH", "TDFT", "TDFTS", "TDFPC",
+	};
+
+	regs_buff[0]  = IXGB_READ_REG(hw, CTRL0);
+	regs_buff[1]  = IXGB_READ_REG(hw, STATUS);
+
+	regs_buff[2]  = IXGB_READ_REG(hw, RCTL);
+	regs_buff[3]  = IXGB_READ_REG(hw, RDLEN);
+	regs_buff[4]  = IXGB_READ_REG(hw, RDH);
+	regs_buff[5]  = IXGB_READ_REG(hw, RDT);
+	regs_buff[6]  = IXGB_READ_REG(hw, RDTR);
+
+	regs_buff[7]  = IXGB_READ_REG(hw, TCTL);
+	regs_buff[8]  = IXGB_READ_REG(hw, TDBAL);
+	regs_buff[9]  = IXGB_READ_REG(hw, TDBAH);
+	regs_buff[10]  = IXGB_READ_REG(hw, TDLEN);
+	regs_buff[11]  = IXGB_READ_REG(hw, TDH);
+	regs_buff[12] = IXGB_READ_REG(hw, TDT);
+
+	regs_buff[13] = IXGB_READ_REG(hw, TIDV);
+	regs_buff[14] = IXGB_READ_REG(hw, TXDCTL);
+	regs_buff[15] = IXGB_READ_REG(hw, RXDCTL);
+	regs_buff[16] = IXGB_READ_REG(hw, TDFH);
+	regs_buff[17] = IXGB_READ_REG(hw, TDFT);
+	regs_buff[18] = IXGB_READ_REG(hw, TDFTS);
+	regs_buff[19] = IXGB_READ_REG(hw, TDFPC);
+	
+	printk(KERN_ERR"Register dump\n");
+	for (i = 0; i < NUM_REGS; i++) {
+		printk("%-15s  %08x\n", 
+		reg_name[i], regs_buff[i]);
+	}
+	
+	printk(KERN_ERR"TX Desc ring0 dump @ TDBAL: %08lX\n",
+	       (unsigned long)IXGB_READ_REG(hw, TDBAL));
+
+	printk(KERN_ERR"             dma              status  len      bidma            bilen ntw ts       skb             \n");
+
+	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++ ) {
+		struct ixgb_tx_desc* tx_desc = IXGB_TX_DESC(*tx_ring, i);
+		struct ixgb_buffer *buffer_info = &tx_ring->buffer_info[i];
+		struct my_u { u64 a; u64 b;};
+		struct my_u *u = (struct my_u *)tx_desc;
+		printk("T[0x%3x]     %016llX %016llX %016llX %04X  %3X %08lX %p"
+			, i, le64_to_cpu(u->a),le64_to_cpu(u->b),
+			(u64)buffer_info->dma, buffer_info->length,
+			buffer_info->next_to_watch,
+			(unsigned long)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");
+	}
+
+	msleep(5);
+
+#if 0
+	/* print the tx fifo all 32kB of it */
+	printk("\nTx fifo\n0x   0: ");
+	for (i=0; i<0x8000; ) {
+		IXGB_WRITE_REG(hw, TPR, i);
+		printk("%08X ", IXGB_READ_REG(hw, TPDBM+(i & 0xfff)));
+		i+=4;
+		if (i % 16 == 0) {
+			printk("\n 0x%4X: ", i);
+		}
+		if (i % 64 == 0) {
+			msleep(1);
+		}
+		
+	}
+	/* print the tx descriptor cache (only 2k)*/
+	printk("\nTx descriptor cache\n0x   0: ");
+	{
+		int j;
+		IXGB_WRITE_REG(hw, TPR, 1<<20);
+		for (j=0; j < 0x800; ) {
+			printk("%08X ", IXGB_READ_REG(hw, TPDBM+j+4));
+			printk("%08X ", IXGB_READ_REG(hw, TPDBM+j));
+			j+=8;
+			if (j % 16 == 0) {
+				printk("\n 0x%4X: ", j);
+			}
+			if (j % 64 == 0) {
+				msleep(1);
+			}
+		}
+	}
+#endif
+	printk(KERN_ERR"\nRX Desc ring0 dump\n");
+
+		printk("             dma              status  len\n");
+	for (i = 0; rx_ring->desc && (i < rx_ring->count); i++ ) {
+		struct ixgb_rx_desc* rx_desc = IXGB_RX_DESC(*rx_ring, i);
+		struct my_u { u64 a; u64 b;};
+		struct my_u *u = (struct my_u *)rx_desc;
+		printk("R[0x%3x]     %016llX %016llX", i, le64_to_cpu(u->a),le64_to_cpu(u->b));
+		if (i == rx_ring->next_to_use)
+			printk(" NTU\n");
+		else if (i == rx_ring->next_to_clean)
+			printk(" NTC\n");
+		else
+			printk("\n");
+	} /* for */
+}
+
 /**
  * ixgb_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
@@ -1511,6 +1642,11 @@ ixgb_tx_timeout_task(struct work_struct *work)
 		container_of(work, struct ixgb_adapter, tx_timeout_task);
 
 	adapter->tx_timeout_count++;
+	if (debug_dump) {
+		ixgb_dump(adapter);
+		/* trigger an analyzer */
+		/* IXGB_WRITE_REG(&adapter->hw, WUS, 1); */
+	}
 	ixgb_down(adapter, true);
 	ixgb_up(adapter);
 }

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  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-26  9:05       ` [PATCH v2 0/3] e1000e, igb, ixgbe: " Taku Izumi
  2 siblings, 1 reply; 20+ messages in thread
From: Taku Izumi @ 2010-02-19  8:16 UTC (permalink / raw)
  To: Brandeburg, Jesse
  Cc: netdev, Allan, Bruce W, David S. Miller, Ronciak, John, Kirsher,
	Jeffrey T, Waskiewicz Jr, Peter P, Koki Sanagi, Kenji Kaneshige,
	chavey, e1000-devel

Hi Jesse,

> I have a counter proposal to make, here is a (incomplete) patch that we
> use all the time to debug tx hangs.  This example is for e1000e.  We are
> trying to avoid changes with other users' copyright to some of the files
> in our drivers so that we can ship them under multiple license.  We would
> much prefer something like this to be used, can you review?

  I haven't understood yet about the reason we have to avoid changing some
  files. Are there any files (header files?) we can't modify?

Best regards,
Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  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:30           ` Taku Izumi
  0 siblings, 2 replies; 20+ messages in thread
From: Jeff Kirsher @ 2010-02-19 11:20 UTC (permalink / raw)
  To: Taku Izumi
  Cc: Brandeburg, Jesse, netdev, Allan, Bruce W, David S. Miller,
	Ronciak, John, Waskiewicz Jr, Peter P, Koki Sanagi,
	Kenji Kaneshige, chavey, e1000-devel

On Fri, 2010-02-19 at 01:16 -0700, Taku Izumi wrote:
> Hi Jesse,
> 
> > I have a counter proposal to make, here is a (incomplete) patch that we
> > use all the time to debug tx hangs.  This example is for e1000e.  We are
> > trying to avoid changes with other users' copyright to some of the files
> > in our drivers so that we can ship them under multiple license.  We would
> > much prefer something like this to be used, can you review?
> 
>   I haven't understood yet about the reason we have to avoid changing some
>   files. Are there any files (header files?) we can't modify?
> 
> Best regards,
> Taku Izumi
> 

To answer your question, no there are no files you can't submit patches
to.  We do have some common files which are used/shared amongst all of
our drivers which are used for initializing and/or bring up the
hardware, so when a patch is submitted to our drivers which changes our
"shared code" our first question is "Is this change necessary for all of
our drivers?" and if the answer is no, then we take a look at what
changes can be made in the code which is not shared among our other
drivers.

-- 
Cheers,
Jeff


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/3] e1000e: add registers etc. printout code just before resetting adapters
  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
  1 sibling, 0 replies; 20+ messages in thread
From: Laurent Chavey @ 2010-02-19 19:19 UTC (permalink / raw)
  To: Taku Izumi
  Cc: netdev, Bruce Allan, David S. Miller, Jesse Brandeburg,
	John Ronciak, Kirsher, Jeffrey T, PJ Waskiewicz, Koki Sanagi,
	Kenji Kaneshige

- are you sure you want KERN_ERR rather than KERN_DEBUG ?




2010/1/21 Taku Izumi <izumi.taku@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/e1000e/hw.h     |   27 +++
>  drivers/net/e1000e/netdev.c |  341 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 368 insertions(+)
> Index: net-next-2.6/drivers/net/e1000e/netdev.c
> ===================================================================
> --- net-next-2.6.orig/drivers/net/e1000e/netdev.c
> +++ net-next-2.6/drivers/net/e1000e/netdev.c
> @@ -52,6 +52,14 @@
>  char e1000e_driver_name[] = "e1000e";
>  const char e1000e_driver_version[] = DRV_VERSION;
>
> +static unsigned int dump_flag = 1;
> +module_param(dump_flag, uint, 0644);
> +MODULE_PARM_DESC(dump_flag, "Dump Flag");
> +#define E1000_DUMP_REGS                (1 << 0)
> +#define E1000_DUMP_TX_RINGS    (1 << 1)
> +#define E1000_DUMP_RX_RINGS    (1 << 2)
> +#define E1000_DUMP_BUFFERS     (1 << 3)
> +
>  static const struct e1000_info *e1000_info_tbl[] = {
>        [board_82571]           = &e1000_82571_info,
>        [board_82572]           = &e1000_82572_info,
> @@ -65,6 +73,338 @@ static const struct e1000_info *e1000_in
>        [board_pchlan]          = &e1000_pch_info,
>  };
>
> +/*
> + * e1000_regdump - register printout routine
> + */
> +static void e1000_regdump(struct e1000_hw *hw, u32 reg,
> +                         char *name, u32 (*get_regofs)(int))
> +{
> +       printk(KERN_ERR "%-15s %08x\n", name, __er32(hw, reg));
> +}
> +
> +/*
> + * e1000_regdump_n - register printout routine
> + */
> +static void e1000_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-1]");
> +       printk(KERN_ERR "%-15s ", rname);
> +       for (n = 0; n < 2; n++)
> +               printk("%08x ", __er32(hw, get_regofs(n)));
> +       printk("\n");
> +}
> +
> +static const struct e1000_reg_info e1000_reg_info_tbl[] = {
> +
> +       /* General Registers */
> +       {E1000_CTRL, "CTRL", NULL, e1000_regdump},
> +       {E1000_STATUS, "STATUS", NULL, e1000_regdump},
> +       {E1000_CTRL_EXT, "CTRL_EXT", NULL, e1000_regdump},
> +
> +       /* Interrupt Registers */
> +       {E1000_ICR, "ICR", NULL, e1000_regdump},
> +
> +       /* RX Registers */
> +       {E1000_RCTL, "RCTL", NULL, e1000_regdump},
> +       {E1000_RDLEN, "RDLEN", NULL, e1000_regdump},
> +       {E1000_RDH, "RDH", NULL, e1000_regdump},
> +       {E1000_RDT, "RDT", NULL, e1000_regdump},
> +       {E1000_RDTR, "RDTR", NULL, e1000_regdump},
> +       {E1000_RXDCTL(0), "RXDCTL", get_regofs_RXDCTL, e1000_regdump_n},
> +       {E1000_ERT, "ERT", NULL, e1000_regdump},
> +       {E1000_RDBAL, "RDBAL", NULL, e1000_regdump},
> +       {E1000_RDBAH, "RDBAH", NULL, e1000_regdump},
> +       {E1000_RDFH, "RDFH", NULL, e1000_regdump},
> +       {E1000_RDFT, "RDFT", NULL, e1000_regdump},
> +       {E1000_RDFHS, "RDFHS", NULL, e1000_regdump},
> +       {E1000_RDFTS, "RDFTS", NULL, e1000_regdump},
> +       {E1000_RDFPC, "RDFPC", NULL, e1000_regdump},
> +
> +       /* TX Registers */
> +       {E1000_TCTL, "TCTL", NULL, e1000_regdump},
> +       {E1000_TDBAL, "TDBAL", NULL, e1000_regdump},
> +       {E1000_TDBAH, "TDBAH", NULL, e1000_regdump},
> +       {E1000_TDLEN, "TDLEN", NULL, e1000_regdump},
> +       {E1000_TDH, "TDH", NULL, e1000_regdump},
> +       {E1000_TDT, "TDT", NULL, e1000_regdump},
> +       {E1000_TIDV, "TIDV", NULL, e1000_regdump},
> +       {E1000_TXDCTL(0), "TXDCTL", get_regofs_TXDCTL, e1000_regdump_n},
> +       {E1000_TADV, "TADV", NULL, e1000_regdump},
> +       {E1000_TARC(0), "TARC", get_regofs_TARC, e1000_regdump_n},
> +       {E1000_TDFH, "TDFH", NULL, e1000_regdump},
> +       {E1000_TDFT, "TDFT", NULL, e1000_regdump},
> +       {E1000_TDFHS, "TDFHS", NULL, e1000_regdump},
> +       {E1000_TDFTS, "TDFTS", NULL, e1000_regdump},
> +       {E1000_TDFPC, "TDFPC", NULL, e1000_regdump},
> +
> +       /* List Terminator */
> +       {}
> +};
> +
> +/*
> + * e1000e_dump - Print registers, tx-ring and rx-ring
> + */
> +static void e1000e_dump(struct e1000_adapter *adapter)
> +{
> +       struct net_device *netdev = adapter->netdev;
> +       struct e1000_hw *hw = &adapter->hw;
> +       struct e1000_reg_info *reginfo;
> +       struct e1000_ring *tx_ring = adapter->tx_ring;
> +       struct e1000_tx_desc *tx_desc;
> +       struct my_u0 { u64 a; u64 b; } *u0;
> +       struct e1000_buffer *buffer_info;
> +       struct e1000_ring *rx_ring = adapter->rx_ring;
> +       union e1000_rx_desc_packet_split *rx_desc_ps;
> +       struct e1000_rx_desc *rx_desc;
> +       struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1;
> +       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 & E1000_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 e1000_reg_info *)e1000_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");
> +       buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
> +       printk(KERN_ERR " %5d %5X %5X %016llX %04X %3X %016llX\n",
> +               0, 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 & E1000_DUMP_TX_RINGS) == 0)
> +               goto rx_ring_summary;
> +
> +       dev_err(&adapter->pdev->dev, "TX Rings Dump\n");
> +
> +       /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
> +        *
> +        * Legacy Transmit Descriptor
> +        *   +--------------------------------------------------------------+
> +        * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
> +        *   +--------------------------------------------------------------+
> +        * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
> +        *   +--------------------------------------------------------------+
> +        *   63       48 47        36 35    32 31     24 23    16 15        0
> +        *
> +        * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
> +        *   63      48 47    40 39       32 31             16 15    8 7      0
> +        *   +----------------------------------------------------------------+
> +        * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
> +        *   +----------------------------------------------------------------+
> +        * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
> +        *   +----------------------------------------------------------------+
> +        *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
> +        *
> +        * Extended Data Descriptor (DTYP=0x1)
> +        *   +----------------------------------------------------------------+
> +        * 0 |                     Buffer Address [63:0]                      |
> +        *   +----------------------------------------------------------------+
> +        * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
> +        *   +----------------------------------------------------------------+
> +        *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
> +        */
> +       printk(KERN_ERR "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
> +               " [bi->dma       ] leng  ntw timestamp        bi->skb "
> +               "<-- Legacy format\n");
> +       printk(KERN_ERR "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
> +               " [bi->dma       ] leng  ntw timestamp        bi->skb "
> +               "<-- Ext Context format\n");
> +       printk(KERN_ERR "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
> +               " [bi->dma       ] leng  ntw timestamp        bi->skb "
> +               "<-- Ext Data format\n");
> +       for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
> +               tx_desc = E1000_TX_DESC(*tx_ring, i);
> +               buffer_info = &tx_ring->buffer_info[i];
> +               u0 = (struct my_u0 *)tx_desc;
> +               printk(KERN_ERR "T%c[0x%03X]    %016llX %016llX %016llX "
> +                       "%04X  %3X %016llX %p",
> +                      (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
> +                       ((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), 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 & E1000_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");
> +       printk(KERN_ERR " %5d %5X %5X\n", 0,
> +               rx_ring->next_to_use, rx_ring->next_to_clean);
> +
> +       /* Print RX Rings */
> +       if ((dump_flag & E1000_DUMP_RX_RINGS) == 0)
> +               goto exit;
> +
> +       dev_err(&adapter->pdev->dev, "RX Rings Dump\n");
> +       switch (adapter->rx_ps_pages) {
> +       case 1:
> +       case 2:
> +       case 3:
> +               /* [Extended] Packet Split Receive Descriptor Format
> +                *
> +                *    +-----------------------------------------------------+
> +                *  0 |                Buffer Address 0 [63:0]              |
> +                *    +-----------------------------------------------------+
> +                *  8 |                Buffer Address 1 [63:0]              |
> +                *    +-----------------------------------------------------+
> +                * 16 |                Buffer Address 2 [63:0]              |
> +                *    +-----------------------------------------------------+
> +                * 24 |                Buffer Address 3 [63:0]              |
> +                *    +-----------------------------------------------------+
> +                */
> +               printk(KERN_ERR "R  [desc]      [buffer 0 63:0 ] "
> +                       "[buffer 1 63:0 ] "
> +                      "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
> +                      "[bi->skb] <-- Ext Pkt Split format\n");
> +               /* [Extended] Receive Descriptor (Write-Back) Format
> +                *
> +                *   63       48 47    32 31     13 12    8 7    4 3        0
> +                *   +------------------------------------------------------+
> +                * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
> +                *   | Checksum | Ident  |         | Queue |      |  Type   |
> +                *   +------------------------------------------------------+
> +                * 8 | VLAN Tag | Length | Extended Error | Extended Status |
> +                *   +------------------------------------------------------+
> +                *   63       48 47    32 31            20 19               0
> +                */
> +               printk(KERN_ERR "RWB[desc]      [ck ipid mrqhsh] "
> +                       "[vl   l0 ee  es] "
> +                      "[ l3  l2  l1 hs] [reserved      ] ---------------- "
> +                      "[bi->skb] <-- Ext Rx Write-Back format\n");
> +               for (i = 0; i < rx_ring->count; i++) {
> +                       buffer_info = &rx_ring->buffer_info[i];
> +                       rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
> +                       u1 = (struct my_u1 *)rx_desc_ps;
> +                       staterr =
> +                               le32_to_cpu(rx_desc_ps->wb.middle.status_error);
> +                       if (staterr & E1000_RXD_STAT_DD) {
> +                               /* Descriptor Done */
> +                               printk(KERN_ERR "RWB[0x%03X]     %016llX "
> +                                       "%016llX %016llX %016llX "
> +                                       "---------------- %p", i,
> +                                       le64_to_cpu(u1->a),
> +                                       le64_to_cpu(u1->b),
> +                                       le64_to_cpu(u1->c),
> +                                       le64_to_cpu(u1->d),
> +                                       buffer_info->skb);
> +                       } else {
> +                               printk(KERN_ERR "R  [0x%03X]     %016llX "
> +                                       "%016llX %016llX %016llX %016llX %p", i,
> +                                       le64_to_cpu(u1->a),
> +                                       le64_to_cpu(u1->b),
> +                                       le64_to_cpu(u1->c),
> +                                       le64_to_cpu(u1->d),
> +                                       (u64)buffer_info->dma,
> +                                       buffer_info->skb);
> +
> +                               if (dump_flag & E1000_DUMP_BUFFERS)
> +                                       print_hex_dump(KERN_ERR, "",
> +                                               DUMP_PREFIX_ADDRESS, 16, 1,
> +                                               phys_to_virt(buffer_info->dma),
> +                                               adapter->rx_ps_bsize0, 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");
> +               }
> +               break;
> +       default:
> +       case 0:
> +               /* Legacy Receive Descriptor Format
> +                *
> +                * +-----------------------------------------------------+
> +                * |                Buffer Address [63:0]                |
> +                * +-----------------------------------------------------+
> +                * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
> +                * +-----------------------------------------------------+
> +                * 63       48 47    40 39      32 31         16 15      0
> +                */
> +               printk(KERN_ERR "Rl[desc]     [address 63:0  ] "
> +                       "[vl er S cks ln] [bi->dma       ] [bi->skb] "
> +                       "<-- Legacy format\n");
> +               for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
> +                       rx_desc = E1000_RX_DESC(*rx_ring, i);
> +                       buffer_info = &rx_ring->buffer_info[i];
> +                       u0 = (struct my_u0 *)rx_desc;
> +                       printk(KERN_ERR "Rl[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 (i == rx_ring->next_to_use)
> +                               printk(" NTU\n");
> +                       else if (i == rx_ring->next_to_clean)
> +                               printk(" NTC\n");
> +                       else
> +                               printk("\n");
> +
> +                       if (dump_flag & E1000_DUMP_BUFFERS)
> +                               print_hex_dump(KERN_ERR, "",
> +                                       DUMP_PREFIX_ADDRESS,
> +                                       16, 1, phys_to_virt(buffer_info->dma),
> +                                       adapter->rx_buffer_len, true);
> +               }
> +       }
> +
> +exit:
> +       return;
> +}
> +
>  /**
>  * e1000_desc_unused - calculate if we have unused descriptors
>  **/
> @@ -4247,6 +4587,7 @@ static void e1000_reset_task(struct work
>        struct e1000_adapter *adapter;
>        adapter = container_of(work, struct e1000_adapter, reset_task);
>
> +       e1000e_dump(adapter);
>        e1000e_reinit_locked(adapter);
>  }
>
> Index: net-next-2.6/drivers/net/e1000e/hw.h
> ===================================================================
> --- net-next-2.6.orig/drivers/net/e1000e/hw.h
> +++ net-next-2.6/drivers/net/e1000e/hw.h
> @@ -92,6 +92,11 @@ enum e1e_registers {
>        E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
>        E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
>        E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
> +       E1000_RDFH     = 0x02410, /* Rx Data FIFO Head - RW */
> +       E1000_RDFT     = 0x02418, /* Rx Data FIFO Tail - RW */
> +       E1000_RDFHS    = 0x02420, /* Rx Data FIFO Head Saved - RW */
> +       E1000_RDFTS    = 0x02428, /* Rx Data FIFO Tail Saved - RW */
> +       E1000_RDFPC    = 0x02430, /* Rx Data FIFO Packet Count - RW */
>        E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
>        E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
>        E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
> @@ -101,6 +106,11 @@ enum e1e_registers {
>        E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
>  #define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
>        E1000_RADV     = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
> +       E1000_TDFH     = 0x03410, /* Tx Data FIFO Head - RW */
> +       E1000_TDFT     = 0x03418, /* Tx Data FIFO Tail - RW */
> +       E1000_TDFHS    = 0x03420, /* Tx Data FIFO Head Saved - RW */
> +       E1000_TDFTS    = 0x03428, /* Tx Data FIFO Tail Saved - RW */
> +       E1000_TDFPC    = 0x03430, /* Tx Data FIFO Packet Count - RW */
>
>  /* Convenience macros
>  *
> @@ -219,6 +229,23 @@ enum e1e_registers {
>        E1000_HICR      = 0x08F00, /* Host Interface Control */
>  };
>
> +struct e1000_reg_info {
> +       u32 reg;
> +       char *name;
> +       u32 (*get_regofs)(int);
> +       void (*dump_reg)(struct e1000_hw *, u32, char *, u32 (*)(int));
> +};
> +
> +#define E1000_GET_REGOFS_FUNC(name)                            \
> +static inline u32 get_regofs_##name(int n)                     \
> +{                                                              \
> +       return E1000_##name(n);                                         \
> +}                                                              \
> +
> +E1000_GET_REGOFS_FUNC(RXDCTL)
> +E1000_GET_REGOFS_FUNC(TXDCTL)
> +E1000_GET_REGOFS_FUNC(TARC)
> +
>  #define E1000_MAX_PHY_ADDR             4
>
>  /* IGP01E1000 Specific Registers */
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  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
  1 sibling, 1 reply; 20+ messages in thread
From: Laurent Chavey @ 2010-02-24 19:36 UTC (permalink / raw)
  To: jeffrey.t.kirsher
  Cc: Taku Izumi, Brandeburg, Jesse, netdev, Allan, Bruce W,
	David S. Miller, Ronciak, John, Waskiewicz Jr, Peter P,
	Koki Sanagi, Kenji Kaneshige, e1000-devel

Taku,

I like the idea of adding debugging support. While using syslog does provide
a "easier" way to get the output out, I am wondering if it would be
worse the while
to try to add a generic debug interface (via ethtool / netlink) that
each driver would
then support.

If using syslog is the choosen way, then having the feature on by
default may not
be wanted.


On Fri, Feb 19, 2010 at 3:20 AM, Jeff Kirsher
<jeffrey.t.kirsher@intel.com> wrote:
> On Fri, 2010-02-19 at 01:16 -0700, Taku Izumi wrote:
>> Hi Jesse,
>>
>> > I have a counter proposal to make, here is a (incomplete) patch that we
>> > use all the time to debug tx hangs.  This example is for e1000e.  We are
>> > trying to avoid changes with other users' copyright to some of the files
>> > in our drivers so that we can ship them under multiple license.  We would
>> > much prefer something like this to be used, can you review?
>>
>>   I haven't understood yet about the reason we have to avoid changing some
>>   files. Are there any files (header files?) we can't modify?
>>
>> Best regards,
>> Taku Izumi
>>
>
> To answer your question, no there are no files you can't submit patches
> to.  We do have some common files which are used/shared amongst all of
> our drivers which are used for initializing and/or bring up the
> hardware, so when a patch is submitted to our drivers which changes our
> "shared code" our first question is "Is this change necessary for all of
> our drivers?" and if the answer is no, then we take a look at what
> changes can be made in the code which is not shared among our other
> drivers.
>
> --
> Cheers,
> Jeff
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code  just before resetting adapters
  2010-02-24 19:36           ` Laurent Chavey
@ 2010-02-25  0:24             ` Taku Izumi
  0 siblings, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-02-25  0:24 UTC (permalink / raw)
  To: Laurent Chavey
  Cc: jeffrey.t.kirsher, Brandeburg, Jesse, netdev, Allan, Bruce W,
	David S. Miller, Ronciak, John, Waskiewicz Jr, Peter P,
	Koki Sanagi, Kenji Kaneshige, e1000-devel

Hi Chavey,

> I like the idea of adding debugging support. While using syslog does provide
> a "easier" way to get the output out, I am wondering if it would be
> worse the while
> to try to add a generic debug interface (via ethtool / netlink) that
> each driver would
> then support.
> 
> If using syslog is the choosen way, then having the feature on by
> default may not
> be wanted.

I think these pritout messages are not only for debugging purpose but
a kind of error notification, for adapter resetting is error.
I prefer that these messages are always output wheter debugging mode is enabled
or not, but if it is not hoped to be always output to syslog, another place
(like a private ring buffer) is also acceptable.
Now I'm considering to output to private pring buffer.

Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
  2010-02-19 11:20         ` Jeff Kirsher
  2010-02-24 19:36           ` Laurent Chavey
@ 2010-02-25  0:30           ` Taku Izumi
  1 sibling, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-02-25  0:30 UTC (permalink / raw)
  To: jeffrey.t.kirsher
  Cc: Brandeburg, Jesse, netdev, Allan, Bruce W, David S. Miller,
	Ronciak, John, Waskiewicz Jr, Peter P, Koki Sanagi,
	Kenji Kaneshige, chavey, e1000-devel

Hi Jeff,

> To answer your question, no there are no files you can't submit patches
> to.  We do have some common files which are used/shared amongst all of
> our drivers which are used for initializing and/or bring up the
> hardware, so when a patch is submitted to our drivers which changes our
> "shared code" our first question is "Is this change necessary for all of
> our drivers?" and if the answer is no, then we take a look at what
> changes can be made in the code which is not shared among our other
> drivers.

Please tell me concretely  which part of my former submitted patchset is bad?
Next time I'll create under that condition.

Best regards,
Taku Izumi


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 0/3] e1000e, igb, ixgbe: add registers etc. printout code just before resetting adapters
  2010-02-17 19:10     ` Brandeburg, Jesse
  2010-02-17 19:32       ` Brandeburg, Jesse
  2010-02-19  8:16       ` Taku Izumi
@ 2010-02-26  9:05       ` Taku Izumi
  2 siblings, 0 replies; 20+ messages in thread
From: Taku Izumi @ 2010-02-26  9:05 UTC (permalink / raw)
  To: Brandeburg, Jesse
  Cc: Koki Sanagi, e1000-devel, netdev, Allan, Bruce W, chavey,
	Ronciak, John, Kirsher, Jeffrey T, Kenji Kaneshige,
	David S. Miller

Hi Jesse,

(2010/02/18 4:10), Brandeburg, Jesse wrote:
> 
> On Tue, 26 Jan 2010, Taku Izumi wrote:
>> (2010/01/23 6:54), Brandeburg, Jesse wrote:
>>> Taku, thanks for these, we are talking the patches over and reviewing
>>> them.  While I agree with the idea of these patches is good, I still don't
>>> agree with the default being enabled.  Usually if someone is getting tx
>>> hangs they are repeatable and we can work with them to get the debug
>>> turned on.  I DO think it is useful to have the feature available by
>>> default but NOT enabled.
>>>
>>> If we wanted to enable something by default it might be useful to print
>>> something that actually draws some conclusions from known failure modes,
>>> like if TDH!=TDT after some amount of time.  I think one or two lines
>>> maximum for default printing.
>>>
>>> If you're working in this area I had an idea.  I had wanted to be able to
>>> print the large amount of ring information (especially in the ixgbe case
>>> with many rings) to the ftrace buffers in order to not overrun the syslog
>>> daemon.  Not sure if you're interested in more new features, it certainly
>>> is separate but related to this patch.
>>
>> I thought similar things, that is, all information should be dumped to
>> the private ring buffer to avoid filling syslog up with driver messages.
>> But I didn't have any good idea to extract information from ring buffers,
>> so as the first step, I decided to printout it by using printk().
>> Is there the easy way to extract it from ring buffers?
> 
> First, I need to apologize for the delay, it's my fault.
> 
> I'm not sure about an easy way to use the private ring buffers yet, I know
> you can use the ftrace buffers directly, and then when someone read
> /sys/kernel/debug/tracing/trace they would get all the output.
> 
> Lets not do ftrace yet.
> 
> I have a counter proposal to make, here is a (incomplete) patch that we
> use all the time to debug tx hangs.  This example is for e1000e.  We are
> trying to avoid changes with other users' copyright to some of the files
> in our drivers so that we can ship them under multiple license.  We would
> much prefer something like this to be used, can you review?
> 
> I also have another patch I made for ixgb to show the use of sysfs and a
> module parameter, I'll reply again with that next.
> 
> ---
> From: Jesse Brandeburg<jesse.brandeburg@intel.com>
> 
> e1000e: dump code for descriptor rings
> 
> This is debug code for descriptor ring dumps, only enable if you really want a
> lot of stuff in your syslog/dmesg when you get NETDEV WATCHDOG or tx hang
> reports from the driver.
> 
> <not implemented>  Code can be enabled at boot time with a module parameter or
> via sysfs at runtime.
> 
> Signed-off-by: Jesse Brandeburg<jesse.brandeburg@intel.com>
> ---
> 
>   drivers/net/e1000e/ethtool.c |    4 +
>   drivers/net/e1000e/hw.h      |   10 +
>   drivers/net/e1000e/netdev.c  |  298 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 311 insertions(+), 1 deletions(-)
> 
> 
> diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
> index 0aa50c2..bbcf5c7 100644
> --- a/drivers/net/e1000e/ethtool.c
> +++ b/drivers/net/e1000e/ethtool.c
> @@ -434,6 +434,8 @@ static int e1000_get_regs_len(struct net_device *netdev)
>   	return E1000_REGS_LEN * sizeof(u32);
>   }
> 
> +extern void e1000e_dump(struct e1000_adapter *);
> +
>   static void e1000_get_regs(struct net_device *netdev,
>   			   struct ethtool_regs *regs, void *p)
>   {
> @@ -443,6 +445,8 @@ static void e1000_get_regs(struct net_device *netdev,
>   	u16 phy_data;
>   	u8 revision_id;
> 
> +	e1000e_dump(adapter);
> +
>   	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
> 
>   	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID,&revision_id);
> diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
> index eccf29b..d23501d 100644
> --- a/drivers/net/e1000e/hw.h
> +++ b/drivers/net/e1000e/hw.h
> @@ -92,6 +92,11 @@ enum e1e_registers {
>   	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
>   	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
>   	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
> +	E1000_RDFH     = 0x02410, /* Rx Data FIFO Head - RW */
> +	E1000_RDFT     = 0x02418, /* Rx Data FIFO Tail - RW */
> +	E1000_RDFHS    = 0x02420, /* Rx Data FIFO Head Saved - RW */
> +	E1000_RDFTS    = 0x02428, /* Rx Data FIFO Tail Saved - RW */
> +	E1000_RDFPC    = 0x02430, /* Rx Data FIFO Packet Count - RW */
>   	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
>   	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
>   	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
> @@ -112,6 +117,11 @@ enum e1e_registers {
>    */
>   #define E1000_RDBAL_REG(_n)   (E1000_RDBAL + (_n<<  8))
>   	E1000_KABGTXD  = 0x03004, /* AFE Band Gap Transmit Ref Data */
> +	E1000_TDFH     = 0x03410, /* TX Data FIFO Head - RW */
> +	E1000_TDFT     = 0x03418, /* TX Data FIFO Tail - RW */
> +	E1000_TDFHS    = 0x03420, /* TX Data FIFO Head Saved - RW */
> +	E1000_TDFTS    = 0x03428, /* Tx Data FIFO Tail Saved - RW */
> +	E1000_TDFPC    = 0x03430, /* TX Data FIFO Packet Count - RW */
>   	E1000_TDBAL    = 0x03800, /* Tx Descriptor Base Address Low - RW */
>   	E1000_TDBAH    = 0x03804, /* Tx Descriptor Base Address High - RW */
>   	E1000_TDLEN    = 0x03808, /* Tx Descriptor Length - RW */
> diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> index c45965a..c990341 100644
> --- a/drivers/net/e1000e/netdev.c
> +++ b/drivers/net/e1000e/netdev.c
> @@ -48,7 +48,7 @@
> 
>   #include "e1000.h"
> 
> -#define DRV_VERSION "1.0.2-k2"
> +#define DRV_VERSION "1.0.2-k4"
>   char e1000e_driver_name[] = "e1000e";
>   const char e1000e_driver_version[] = DRV_VERSION;
> 
> @@ -601,6 +601,301 @@ static void e1000_print_hw_hang(struct work_struct *work)
>   	      pci_status);
>   }
> 
> +#if 0
> +static void hexdump(dma_addr_t dma, u16 len)
> +{
> +	u16 offset, i;
> +	char str[80], byte[4];
> +	void *va = phys_to_virt((unsigned long)dma);
> +
> +	printk("buffer at %016llX (%d)\n", (u64)dma, len);
> +	for (offset = 0; offset<  len; offset += 16) {
> +		sprintf(str, "%04x: ", offset);
> +		for (i = 0; i<  16; i++) {
> +			if ((offset + i)<  len)
> +				sprintf(byte, "%02x ",
> +				        ((unsigned char *)va)[offset + i]);
> +			else
> +				strcpy(byte, "   ");
> +			strcat(str, byte);
> +		}
> +		printk("%s\n", str);
> +	}
> +}
> +
> +#endif
> +void e1000e_dump(struct e1000_adapter *adapter)
> +{
> +	/* this code doesn't handle multiple rings */
> +	struct e1000_ring *tx_ring = adapter->tx_ring;
> +	struct e1000_ring *rx_ring = adapter->rx_ring;
> +	struct e1000_hw *hw =&adapter->hw;
> +	int i = 0;
> +#define NUM_REGS 38 /* 1 based count */
> +	u32 regs[NUM_REGS];
> +	u32 *regs_buff = regs;
> +
> +	char *reg_name[] = {
> +	"CTRL",  "STATUS",
> +	"RCTL", "RDLEN", "RDH", "RDT", "RDTR",
> +	"TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
> +	"TIDV", "TXDCTL", "TADV", "TARC0",
> +	"TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1",
> +	"TXDCTL1", "TARC1",
> +	"CTRL_EXT", "ERT", "RDBAL", "RDBAH",
> +	 "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC",
> +	 "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC",
> +	};
> +
> +	//if (!e1000e_debug_dump)
> +		//return;
> +
> +	regs_buff[0]  = er32(CTRL);
> +	regs_buff[1]  = er32(STATUS);
> +
> +	regs_buff[2]  = er32(RCTL);
> +	regs_buff[3]  = er32(RDLEN);
> +	regs_buff[4]  = er32(RDH);
> +	regs_buff[5]  = er32(RDT);
> +	regs_buff[6]  = er32(RDTR);
> +
> +	regs_buff[7]  = er32(TCTL);
> +	regs_buff[8]  = er32(TDBAL);
> +	regs_buff[9]  = er32(TDBAH);
> +	regs_buff[10] = er32(TDLEN);
> +	regs_buff[11] = er32(TDH);
> +	regs_buff[12] = er32(TDT);
> +	regs_buff[13] = er32(TIDV);
> +	regs_buff[14] = er32(TXDCTL(0));
> +	regs_buff[15] = er32(TADV);
> +	regs_buff[16] = er32(TARC(0));
> +
> +	regs_buff[22] = er32(TXDCTL(1));
> +	regs_buff[23] = er32(TARC(1));
> +	regs_buff[24] = er32(CTRL_EXT);
> +	regs_buff[25] = er32(ERT);
> +	regs_buff[26] = er32(RDBAL);
> +	regs_buff[27] = er32(RDBAH);
> +	regs_buff[28] = er32(TDFH);
> +	regs_buff[29] = er32(TDFT);
> +	regs_buff[30] = er32(TDFHS);
> +	regs_buff[31] = er32(TDFTS);
> +	regs_buff[32] = er32(TDFPC);
> +	regs_buff[33] = er32(RDFH);
> +	regs_buff[34] = er32(RDFT);
> +	regs_buff[35] = er32(RDFHS);
> +	regs_buff[36] = er32(RDFTS);
> +	regs_buff[37] = er32(RDFPC);

 I think indexing is annoying especially when the number of registers
 is large for example in case of the ixgbe driver.

> +
> +	e_err("Register dump\n");
> +	for (i = 0; i<  NUM_REGS; i++) {
> +		printk("%-15s  %08x\n",
> +		reg_name[i], regs_buff[i]);
> +	}
> +
> +	/*
> +	 * transmit dump
> +	 */
> +	printk(KERN_ERR"TX Desc ring0 dump\n");
> +
> +	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
> +	 *
> +	 * Legacy Transmit Descriptor
> +	 *   +--------------------------------------------------------------+
> +	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
> +	 *   +--------------------------------------------------------------+
> +	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
> +	 *   +--------------------------------------------------------------+
> +	 *   63       48 47        36 35    32 31     24 23    16 15        0
> +	 *
> +	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
> +	 *   63      48 47    40 39       32 31             16 15    8 7      0
> +	 *   +----------------------------------------------------------------+
> +	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
> +	 *   +----------------------------------------------------------------+
> +	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
> +	 *   +----------------------------------------------------------------+
> +	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
> +	 *
> +	 * Extended Data Descriptor (DTYP=0x1)
> +	 *   +----------------------------------------------------------------+
> +	 * 0 |                     Buffer Address [63:0]                      |
> +	 *   +----------------------------------------------------------------+
> +	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
> +	 *   +----------------------------------------------------------------+
> +	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
> +	 */
> +	printk("Tl(Legacy)   [address 63:0  ] [SpeCssSCmCsLen] [buffer_info dma"
> +	       " leng  ntw       time_stamp             skb]\n");
> +	printk("Tc(ExtCont)  [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [buffer_info dma"
> +	       " leng  ntw       time_stamp             skb]\n");
> +	printk("Td(ExtData)  [address 63:0  ] [VlaPoRSCm1Dlen] [buffer_info dma"
> +	       " leng  ntw       time_stamp             skb]\n");
> +	for (i = 0; tx_ring->desc&&  (i<  tx_ring->count); i++) {
> +		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
> +		struct e1000_buffer *buffer_info =&tx_ring->buffer_info[i];
> +		struct my_u { u64 a; u64 b; };
> +		struct my_u *u = (struct my_u *)tx_desc;
> +		printk("T%c[0x%03X]    %016llX %016llX %016llX %04X  %3X "
> +		       "%016llX %p",
> +		       (!(le64_to_cpu(u->b)&  (1<<29)) ? 'l' :
> +		         ((le64_to_cpu(u->b)&  (1<<20)) ? 'd' : 'c')), i,
> +		       le64_to_cpu(u->a), le64_to_cpu(u->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 0
> +		if (adapter->dump_buffers&&  (buffer_info->dma != 0))
> +			hexdump(buffer_info->dma, buffer_info->length);
> +#endif
> +	}
> +
> +	/*
> +	 * receive dump
> +	 */
> +	printk(KERN_ERR"\nRX Desc ring dump\n");
> +
> +	switch (adapter->rx_ps_pages) {
> +	case 1:
> +	case 2:
> +	case 3:
> +		/* [Extended] Packet Split Receive Descriptor Format
> +		 *
> +		 *    +-----------------------------------------------------+
> +		 *  0 |                Buffer Address 0 [63:0]              |
> +		 *    +-----------------------------------------------------+
> +		 *  8 |                Buffer Address 1 [63:0]              |
> +		 *    +-----------------------------------------------------+
> +		 * 16 |                Buffer Address 2 [63:0]              |
> +		 *    +-----------------------------------------------------+
> +		 * 24 |                Buffer Address 3 [63:0]              |
> +		 *    +-----------------------------------------------------+
> +		 */
> +		printk("R  [desc]      [buffer 0 63:0 ] [buffer 1 63:0 ] "
> +		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
> +		       "[bi->skb]<-- Ext Pkt Split format\n");
> +		/* [Extended] Receive Descriptor (Write-Back) Format
> +		 *
> +		 *   63       48 47    32 31     13 12    8 7    4 3        0
> +		 *   +------------------------------------------------------+
> +		 * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
> +		 *   | Checksum | Ident  |         | Queue |      |  Type   |
> +		 *   +------------------------------------------------------+
> +		 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
> +		 *   +------------------------------------------------------+
> +		 *   63       48 47    32 31            20 19               0
> +		 */
> +		printk("RWB[desc]      [ck ipid mrqhsh] [vl   l0 ee  es] "
> +		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
> +		       "[bi->skb]<-- Ext Rx Write-Back format\n");
> +		for (i = 0; i<  rx_ring->count; i++) {
> +			struct e1000_buffer *buffer_info =
> +						&rx_ring->buffer_info[i];
> +			union e1000_rx_desc_packet_split *rx_desc =
> +						E1000_RX_DESC_PS(*rx_ring, i);
> +			struct my_u { u64 a; u64 b; u64 c; u64 d; };
> +			struct my_u *u = (struct my_u *)rx_desc;
> +			u32 staterr;
> +			staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
> +			if (staterr&  E1000_RXD_STAT_DD) {
> +				/* Descriptor Done */
> +				printk("RWB[0x%03X]     %016llX %016llX %016llX"
> +				       " %016llX ---------------- %p",
> +				       i, le64_to_cpu(u->a), le64_to_cpu(u->b),
> +				       le64_to_cpu(u->c), le64_to_cpu(u->d),
> +				       buffer_info->skb);
> +			} else {
> +				printk("R  [0x%03X]     %016llX %016llX %016llX"
> +				       " %016llX %016llX %p",
> +				       i, le64_to_cpu(u->a), le64_to_cpu(u->b),
> +				       le64_to_cpu(u->c), le64_to_cpu(u->d),
> +				       (u64)buffer_info->dma, buffer_info->skb);
> +
> +#if 0
> +				if (adapter->dump_buffers)
> +					hexdump(buffer_info->dma,
> +					        adapter->rx_ps_bsize0);
> +#endif
> +			}
> +
> +			if (i == rx_ring->next_to_use)
> +				printk(" NTU\n");
> +			else if (i == rx_ring->next_to_clean)
> +				printk(" NTC\n");
> +			else
> +				printk("\n");
> +		}
> +		break;
> +	default:
> +	case 0:
> +		/* Legacy Receive Descriptor Format
> +		 *
> +		 * +-----------------------------------------------------+
> +		 * |                Buffer Address [63:0]                |
> +		 * +-----------------------------------------------------+
> +		 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
> +		 * +-----------------------------------------------------+
> +		 * 63       48 47    40 39      32 31         16 15      0
> +		 */
> +		printk("Rl[desc]     [address 63:0  ] [vl er S cks ln] "
> +		       "[bi->dma       ] [bi->skb]<-- Legacy format\n");
> +		for (i = 0; rx_ring->desc&&  (i<  rx_ring->count); i++) {
> +			struct e1000_rx_desc *rx_desc =
> +						E1000_RX_DESC(*rx_ring, i);
> +			struct e1000_buffer *buffer_info =
> +						&rx_ring->buffer_info[i];
> +			struct my_u { u64 a; u64 b; };
> +			struct my_u *u = (struct my_u *)rx_desc;
> +			printk("Rl[0x%03X]    %016llX %016llX %016llX %p",
> +				i, le64_to_cpu(u->a), le64_to_cpu(u->b),
> +				(u64)buffer_info->dma, buffer_info->skb);
> +			if (i == rx_ring->next_to_use)
> +				printk(" NTU\n");
> +			else if (i == rx_ring->next_to_clean)
> +				printk(" NTC\n");
> +			else
> +				printk("\n");
> +
> +#if 0
> +			if (adapter->dump_buffers)
> +				hexdump(buffer_info->dma,
> +				        adapter->rx_buffer_len);
> +#endif
> +		} /* for */
> +	} /* switch */
> +
> +	/* dump the descriptor caches */
> +	/* rx */
> +	printk("Rx descriptor cache in 64bit format\n");
> +	for (i = 0x6000; i<= 0x63FF ; i += 0x10) {
> +		printk("R%04X: %08X|%08X %08X|%08X\n",
> +				i,
> +				readl(adapter->hw.hw_addr + i+4),
> +				readl(adapter->hw.hw_addr + i),
> +				readl(adapter->hw.hw_addr + i+12),
> +				readl(adapter->hw.hw_addr + i+8));
> +	}
> +	/* tx */
> +	printk("Tx descriptor cache in 64bit format\n");
> +	for (i = 0x7000; i<= 0x73FF ; i += 0x10) {
> +		printk("T%04X: %08X|%08X %08X|%08X\n",
> +				i,
> +				readl(adapter->hw.hw_addr + i+4),
> +				readl(adapter->hw.hw_addr + i),
> +				readl(adapter->hw.hw_addr + i+12),
> +				readl(adapter->hw.hw_addr + i+8));
> +	}
> +}
> +
>   /**
>    * e1000_clean_tx_irq - Reclaim resources after transmit completes
>    * @adapter: board private structure
> @@ -682,6 +977,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
>   			       + (adapter->tx_timeout_factor * HZ))&&
>   		!(er32(STATUS)&  E1000_STATUS_TXOFF)) {
>   			schedule_work(&adapter->print_hang_task);
> +			e1000e_dump(adapter);

  I think it is not proper to invoke e1000e_dump() here because here is in interupt
  context and there is the case of resetting adapters without meeting the condition
  of "adapter->detect_tx_hung == true"

	
>   			netif_stop_queue(netdev);
>   		}
>   	}
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

Best regards,
Taku Izumi



------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2010-02-26  9:05 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH v2 2/3] igb: " Taku Izumi
2010-01-22  8:49   ` 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

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.