mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
9.0 KiB
318 lines
9.0 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* Copyright (c) 2018 Intel Corporation */ |
|
|
|
#include "igc.h" |
|
|
|
struct igc_reg_info { |
|
u32 ofs; |
|
char *name; |
|
}; |
|
|
|
static const struct igc_reg_info igc_reg_info_tbl[] = { |
|
/* General Registers */ |
|
{IGC_CTRL, "CTRL"}, |
|
{IGC_STATUS, "STATUS"}, |
|
{IGC_CTRL_EXT, "CTRL_EXT"}, |
|
{IGC_MDIC, "MDIC"}, |
|
|
|
/* Interrupt Registers */ |
|
{IGC_ICR, "ICR"}, |
|
|
|
/* RX Registers */ |
|
{IGC_RCTL, "RCTL"}, |
|
{IGC_RDLEN(0), "RDLEN"}, |
|
{IGC_RDH(0), "RDH"}, |
|
{IGC_RDT(0), "RDT"}, |
|
{IGC_RXDCTL(0), "RXDCTL"}, |
|
{IGC_RDBAL(0), "RDBAL"}, |
|
{IGC_RDBAH(0), "RDBAH"}, |
|
|
|
/* TX Registers */ |
|
{IGC_TCTL, "TCTL"}, |
|
{IGC_TDBAL(0), "TDBAL"}, |
|
{IGC_TDBAH(0), "TDBAH"}, |
|
{IGC_TDLEN(0), "TDLEN"}, |
|
{IGC_TDH(0), "TDH"}, |
|
{IGC_TDT(0), "TDT"}, |
|
{IGC_TXDCTL(0), "TXDCTL"}, |
|
|
|
/* List Terminator */ |
|
{} |
|
}; |
|
|
|
/* igc_regdump - register printout routine */ |
|
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo) |
|
{ |
|
struct net_device *dev = igc_get_hw_dev(hw); |
|
int n = 0; |
|
char rname[16]; |
|
u32 regs[8]; |
|
|
|
switch (reginfo->ofs) { |
|
case IGC_RDLEN(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RDLEN(n)); |
|
break; |
|
case IGC_RDH(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RDH(n)); |
|
break; |
|
case IGC_RDT(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RDT(n)); |
|
break; |
|
case IGC_RXDCTL(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RXDCTL(n)); |
|
break; |
|
case IGC_RDBAL(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RDBAL(n)); |
|
break; |
|
case IGC_RDBAH(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_RDBAH(n)); |
|
break; |
|
case IGC_TDBAL(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TDBAL(n)); |
|
break; |
|
case IGC_TDBAH(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TDBAH(n)); |
|
break; |
|
case IGC_TDLEN(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TDLEN(n)); |
|
break; |
|
case IGC_TDH(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TDH(n)); |
|
break; |
|
case IGC_TDT(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TDT(n)); |
|
break; |
|
case IGC_TXDCTL(0): |
|
for (n = 0; n < 4; n++) |
|
regs[n] = rd32(IGC_TXDCTL(n)); |
|
break; |
|
default: |
|
netdev_info(dev, "%-15s %08x\n", reginfo->name, |
|
rd32(reginfo->ofs)); |
|
return; |
|
} |
|
|
|
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); |
|
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], |
|
regs[2], regs[3]); |
|
} |
|
|
|
/* igc_rings_dump - Tx-rings and Rx-rings */ |
|
void igc_rings_dump(struct igc_adapter *adapter) |
|
{ |
|
struct net_device *netdev = adapter->netdev; |
|
struct my_u0 { u64 a; u64 b; } *u0; |
|
union igc_adv_tx_desc *tx_desc; |
|
union igc_adv_rx_desc *rx_desc; |
|
struct igc_ring *tx_ring; |
|
struct igc_ring *rx_ring; |
|
u32 staterr; |
|
u16 i, n; |
|
|
|
if (!netif_msg_hw(adapter)) |
|
return; |
|
|
|
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n", |
|
netdev->state, dev_trans_start(netdev)); |
|
|
|
/* Print TX Ring Summary */ |
|
if (!netif_running(netdev)) |
|
goto exit; |
|
|
|
netdev_info(netdev, "TX Rings Summary\n"); |
|
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); |
|
for (n = 0; n < adapter->num_tx_queues; n++) { |
|
struct igc_tx_buffer *buffer_info; |
|
|
|
tx_ring = adapter->tx_ring[n]; |
|
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; |
|
|
|
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n", |
|
n, tx_ring->next_to_use, tx_ring->next_to_clean, |
|
(u64)dma_unmap_addr(buffer_info, dma), |
|
dma_unmap_len(buffer_info, len), |
|
buffer_info->next_to_watch, |
|
(u64)buffer_info->time_stamp); |
|
} |
|
|
|
/* Print TX Rings */ |
|
if (!netif_msg_tx_done(adapter)) |
|
goto rx_ring_summary; |
|
|
|
netdev_info(netdev, "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]; |
|
netdev_info(netdev, "------------------------------------\n"); |
|
netdev_info(netdev, "TX QUEUE INDEX = %d\n", |
|
tx_ring->queue_index); |
|
netdev_info(netdev, "------------------------------------\n"); |
|
netdev_info(netdev, "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++) { |
|
const char *next_desc; |
|
struct igc_tx_buffer *buffer_info; |
|
|
|
tx_desc = IGC_TX_DESC(tx_ring, i); |
|
buffer_info = &tx_ring->tx_buffer_info[i]; |
|
u0 = (struct my_u0 *)tx_desc; |
|
if (i == tx_ring->next_to_use && |
|
i == tx_ring->next_to_clean) |
|
next_desc = " NTC/U"; |
|
else if (i == tx_ring->next_to_use) |
|
next_desc = " NTU"; |
|
else if (i == tx_ring->next_to_clean) |
|
next_desc = " NTC"; |
|
else |
|
next_desc = ""; |
|
|
|
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n", |
|
i, le64_to_cpu(u0->a), |
|
le64_to_cpu(u0->b), |
|
(u64)dma_unmap_addr(buffer_info, dma), |
|
dma_unmap_len(buffer_info, len), |
|
buffer_info->next_to_watch, |
|
(u64)buffer_info->time_stamp, |
|
buffer_info->skb, next_desc); |
|
|
|
if (netif_msg_pktdata(adapter) && buffer_info->skb) |
|
print_hex_dump(KERN_INFO, "", |
|
DUMP_PREFIX_ADDRESS, |
|
16, 1, buffer_info->skb->data, |
|
dma_unmap_len(buffer_info, len), |
|
true); |
|
} |
|
} |
|
|
|
/* Print RX Rings Summary */ |
|
rx_ring_summary: |
|
netdev_info(netdev, "RX Rings Summary\n"); |
|
netdev_info(netdev, "Queue [NTU] [NTC]\n"); |
|
for (n = 0; n < adapter->num_rx_queues; n++) { |
|
rx_ring = adapter->rx_ring[n]; |
|
netdev_info(netdev, "%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; |
|
|
|
netdev_info(netdev, "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]; |
|
netdev_info(netdev, "------------------------------------\n"); |
|
netdev_info(netdev, "RX QUEUE INDEX = %d\n", |
|
rx_ring->queue_index); |
|
netdev_info(netdev, "------------------------------------\n"); |
|
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); |
|
netdev_info(netdev, "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++) { |
|
const char *next_desc; |
|
struct igc_rx_buffer *buffer_info; |
|
|
|
buffer_info = &rx_ring->rx_buffer_info[i]; |
|
rx_desc = IGC_RX_DESC(rx_ring, i); |
|
u0 = (struct my_u0 *)rx_desc; |
|
staterr = le32_to_cpu(rx_desc->wb.upper.status_error); |
|
|
|
if (i == rx_ring->next_to_use) |
|
next_desc = " NTU"; |
|
else if (i == rx_ring->next_to_clean) |
|
next_desc = " NTC"; |
|
else |
|
next_desc = ""; |
|
|
|
if (staterr & IGC_RXD_STAT_DD) { |
|
/* Descriptor Done */ |
|
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n", |
|
"RWB", i, |
|
le64_to_cpu(u0->a), |
|
le64_to_cpu(u0->b), |
|
next_desc); |
|
} else { |
|
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n", |
|
"R ", i, |
|
le64_to_cpu(u0->a), |
|
le64_to_cpu(u0->b), |
|
(u64)buffer_info->dma, |
|
next_desc); |
|
|
|
if (netif_msg_pktdata(adapter) && |
|
buffer_info->dma && buffer_info->page) { |
|
print_hex_dump(KERN_INFO, "", |
|
DUMP_PREFIX_ADDRESS, |
|
16, 1, |
|
page_address |
|
(buffer_info->page) + |
|
buffer_info->page_offset, |
|
igc_rx_bufsz(rx_ring), |
|
true); |
|
} |
|
} |
|
} |
|
} |
|
|
|
exit: |
|
return; |
|
} |
|
|
|
/* igc_regs_dump - registers dump */ |
|
void igc_regs_dump(struct igc_adapter *adapter) |
|
{ |
|
struct igc_hw *hw = &adapter->hw; |
|
struct igc_reg_info *reginfo; |
|
|
|
/* Print Registers */ |
|
netdev_info(adapter->netdev, "Register Dump\n"); |
|
netdev_info(adapter->netdev, "Register Name Value\n"); |
|
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl; |
|
reginfo->name; reginfo++) { |
|
igc_regdump(hw, reginfo); |
|
} |
|
}
|
|
|