1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2018 Intel Corporation */ |
3 | |
4 | #include "igc.h" |
5 | |
6 | struct igc_reg_info { |
7 | u32 ofs; |
8 | char *name; |
9 | }; |
10 | |
11 | static const struct igc_reg_info igc_reg_info_tbl[] = { |
12 | /* General Registers */ |
13 | {IGC_CTRL, "CTRL" }, |
14 | {IGC_STATUS, "STATUS" }, |
15 | {IGC_CTRL_EXT, "CTRL_EXT" }, |
16 | {IGC_MDIC, "MDIC" }, |
17 | |
18 | /* Interrupt Registers */ |
19 | {IGC_ICR, "ICR" }, |
20 | |
21 | /* RX Registers */ |
22 | {IGC_RCTL, "RCTL" }, |
23 | {IGC_RDLEN(0), "RDLEN" }, |
24 | {IGC_RDH(0), "RDH" }, |
25 | {IGC_RDT(0), "RDT" }, |
26 | {IGC_RXDCTL(0), "RXDCTL" }, |
27 | {IGC_RDBAL(0), "RDBAL" }, |
28 | {IGC_RDBAH(0), "RDBAH" }, |
29 | |
30 | /* TX Registers */ |
31 | {IGC_TCTL, "TCTL" }, |
32 | {IGC_TDBAL(0), "TDBAL" }, |
33 | {IGC_TDBAH(0), "TDBAH" }, |
34 | {IGC_TDLEN(0), "TDLEN" }, |
35 | {IGC_TDH(0), "TDH" }, |
36 | {IGC_TDT(0), "TDT" }, |
37 | {IGC_TXDCTL(0), "TXDCTL" }, |
38 | |
39 | /* List Terminator */ |
40 | {} |
41 | }; |
42 | |
43 | /* igc_regdump - register printout routine */ |
44 | static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo) |
45 | { |
46 | struct net_device *dev = igc_get_hw_dev(hw); |
47 | int n = 0; |
48 | char rname[16]; |
49 | u32 regs[8]; |
50 | |
51 | switch (reginfo->ofs) { |
52 | case IGC_RDLEN(0): |
53 | for (n = 0; n < 4; n++) |
54 | regs[n] = rd32(IGC_RDLEN(n)); |
55 | break; |
56 | case IGC_RDH(0): |
57 | for (n = 0; n < 4; n++) |
58 | regs[n] = rd32(IGC_RDH(n)); |
59 | break; |
60 | case IGC_RDT(0): |
61 | for (n = 0; n < 4; n++) |
62 | regs[n] = rd32(IGC_RDT(n)); |
63 | break; |
64 | case IGC_RXDCTL(0): |
65 | for (n = 0; n < 4; n++) |
66 | regs[n] = rd32(IGC_RXDCTL(n)); |
67 | break; |
68 | case IGC_RDBAL(0): |
69 | for (n = 0; n < 4; n++) |
70 | regs[n] = rd32(IGC_RDBAL(n)); |
71 | break; |
72 | case IGC_RDBAH(0): |
73 | for (n = 0; n < 4; n++) |
74 | regs[n] = rd32(IGC_RDBAH(n)); |
75 | break; |
76 | case IGC_TDBAL(0): |
77 | for (n = 0; n < 4; n++) |
78 | regs[n] = rd32(IGC_TDBAL(n)); |
79 | break; |
80 | case IGC_TDBAH(0): |
81 | for (n = 0; n < 4; n++) |
82 | regs[n] = rd32(IGC_TDBAH(n)); |
83 | break; |
84 | case IGC_TDLEN(0): |
85 | for (n = 0; n < 4; n++) |
86 | regs[n] = rd32(IGC_TDLEN(n)); |
87 | break; |
88 | case IGC_TDH(0): |
89 | for (n = 0; n < 4; n++) |
90 | regs[n] = rd32(IGC_TDH(n)); |
91 | break; |
92 | case IGC_TDT(0): |
93 | for (n = 0; n < 4; n++) |
94 | regs[n] = rd32(IGC_TDT(n)); |
95 | break; |
96 | case IGC_TXDCTL(0): |
97 | for (n = 0; n < 4; n++) |
98 | regs[n] = rd32(IGC_TXDCTL(n)); |
99 | break; |
100 | default: |
101 | netdev_info(dev, format: "%-15s %08x\n" , reginfo->name, |
102 | rd32(reginfo->ofs)); |
103 | return; |
104 | } |
105 | |
106 | snprintf(buf: rname, size: 16, fmt: "%s%s" , reginfo->name, "[0-3]" ); |
107 | netdev_info(dev, format: "%-15s %08x %08x %08x %08x\n" , rname, regs[0], regs[1], |
108 | regs[2], regs[3]); |
109 | } |
110 | |
111 | /* igc_rings_dump - Tx-rings and Rx-rings */ |
112 | void igc_rings_dump(struct igc_adapter *adapter) |
113 | { |
114 | struct net_device *netdev = adapter->netdev; |
115 | struct my_u0 { __le64 a; __le64 b; } *u0; |
116 | union igc_adv_tx_desc *tx_desc; |
117 | union igc_adv_rx_desc *rx_desc; |
118 | struct igc_ring *tx_ring; |
119 | struct igc_ring *rx_ring; |
120 | u32 staterr; |
121 | u16 i, n; |
122 | |
123 | if (!netif_msg_hw(adapter)) |
124 | return; |
125 | |
126 | netdev_info(dev: netdev, format: "Device info: state %016lX trans_start %016lX\n" , |
127 | netdev->state, dev_trans_start(dev: netdev)); |
128 | |
129 | /* Print TX Ring Summary */ |
130 | if (!netif_running(dev: netdev)) |
131 | goto exit; |
132 | |
133 | netdev_info(dev: netdev, format: "TX Rings Summary\n" ); |
134 | netdev_info(dev: netdev, format: "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n" ); |
135 | for (n = 0; n < adapter->num_tx_queues; n++) { |
136 | struct igc_tx_buffer *buffer_info; |
137 | |
138 | tx_ring = adapter->tx_ring[n]; |
139 | buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; |
140 | |
141 | netdev_info(dev: netdev, format: "%5d %5X %5X %016llX %04X %p %016llX\n" , |
142 | n, tx_ring->next_to_use, tx_ring->next_to_clean, |
143 | (u64)dma_unmap_addr(buffer_info, dma), |
144 | dma_unmap_len(buffer_info, len), |
145 | buffer_info->next_to_watch, |
146 | (u64)buffer_info->time_stamp); |
147 | } |
148 | |
149 | /* Print TX Rings */ |
150 | if (!netif_msg_tx_done(adapter)) |
151 | goto rx_ring_summary; |
152 | |
153 | netdev_info(dev: netdev, format: "TX Rings Dump\n" ); |
154 | |
155 | /* Transmit Descriptor Formats |
156 | * |
157 | * Advanced Transmit Descriptor |
158 | * +--------------------------------------------------------------+ |
159 | * 0 | Buffer Address [63:0] | |
160 | * +--------------------------------------------------------------+ |
161 | * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN | |
162 | * +--------------------------------------------------------------+ |
163 | * 63 46 45 40 39 38 36 35 32 31 24 15 0 |
164 | */ |
165 | |
166 | for (n = 0; n < adapter->num_tx_queues; n++) { |
167 | tx_ring = adapter->tx_ring[n]; |
168 | netdev_info(dev: netdev, format: "------------------------------------\n" ); |
169 | netdev_info(dev: netdev, format: "TX QUEUE INDEX = %d\n" , |
170 | tx_ring->queue_index); |
171 | netdev_info(dev: netdev, format: "------------------------------------\n" ); |
172 | netdev_info(dev: netdev, format: "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n" ); |
173 | |
174 | for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { |
175 | const char *next_desc; |
176 | struct igc_tx_buffer *buffer_info; |
177 | |
178 | tx_desc = IGC_TX_DESC(tx_ring, i); |
179 | buffer_info = &tx_ring->tx_buffer_info[i]; |
180 | u0 = (struct my_u0 *)tx_desc; |
181 | if (i == tx_ring->next_to_use && |
182 | i == tx_ring->next_to_clean) |
183 | next_desc = " NTC/U" ; |
184 | else if (i == tx_ring->next_to_use) |
185 | next_desc = " NTU" ; |
186 | else if (i == tx_ring->next_to_clean) |
187 | next_desc = " NTC" ; |
188 | else |
189 | next_desc = "" ; |
190 | |
191 | netdev_info(dev: netdev, format: "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n" , |
192 | i, le64_to_cpu(u0->a), |
193 | le64_to_cpu(u0->b), |
194 | (u64)dma_unmap_addr(buffer_info, dma), |
195 | dma_unmap_len(buffer_info, len), |
196 | buffer_info->next_to_watch, |
197 | (u64)buffer_info->time_stamp, |
198 | buffer_info->skb, next_desc); |
199 | |
200 | if (netif_msg_pktdata(adapter) && buffer_info->skb) |
201 | print_hex_dump(KERN_INFO, prefix_str: "" , |
202 | prefix_type: DUMP_PREFIX_ADDRESS, |
203 | rowsize: 16, groupsize: 1, buf: buffer_info->skb->data, |
204 | dma_unmap_len(buffer_info, len), |
205 | ascii: true); |
206 | } |
207 | } |
208 | |
209 | /* Print RX Rings Summary */ |
210 | rx_ring_summary: |
211 | netdev_info(dev: netdev, format: "RX Rings Summary\n" ); |
212 | netdev_info(dev: netdev, format: "Queue [NTU] [NTC]\n" ); |
213 | for (n = 0; n < adapter->num_rx_queues; n++) { |
214 | rx_ring = adapter->rx_ring[n]; |
215 | netdev_info(dev: netdev, format: "%5d %5X %5X\n" , n, rx_ring->next_to_use, |
216 | rx_ring->next_to_clean); |
217 | } |
218 | |
219 | /* Print RX Rings */ |
220 | if (!netif_msg_rx_status(adapter)) |
221 | goto exit; |
222 | |
223 | netdev_info(dev: netdev, format: "RX Rings Dump\n" ); |
224 | |
225 | /* Advanced Receive Descriptor (Read) Format |
226 | * 63 1 0 |
227 | * +-----------------------------------------------------+ |
228 | * 0 | Packet Buffer Address [63:1] |A0/NSE| |
229 | * +----------------------------------------------+------+ |
230 | * 8 | Header Buffer Address [63:1] | DD | |
231 | * +-----------------------------------------------------+ |
232 | * |
233 | * |
234 | * Advanced Receive Descriptor (Write-Back) Format |
235 | * |
236 | * 63 48 47 32 31 30 21 20 17 16 4 3 0 |
237 | * +------------------------------------------------------+ |
238 | * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | |
239 | * | Checksum Ident | | | | Type | Type | |
240 | * +------------------------------------------------------+ |
241 | * 8 | VLAN Tag | Length | Extended Error | Extended Status | |
242 | * +------------------------------------------------------+ |
243 | * 63 48 47 32 31 20 19 0 |
244 | */ |
245 | |
246 | for (n = 0; n < adapter->num_rx_queues; n++) { |
247 | rx_ring = adapter->rx_ring[n]; |
248 | netdev_info(dev: netdev, format: "------------------------------------\n" ); |
249 | netdev_info(dev: netdev, format: "RX QUEUE INDEX = %d\n" , |
250 | rx_ring->queue_index); |
251 | netdev_info(dev: netdev, format: "------------------------------------\n" ); |
252 | netdev_info(dev: netdev, format: "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n" ); |
253 | netdev_info(dev: netdev, format: "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n" ); |
254 | |
255 | for (i = 0; i < rx_ring->count; i++) { |
256 | const char *next_desc; |
257 | struct igc_rx_buffer *buffer_info; |
258 | |
259 | buffer_info = &rx_ring->rx_buffer_info[i]; |
260 | rx_desc = IGC_RX_DESC(rx_ring, i); |
261 | u0 = (struct my_u0 *)rx_desc; |
262 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); |
263 | |
264 | if (i == rx_ring->next_to_use) |
265 | next_desc = " NTU" ; |
266 | else if (i == rx_ring->next_to_clean) |
267 | next_desc = " NTC" ; |
268 | else |
269 | next_desc = "" ; |
270 | |
271 | if (staterr & IGC_RXD_STAT_DD) { |
272 | /* Descriptor Done */ |
273 | netdev_info(dev: netdev, format: "%s[0x%03X] %016llX %016llX ---------------- %s\n" , |
274 | "RWB" , i, |
275 | le64_to_cpu(u0->a), |
276 | le64_to_cpu(u0->b), |
277 | next_desc); |
278 | } else { |
279 | netdev_info(dev: netdev, format: "%s[0x%03X] %016llX %016llX %016llX %s\n" , |
280 | "R " , i, |
281 | le64_to_cpu(u0->a), |
282 | le64_to_cpu(u0->b), |
283 | (u64)buffer_info->dma, |
284 | next_desc); |
285 | |
286 | if (netif_msg_pktdata(adapter) && |
287 | buffer_info->dma && buffer_info->page) { |
288 | print_hex_dump(KERN_INFO, prefix_str: "" , |
289 | prefix_type: DUMP_PREFIX_ADDRESS, |
290 | rowsize: 16, groupsize: 1, |
291 | page_address |
292 | (buffer_info->page) + |
293 | buffer_info->page_offset, |
294 | len: igc_rx_bufsz(ring: rx_ring), |
295 | ascii: true); |
296 | } |
297 | } |
298 | } |
299 | } |
300 | |
301 | exit: |
302 | return; |
303 | } |
304 | |
305 | /* igc_regs_dump - registers dump */ |
306 | void igc_regs_dump(struct igc_adapter *adapter) |
307 | { |
308 | struct igc_hw *hw = &adapter->hw; |
309 | struct igc_reg_info *reginfo; |
310 | |
311 | /* Print Registers */ |
312 | netdev_info(dev: adapter->netdev, format: "Register Dump\n" ); |
313 | netdev_info(dev: adapter->netdev, format: "Register Name Value\n" ); |
314 | for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl; |
315 | reginfo->name; reginfo++) { |
316 | igc_regdump(hw, reginfo); |
317 | } |
318 | } |
319 | |