e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
Subsystems (2)
v2 cover e1000e,igb,ixgbe: add registers etc. printout code just before resetting adapters
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
PATCH v2 1/3 e1000e: add registers etc. printout code just before resetting adapters
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.
--- drivers/net/e1000e/hw.h | 27 +++ drivers/net/e1000e/netdev.c | 341 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+)
drivers/net/e1000e/netdev.c +341 -0
@@ -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 workstruct e1000_adapter *adapter; adapter = container_of(work, struct e1000_adapter, reset_task); +e1000e_dump (adapter);e1000e_reinit_locked (adapter); }
drivers/net/e1000e/hw.h +27 -0
@@ -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 */
Re: [PATCH v2 1/3] e1000e: add registers etc. printout code just before resetting adapters
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.
--- drivers/net/e1000e/hw.h | 27 +++ drivers/net/e1000e/netdev.c | 341 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+)
drivers/net/e1000e/netdev.c +341 -0
@@ -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 workstruct e1000_adapter *adapter; adapter = container_of(work, struct e1000_adapter, reset_task); +e1000e_dump (adapter);e1000e_reinit_locked (adapter); }
drivers/net/e1000e/hw.h +27 -0
@@ -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 */
Re: [PATCH v2 1/3] e1000e: add registers etc. printout code just before resetting adapters
In reply to Taku Izumi- are you sure you want KERN_ERR rather than KERN_DEBUG ?
2010/1/21 Taku Izumi <[email protected]>:
Quoted 436 lines
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 andbuffer_infocan be output by changing thedump_flagmodule option, but, of course, the amount of output becomes quite large.Signed-off-by Taku Izumi <[email protected]>Signed-off-by Koki Sanagi <[email protected]>---
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
===================================================================drivers/net/e1000e/netdev.c +341
-0@@ -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
===================================================================drivers/net/e1000e/hw.h +0
-0@@ -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 */drivers/net/e1000e/hw.h +0
-0@@ -101,6 +106,11 @@ enum e1e_registers {E1000_RXDCTL_BASE =
0x02828, /* Rx Descriptor Control - RW */ #defineE1000_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
*drivers/net/e1000e/hw.h +0
-0@@ -219,6 +229,23 @@ enum e1e_registers {E1000_HICR =
0x08F00, /* Host Interface Control */ };drivers/net/e1000e/hw.h +17
-0+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_ADDR4/* IGP01E1000 Specific Registers */
PATCH v2 2/3 igb: add registers etc. printout code just before resetting adapters
In reply to Taku IzumiThis 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.
--- 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(+)
drivers/net/igb/igb_main.c +294 -0
@@ -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 EthMODULE_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_sstruct igb_adapter *adapter; adapter = container_of(work, struct igb_adapter, reset_task); +igb_dump (adapter);igb_reinit_locked (adapter); }
drivers/net/igb/e1000_regs.h +21 -0
@@ -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
drivers/net/igb/e1000_hw.h +7 -0
@@ -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...) \
Re: [PATCH v2 2/3] igb: add registers etc. printout code just before resetting adapters
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.
--- 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(+)
drivers/net/igb/igb_main.c +294 -0
@@ -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 EthMODULE_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_sstruct igb_adapter *adapter; adapter = container_of(work, struct igb_adapter, reset_task); +igb_dump (adapter);igb_reinit_locked (adapter); }
drivers/net/igb/e1000_regs.h +21 -0
@@ -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
drivers/net/igb/e1000_hw.h +7 -0
@@ -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...) \
PATCH v2 3/3 ixgbe: add registers etc. printout code just before resetting adapters
In reply to Taku IzumiThis 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.
--- drivers/net/ixgbe/ixgbe_main.c | 293 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_type.h | 29 ++++ 2 files changed, 322 insertions(+)
drivers/net/ixgbe/ixgbe_main.c +293 -0
@@ -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); }
drivers/net/ixgbe/ixgbe_type.h +29 -0
@@ -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_ */
Re: [PATCH v2 3/3] ixgbe: add registers etc. printout code just before resetting adapters
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.
--- drivers/net/ixgbe/ixgbe_main.c | 294 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_type.h | 29 ++++ 2 files changed, 323 insertions(+)
drivers/net/ixgbe/ixgbe_main.c +294 -0
@@ -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); }
drivers/net/ixgbe/ixgbe_type.h +29 -0
@@ -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_ */
Trivial:
All of the printks without KERN_<level> should be KERN_CONT
For example:
Review
Quoted 4 lines
(quoted diff) +4
-0+ 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)));
Quoted 18 lines · Joe Perches
Trivial:
All of the printks without KERN_<level> should be
KERN_CONTFor example:
Review
Quoted 4 lines
(quoted diff) +4
-0+ 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")
Quoted 5 lines
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
Re: [PATCH v2 0/3] e1000e, igb, ixgbe: add registers etc. printout code just before resetting adapters
In reply to Taku IzumiQuoted 8 lines · Taku Izumi
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=2v1 -> v2:
- replacedhexdump()withprint_hex_dump()
- changed the register printout inplementation (for-switch-case -> data-driven-table)
Quoted 5 lines
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
Hi Jesse,
Quoted 12 lines · Jesse
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.
Quoted 5 lines
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
Quoted 19 lines · Taku Izumi
Quoted 12 lines · Jesse
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.
Quoted 5 lines
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.
Quoted 5 lines
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 <[email protected]>
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.
---
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(-)
drivers/net/e1000e/ethtool.c +4 -0
@@ -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);
drivers/net/e1000e/hw.h +10 -0
@@ -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 */
drivers/net/e1000e/netdev.c +297 -1
316 lines not on this page · raw message
Quoted 2 lines · Jesse
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.
---
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(-)
drivers/net/ixgb/ixgb_ethtool.c +6 -0
@@ -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 */
drivers/net/ixgb/ixgb_hw.h +15 -0
@@ -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
drivers/net/ixgb/ixgb_main.c +138 -2
170 lines not on this page · raw message
Hi Jesse,
Quoted 5 lines
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
Quoted 8 lines · Taku Izumi
Hi Jesse,
Quoted 5 lines
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?
Quoted 6 lines
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.
Signature · 2 lines
Cheers, Jeff
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.
Quoted 30 lines · Jeff Kirsher
Quoted 8 lines · Taku Izumi
Hi Jesse,
Quoted 5 lines
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?
Quoted 6 lines
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 IzumiTo 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
Hi Chavey,
Quoted 10 lines
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
Hi Jeff,
Quoted 8 lines
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
Re: [PATCH v2 0/3] e1000e, igb, ixgbe: add registers etc. printout code just before resetting adapters
In reply to Brandeburg, JesseHi Jesse,
Quoted 207 lines · Jesse
Quoted 19 lines · Taku Izumi
Quoted 12 lines · Jesse
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.
Quoted 5 lines
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.
Quoted 5 lines
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/tracethey 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<[email protected]>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<[email protected]>---
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(-)drivers/net/e1000e/ethtool.c +4
-0@@ -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);drivers/net/e1000e/hw.h +10
-0@@ -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 */drivers/net/e1000e/netdev.c +76
-1@@ -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 );
drivers/net/e1000e/netdev.c static void e1000_print_hw_hang(struct work_struct *work) · line 688
Quoted 10 lines
drivers/net/e1000e/netdev.c +10
-0+ 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.
Quoted 214 lines
drivers/net/e1000e/netdev.c +210
-0+ +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
drivers/net/e1000e/netdev.c static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) · line 980
Quoted 4 lines
drivers/net/e1000e/netdev.c +1
-0@@ -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"
Quoted 9 lines
drivers/net/e1000e/netdev.c +0
-1netif_stop_queue (netdev); } } --To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Best regards,
Taku Izumi
------------------------------------------------------------------------------
Download Intel® 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired