forked from luck/tmp_suning_uos_patched
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. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
84f4ee902a
commit
c97ec42a7a
@ -201,6 +201,336 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
struct igb_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct igb_reg_info igb_reg_info_tbl[] = {
|
||||
|
||||
/* General Registers */
|
||||
{E1000_CTRL, "CTRL"},
|
||||
{E1000_STATUS, "STATUS"},
|
||||
{E1000_CTRL_EXT, "CTRL_EXT"},
|
||||
|
||||
/* Interrupt Registers */
|
||||
{E1000_ICR, "ICR"},
|
||||
|
||||
/* RX Registers */
|
||||
{E1000_RCTL, "RCTL"},
|
||||
{E1000_RDLEN(0), "RDLEN"},
|
||||
{E1000_RDH(0), "RDH"},
|
||||
{E1000_RDT(0), "RDT"},
|
||||
{E1000_RXDCTL(0), "RXDCTL"},
|
||||
{E1000_RDBAL(0), "RDBAL"},
|
||||
{E1000_RDBAH(0), "RDBAH"},
|
||||
|
||||
/* TX Registers */
|
||||
{E1000_TCTL, "TCTL"},
|
||||
{E1000_TDBAL(0), "TDBAL"},
|
||||
{E1000_TDBAH(0), "TDBAH"},
|
||||
{E1000_TDLEN(0), "TDLEN"},
|
||||
{E1000_TDH(0), "TDH"},
|
||||
{E1000_TDT(0), "TDT"},
|
||||
{E1000_TXDCTL(0), "TXDCTL"},
|
||||
{E1000_TDFH, "TDFH"},
|
||||
{E1000_TDFT, "TDFT"},
|
||||
{E1000_TDFHS, "TDFHS"},
|
||||
{E1000_TDFPC, "TDFPC"},
|
||||
|
||||
/* List Terminator */
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* igb_regdump - register printout routine
|
||||
*/
|
||||
static void igb_regdump(struct e1000_hw *hw, struct igb_reg_info *reginfo)
|
||||
{
|
||||
int n = 0;
|
||||
char rname[16];
|
||||
u32 regs[8];
|
||||
|
||||
switch (reginfo->ofs) {
|
||||
case E1000_RDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDLEN(n));
|
||||
break;
|
||||
case E1000_RDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDH(n));
|
||||
break;
|
||||
case E1000_RDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDT(n));
|
||||
break;
|
||||
case E1000_RXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RXDCTL(n));
|
||||
break;
|
||||
case E1000_RDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDBAL(n));
|
||||
break;
|
||||
case E1000_RDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDBAH(n));
|
||||
break;
|
||||
case E1000_TDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_RDBAL(n));
|
||||
break;
|
||||
case E1000_TDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_TDBAH(n));
|
||||
break;
|
||||
case E1000_TDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_TDLEN(n));
|
||||
break;
|
||||
case E1000_TDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_TDH(n));
|
||||
break;
|
||||
case E1000_TDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_TDT(n));
|
||||
break;
|
||||
case E1000_TXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(E1000_TXDCTL(n));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_INFO "%-15s %08x\n",
|
||||
reginfo->name, rd32(reginfo->ofs));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
|
||||
printk(KERN_INFO "%-15s ", rname);
|
||||
for (n = 0; n < 4; n++)
|
||||
printk(KERN_CONT "%08x ", regs[n]);
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (!netif_msg_hw(adapter))
|
||||
return;
|
||||
|
||||
/* Print netdevice Info */
|
||||
if (netdev) {
|
||||
dev_info(&adapter->pdev->dev, "Net device Info\n");
|
||||
printk(KERN_INFO "Device Name state "
|
||||
"trans_start last_rx\n");
|
||||
printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
|
||||
netdev->name,
|
||||
netdev->state,
|
||||
netdev->trans_start,
|
||||
netdev->last_rx);
|
||||
}
|
||||
|
||||
/* Print Registers */
|
||||
dev_info(&adapter->pdev->dev, "Register Dump\n");
|
||||
printk(KERN_INFO " Register Name Value\n");
|
||||
for (reginfo = (struct igb_reg_info *)igb_reg_info_tbl;
|
||||
reginfo->name; reginfo++) {
|
||||
igb_regdump(hw, reginfo);
|
||||
}
|
||||
|
||||
/* Print TX Ring Summary */
|
||||
if (!netdev || !netif_running(netdev))
|
||||
goto exit;
|
||||
|
||||
dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
|
||||
printk(KERN_INFO "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_INFO " %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 (!netif_msg_tx_done(adapter))
|
||||
goto rx_ring_summary;
|
||||
|
||||
dev_info(&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_INFO "------------------------------------\n");
|
||||
printk(KERN_INFO "TX QUEUE INDEX = %d\n", tx_ring->queue_index);
|
||||
printk(KERN_INFO "------------------------------------\n");
|
||||
printk(KERN_INFO "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_INFO "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 (netif_msg_pktdata(adapter) && buffer_info->dma != 0)
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1, phys_to_virt(buffer_info->dma),
|
||||
buffer_info->length, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print RX Rings Summary */
|
||||
rx_ring_summary:
|
||||
dev_info(&adapter->pdev->dev, "RX Rings Summary\n");
|
||||
printk(KERN_INFO "Queue [NTU] [NTC]\n");
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
printk(KERN_INFO " %5d %5X %5X\n", n,
|
||||
rx_ring->next_to_use, rx_ring->next_to_clean);
|
||||
}
|
||||
|
||||
/* Print RX Rings */
|
||||
if (!netif_msg_rx_status(adapter))
|
||||
goto exit;
|
||||
|
||||
dev_info(&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_INFO "------------------------------------\n");
|
||||
printk(KERN_INFO "RX QUEUE INDEX = %d\n", rx_ring->queue_index);
|
||||
printk(KERN_INFO "------------------------------------\n");
|
||||
printk(KERN_INFO "R [desc] [ PktBuf A0] "
|
||||
"[ HeadBuf DD] [bi->dma ] [bi->skb] "
|
||||
"<-- Adv Rx Read format\n");
|
||||
printk(KERN_INFO "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_INFO "RWB[0x%03X] %016llX "
|
||||
"%016llX ---------------- %p", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
buffer_info->skb);
|
||||
} else {
|
||||
printk(KERN_INFO "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 (netif_msg_pktdata(adapter)) {
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
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_INFO, "",
|
||||
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)
|
||||
*/
|
||||
@ -3858,6 +4188,8 @@ static void igb_reset_task(struct work_struct *work)
|
||||
struct igb_adapter *adapter;
|
||||
adapter = container_of(work, struct igb_adapter, reset_task);
|
||||
|
||||
igb_dump(adapter);
|
||||
netdev_err(adapter->netdev, "Reset adapter\n");
|
||||
igb_reinit_locked(adapter);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user