diff mbox

[v2,1/3] e1000e: add registers etc. printout code just before resetting adapters

Message ID 4B593C33.5020208@jp.fujitsu.com
State Awaiting Upstream, archived
Delegated to: David Miller
Headers show

Commit Message

Taku Izumi Jan. 22, 2010, 5:48 a.m. UTC
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(+)

--
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

Comments

laurent chavey Feb. 19, 2010, 7:19 p.m. UTC | #1
- 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 */
>
>
--
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
diff mbox

Patch

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 */