1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
2 | /* QLogic qede NIC Driver |
3 | * Copyright (c) 2015-2017 QLogic Corporation |
4 | * Copyright (c) 2019-2020 Marvell International Ltd. |
5 | */ |
6 | |
7 | #include <linux/types.h> |
8 | #include <linux/netdevice.h> |
9 | #include <linux/etherdevice.h> |
10 | #include <linux/ethtool.h> |
11 | #include <linux/string.h> |
12 | #include <linux/pci.h> |
13 | #include <linux/capability.h> |
14 | #include <linux/vmalloc.h> |
15 | #include <linux/phylink.h> |
16 | |
17 | #include "qede.h" |
18 | #include "qede_ptp.h" |
19 | |
20 | #define QEDE_RQSTAT_OFFSET(stat_name) \ |
21 | (offsetof(struct qede_rx_queue, stat_name)) |
22 | #define QEDE_RQSTAT_STRING(stat_name) (#stat_name) |
23 | #define QEDE_RQSTAT(stat_name) \ |
24 | {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} |
25 | |
26 | #define QEDE_SELFTEST_POLL_COUNT 100 |
27 | #define QEDE_DUMP_VERSION 0x1 |
28 | #define QEDE_DUMP_NVM_ARG_COUNT 2 |
29 | |
30 | static const struct { |
31 | u64 offset; |
32 | char string[ETH_GSTRING_LEN]; |
33 | } qede_rqstats_arr[] = { |
34 | QEDE_RQSTAT(rcv_pkts), |
35 | QEDE_RQSTAT(rx_hw_errors), |
36 | QEDE_RQSTAT(rx_alloc_errors), |
37 | QEDE_RQSTAT(rx_ip_frags), |
38 | QEDE_RQSTAT(xdp_no_pass), |
39 | }; |
40 | |
41 | #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) |
42 | #define QEDE_TQSTAT_OFFSET(stat_name) \ |
43 | (offsetof(struct qede_tx_queue, stat_name)) |
44 | #define QEDE_TQSTAT_STRING(stat_name) (#stat_name) |
45 | #define QEDE_TQSTAT(stat_name) \ |
46 | {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)} |
47 | #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr) |
48 | static const struct { |
49 | u64 offset; |
50 | char string[ETH_GSTRING_LEN]; |
51 | } qede_tqstats_arr[] = { |
52 | QEDE_TQSTAT(xmit_pkts), |
53 | QEDE_TQSTAT(stopped_cnt), |
54 | QEDE_TQSTAT(tx_mem_alloc_err), |
55 | }; |
56 | |
57 | #define QEDE_STAT_OFFSET(stat_name, type, base) \ |
58 | (offsetof(type, stat_name) + (base)) |
59 | #define QEDE_STAT_STRING(stat_name) (#stat_name) |
60 | #define _QEDE_STAT(stat_name, type, base, attr) \ |
61 | {QEDE_STAT_OFFSET(stat_name, type, base), \ |
62 | QEDE_STAT_STRING(stat_name), \ |
63 | attr} |
64 | #define QEDE_STAT(stat_name) \ |
65 | _QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0) |
66 | #define QEDE_PF_STAT(stat_name) \ |
67 | _QEDE_STAT(stat_name, struct qede_stats_common, 0, \ |
68 | BIT(QEDE_STAT_PF_ONLY)) |
69 | #define QEDE_PF_BB_STAT(stat_name) \ |
70 | _QEDE_STAT(stat_name, struct qede_stats_bb, \ |
71 | offsetof(struct qede_stats, bb), \ |
72 | BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY)) |
73 | #define QEDE_PF_AH_STAT(stat_name) \ |
74 | _QEDE_STAT(stat_name, struct qede_stats_ah, \ |
75 | offsetof(struct qede_stats, ah), \ |
76 | BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY)) |
77 | static const struct { |
78 | u64 offset; |
79 | char string[ETH_GSTRING_LEN]; |
80 | unsigned long attr; |
81 | #define QEDE_STAT_PF_ONLY 0 |
82 | #define QEDE_STAT_BB_ONLY 1 |
83 | #define QEDE_STAT_AH_ONLY 2 |
84 | } qede_stats_arr[] = { |
85 | QEDE_STAT(rx_ucast_bytes), |
86 | QEDE_STAT(rx_mcast_bytes), |
87 | QEDE_STAT(rx_bcast_bytes), |
88 | QEDE_STAT(rx_ucast_pkts), |
89 | QEDE_STAT(rx_mcast_pkts), |
90 | QEDE_STAT(rx_bcast_pkts), |
91 | |
92 | QEDE_STAT(tx_ucast_bytes), |
93 | QEDE_STAT(tx_mcast_bytes), |
94 | QEDE_STAT(tx_bcast_bytes), |
95 | QEDE_STAT(tx_ucast_pkts), |
96 | QEDE_STAT(tx_mcast_pkts), |
97 | QEDE_STAT(tx_bcast_pkts), |
98 | |
99 | QEDE_PF_STAT(rx_64_byte_packets), |
100 | QEDE_PF_STAT(rx_65_to_127_byte_packets), |
101 | QEDE_PF_STAT(rx_128_to_255_byte_packets), |
102 | QEDE_PF_STAT(rx_256_to_511_byte_packets), |
103 | QEDE_PF_STAT(rx_512_to_1023_byte_packets), |
104 | QEDE_PF_STAT(rx_1024_to_1518_byte_packets), |
105 | QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets), |
106 | QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets), |
107 | QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets), |
108 | QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets), |
109 | QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets), |
110 | QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets), |
111 | QEDE_PF_STAT(tx_64_byte_packets), |
112 | QEDE_PF_STAT(tx_65_to_127_byte_packets), |
113 | QEDE_PF_STAT(tx_128_to_255_byte_packets), |
114 | QEDE_PF_STAT(tx_256_to_511_byte_packets), |
115 | QEDE_PF_STAT(tx_512_to_1023_byte_packets), |
116 | QEDE_PF_STAT(tx_1024_to_1518_byte_packets), |
117 | QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets), |
118 | QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets), |
119 | QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets), |
120 | QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets), |
121 | QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets), |
122 | QEDE_PF_STAT(rx_mac_crtl_frames), |
123 | QEDE_PF_STAT(tx_mac_ctrl_frames), |
124 | QEDE_PF_STAT(rx_pause_frames), |
125 | QEDE_PF_STAT(tx_pause_frames), |
126 | QEDE_PF_STAT(rx_pfc_frames), |
127 | QEDE_PF_STAT(tx_pfc_frames), |
128 | |
129 | QEDE_PF_STAT(rx_crc_errors), |
130 | QEDE_PF_STAT(rx_align_errors), |
131 | QEDE_PF_STAT(rx_carrier_errors), |
132 | QEDE_PF_STAT(rx_oversize_packets), |
133 | QEDE_PF_STAT(rx_jabbers), |
134 | QEDE_PF_STAT(rx_undersize_packets), |
135 | QEDE_PF_STAT(rx_fragments), |
136 | QEDE_PF_BB_STAT(tx_lpi_entry_count), |
137 | QEDE_PF_BB_STAT(tx_total_collisions), |
138 | QEDE_PF_STAT(brb_truncates), |
139 | QEDE_PF_STAT(brb_discards), |
140 | QEDE_STAT(no_buff_discards), |
141 | QEDE_PF_STAT(mftag_filter_discards), |
142 | QEDE_PF_STAT(mac_filter_discards), |
143 | QEDE_PF_STAT(gft_filter_drop), |
144 | QEDE_STAT(tx_err_drop_pkts), |
145 | QEDE_STAT(ttl0_discard), |
146 | QEDE_STAT(packet_too_big_discard), |
147 | |
148 | QEDE_STAT(coalesced_pkts), |
149 | QEDE_STAT(coalesced_events), |
150 | QEDE_STAT(coalesced_aborts_num), |
151 | QEDE_STAT(non_coalesced_pkts), |
152 | QEDE_STAT(coalesced_bytes), |
153 | |
154 | QEDE_STAT(link_change_count), |
155 | QEDE_STAT(ptp_skip_txts), |
156 | }; |
157 | |
158 | #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) |
159 | #define QEDE_STAT_IS_PF_ONLY(i) \ |
160 | test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr) |
161 | #define QEDE_STAT_IS_BB_ONLY(i) \ |
162 | test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr) |
163 | #define QEDE_STAT_IS_AH_ONLY(i) \ |
164 | test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr) |
165 | |
166 | enum { |
167 | QEDE_PRI_FLAG_CMT, |
168 | QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */ |
169 | QEDE_PRI_FLAG_RECOVER_ON_ERROR, |
170 | QEDE_PRI_FLAG_ESL_SUPPORT, /* MFW supports Enhanced System Lockdown */ |
171 | QEDE_PRI_FLAG_ESL_ACTIVE, /* Enhanced System Lockdown Active status */ |
172 | QEDE_PRI_FLAG_LEN, |
173 | }; |
174 | |
175 | static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { |
176 | "Coupled-Function" , |
177 | "SmartAN capable" , |
178 | "Recover on error" , |
179 | "ESL capable" , |
180 | "ESL active" , |
181 | }; |
182 | |
183 | enum qede_ethtool_tests { |
184 | QEDE_ETHTOOL_INT_LOOPBACK, |
185 | QEDE_ETHTOOL_INTERRUPT_TEST, |
186 | QEDE_ETHTOOL_MEMORY_TEST, |
187 | QEDE_ETHTOOL_REGISTER_TEST, |
188 | QEDE_ETHTOOL_CLOCK_TEST, |
189 | QEDE_ETHTOOL_NVRAM_TEST, |
190 | QEDE_ETHTOOL_TEST_MAX |
191 | }; |
192 | |
193 | static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { |
194 | "Internal loopback (offline)" , |
195 | "Interrupt (online)\t" , |
196 | "Memory (online)\t\t" , |
197 | "Register (online)\t" , |
198 | "Clock (online)\t\t" , |
199 | "Nvram (online)\t\t" , |
200 | }; |
201 | |
202 | /* Forced speed capabilities maps */ |
203 | |
204 | static const u32 qede_forced_speed_1000[] __initconst = { |
205 | ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
206 | ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, |
207 | ETHTOOL_LINK_MODE_1000baseX_Full_BIT, |
208 | }; |
209 | |
210 | static const u32 qede_forced_speed_10000[] __initconst = { |
211 | ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
212 | ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, |
213 | ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, |
214 | ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, |
215 | ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, |
216 | ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, |
217 | ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, |
218 | ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, |
219 | }; |
220 | |
221 | static const u32 qede_forced_speed_20000[] __initconst = { |
222 | ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT, |
223 | }; |
224 | |
225 | static const u32 qede_forced_speed_25000[] __initconst = { |
226 | ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, |
227 | ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, |
228 | ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, |
229 | }; |
230 | |
231 | static const u32 qede_forced_speed_40000[] __initconst = { |
232 | ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, |
233 | ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, |
234 | ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, |
235 | ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, |
236 | }; |
237 | |
238 | static const u32 qede_forced_speed_50000[] __initconst = { |
239 | ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, |
240 | ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, |
241 | ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, |
242 | }; |
243 | |
244 | static const u32 qede_forced_speed_100000[] __initconst = { |
245 | ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, |
246 | ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, |
247 | ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, |
248 | ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, |
249 | }; |
250 | |
251 | static struct ethtool_forced_speed_map |
252 | qede_forced_speed_maps[] __ro_after_init = { |
253 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 1000), |
254 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 10000), |
255 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 20000), |
256 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 25000), |
257 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 40000), |
258 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 50000), |
259 | ETHTOOL_FORCED_SPEED_MAP(qede_forced_speed, 100000), |
260 | }; |
261 | |
262 | void __init qede_forced_speed_maps_init(void) |
263 | { |
264 | ethtool_forced_speed_maps_init(maps: qede_forced_speed_maps, |
265 | ARRAY_SIZE(qede_forced_speed_maps)); |
266 | } |
267 | |
268 | /* Ethtool callbacks */ |
269 | |
270 | static void qede_get_strings_stats_txq(struct qede_dev *edev, |
271 | struct qede_tx_queue *txq, u8 **buf) |
272 | { |
273 | int i; |
274 | |
275 | for (i = 0; i < QEDE_NUM_TQSTATS; i++) { |
276 | if (txq->is_xdp) |
277 | sprintf(buf: *buf, fmt: "%d [XDP]: %s" , |
278 | QEDE_TXQ_XDP_TO_IDX(edev, txq), |
279 | qede_tqstats_arr[i].string); |
280 | else |
281 | sprintf(buf: *buf, fmt: "%d_%d: %s" , txq->index, txq->cos, |
282 | qede_tqstats_arr[i].string); |
283 | *buf += ETH_GSTRING_LEN; |
284 | } |
285 | } |
286 | |
287 | static void qede_get_strings_stats_rxq(struct qede_dev *edev, |
288 | struct qede_rx_queue *rxq, u8 **buf) |
289 | { |
290 | int i; |
291 | |
292 | for (i = 0; i < QEDE_NUM_RQSTATS; i++) { |
293 | sprintf(buf: *buf, fmt: "%d: %s" , rxq->rxq_id, |
294 | qede_rqstats_arr[i].string); |
295 | *buf += ETH_GSTRING_LEN; |
296 | } |
297 | } |
298 | |
299 | static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index) |
300 | { |
301 | return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) || |
302 | (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) || |
303 | (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index)); |
304 | } |
305 | |
306 | static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) |
307 | { |
308 | struct qede_fastpath *fp; |
309 | int i; |
310 | |
311 | /* Account for queue statistics */ |
312 | for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { |
313 | fp = &edev->fp_array[i]; |
314 | |
315 | if (fp->type & QEDE_FASTPATH_RX) |
316 | qede_get_strings_stats_rxq(edev, rxq: fp->rxq, buf: &buf); |
317 | |
318 | if (fp->type & QEDE_FASTPATH_XDP) |
319 | qede_get_strings_stats_txq(edev, txq: fp->xdp_tx, buf: &buf); |
320 | |
321 | if (fp->type & QEDE_FASTPATH_TX) { |
322 | int cos; |
323 | |
324 | for_each_cos_in_txq(edev, cos) |
325 | qede_get_strings_stats_txq(edev, |
326 | txq: &fp->txq[cos], buf: &buf); |
327 | } |
328 | } |
329 | |
330 | /* Account for non-queue statistics */ |
331 | for (i = 0; i < QEDE_NUM_STATS; i++) { |
332 | if (qede_is_irrelevant_stat(edev, stat_index: i)) |
333 | continue; |
334 | strcpy(p: buf, q: qede_stats_arr[i].string); |
335 | buf += ETH_GSTRING_LEN; |
336 | } |
337 | } |
338 | |
339 | static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) |
340 | { |
341 | struct qede_dev *edev = netdev_priv(dev); |
342 | |
343 | switch (stringset) { |
344 | case ETH_SS_STATS: |
345 | qede_get_strings_stats(edev, buf); |
346 | break; |
347 | case ETH_SS_PRIV_FLAGS: |
348 | memcpy(buf, qede_private_arr, |
349 | ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); |
350 | break; |
351 | case ETH_SS_TEST: |
352 | memcpy(buf, qede_tests_str_arr, |
353 | ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); |
354 | break; |
355 | default: |
356 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
357 | "Unsupported stringset 0x%08x\n" , stringset); |
358 | } |
359 | } |
360 | |
361 | static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) |
362 | { |
363 | int i; |
364 | |
365 | for (i = 0; i < QEDE_NUM_TQSTATS; i++) { |
366 | **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); |
367 | (*buf)++; |
368 | } |
369 | } |
370 | |
371 | static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) |
372 | { |
373 | int i; |
374 | |
375 | for (i = 0; i < QEDE_NUM_RQSTATS; i++) { |
376 | **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); |
377 | (*buf)++; |
378 | } |
379 | } |
380 | |
381 | static void qede_get_ethtool_stats(struct net_device *dev, |
382 | struct ethtool_stats *stats, u64 *buf) |
383 | { |
384 | struct qede_dev *edev = netdev_priv(dev); |
385 | struct qede_fastpath *fp; |
386 | int i; |
387 | |
388 | qede_fill_by_demand_stats(edev); |
389 | |
390 | /* Need to protect the access to the fastpath array */ |
391 | __qede_lock(edev); |
392 | |
393 | for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { |
394 | fp = &edev->fp_array[i]; |
395 | |
396 | if (fp->type & QEDE_FASTPATH_RX) |
397 | qede_get_ethtool_stats_rxq(rxq: fp->rxq, buf: &buf); |
398 | |
399 | if (fp->type & QEDE_FASTPATH_XDP) |
400 | qede_get_ethtool_stats_txq(txq: fp->xdp_tx, buf: &buf); |
401 | |
402 | if (fp->type & QEDE_FASTPATH_TX) { |
403 | int cos; |
404 | |
405 | for_each_cos_in_txq(edev, cos) |
406 | qede_get_ethtool_stats_txq(txq: &fp->txq[cos], buf: &buf); |
407 | } |
408 | } |
409 | |
410 | spin_lock(lock: &edev->stats_lock); |
411 | |
412 | for (i = 0; i < QEDE_NUM_STATS; i++) { |
413 | if (qede_is_irrelevant_stat(edev, stat_index: i)) |
414 | continue; |
415 | *buf = *((u64 *)(((void *)&edev->stats) + |
416 | qede_stats_arr[i].offset)); |
417 | |
418 | buf++; |
419 | } |
420 | |
421 | spin_unlock(lock: &edev->stats_lock); |
422 | |
423 | __qede_unlock(edev); |
424 | } |
425 | |
426 | static int qede_get_sset_count(struct net_device *dev, int stringset) |
427 | { |
428 | struct qede_dev *edev = netdev_priv(dev); |
429 | int num_stats = QEDE_NUM_STATS, i; |
430 | |
431 | switch (stringset) { |
432 | case ETH_SS_STATS: |
433 | for (i = 0; i < QEDE_NUM_STATS; i++) |
434 | if (qede_is_irrelevant_stat(edev, stat_index: i)) |
435 | num_stats--; |
436 | |
437 | /* Account for the Regular Tx statistics */ |
438 | num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * |
439 | edev->dev_info.num_tc; |
440 | |
441 | /* Account for the Regular Rx statistics */ |
442 | num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; |
443 | |
444 | /* Account for XDP statistics [if needed] */ |
445 | if (edev->xdp_prog) |
446 | num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; |
447 | return num_stats; |
448 | |
449 | case ETH_SS_PRIV_FLAGS: |
450 | return QEDE_PRI_FLAG_LEN; |
451 | case ETH_SS_TEST: |
452 | if (!IS_VF(edev)) |
453 | return QEDE_ETHTOOL_TEST_MAX; |
454 | else |
455 | return 0; |
456 | default: |
457 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
458 | "Unsupported stringset 0x%08x\n" , stringset); |
459 | return -EINVAL; |
460 | } |
461 | } |
462 | |
463 | static u32 qede_get_priv_flags(struct net_device *dev) |
464 | { |
465 | struct qede_dev *edev = netdev_priv(dev); |
466 | bool esl_active; |
467 | u32 flags = 0; |
468 | |
469 | if (edev->dev_info.common.num_hwfns > 1) |
470 | flags |= BIT(QEDE_PRI_FLAG_CMT); |
471 | |
472 | if (edev->dev_info.common.smart_an) |
473 | flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT); |
474 | |
475 | if (edev->err_flags & BIT(QEDE_ERR_IS_RECOVERABLE)) |
476 | flags |= BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR); |
477 | |
478 | if (edev->dev_info.common.esl) |
479 | flags |= BIT(QEDE_PRI_FLAG_ESL_SUPPORT); |
480 | |
481 | edev->ops->common->get_esl_status(edev->cdev, &esl_active); |
482 | |
483 | if (esl_active) |
484 | flags |= BIT(QEDE_PRI_FLAG_ESL_ACTIVE); |
485 | |
486 | return flags; |
487 | } |
488 | |
489 | static int qede_set_priv_flags(struct net_device *dev, u32 flags) |
490 | { |
491 | struct qede_dev *edev = netdev_priv(dev); |
492 | u32 cflags = qede_get_priv_flags(dev); |
493 | u32 dflags = flags ^ cflags; |
494 | |
495 | /* can only change RECOVER_ON_ERROR flag */ |
496 | if (dflags & ~BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR)) |
497 | return -EINVAL; |
498 | |
499 | if (flags & BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR)) |
500 | set_bit(QEDE_ERR_IS_RECOVERABLE, addr: &edev->err_flags); |
501 | else |
502 | clear_bit(QEDE_ERR_IS_RECOVERABLE, addr: &edev->err_flags); |
503 | |
504 | return 0; |
505 | } |
506 | |
507 | static int qede_get_link_ksettings(struct net_device *dev, |
508 | struct ethtool_link_ksettings *cmd) |
509 | { |
510 | typeof(cmd->link_modes) *link_modes = &cmd->link_modes; |
511 | struct ethtool_link_settings *base = &cmd->base; |
512 | struct qede_dev *edev = netdev_priv(dev); |
513 | struct qed_link_output current_link; |
514 | |
515 | __qede_lock(edev); |
516 | |
517 | memset(¤t_link, 0, sizeof(current_link)); |
518 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
519 | |
520 | linkmode_copy(dst: link_modes->supported, src: current_link.supported_caps); |
521 | linkmode_copy(dst: link_modes->advertising, src: current_link.advertised_caps); |
522 | linkmode_copy(dst: link_modes->lp_advertising, src: current_link.lp_caps); |
523 | |
524 | if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { |
525 | base->speed = current_link.speed; |
526 | base->duplex = current_link.duplex; |
527 | } else { |
528 | base->speed = SPEED_UNKNOWN; |
529 | base->duplex = DUPLEX_UNKNOWN; |
530 | } |
531 | |
532 | __qede_unlock(edev); |
533 | |
534 | base->port = current_link.port; |
535 | base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : |
536 | AUTONEG_DISABLE; |
537 | |
538 | return 0; |
539 | } |
540 | |
541 | static int qede_set_link_ksettings(struct net_device *dev, |
542 | const struct ethtool_link_ksettings *cmd) |
543 | { |
544 | const struct ethtool_link_settings *base = &cmd->base; |
545 | const struct ethtool_forced_speed_map *map; |
546 | struct qede_dev *edev = netdev_priv(dev); |
547 | struct qed_link_output current_link; |
548 | struct qed_link_params params; |
549 | u32 i; |
550 | |
551 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
552 | DP_INFO(edev, "Link settings are not allowed to be changed\n" ); |
553 | return -EOPNOTSUPP; |
554 | } |
555 | memset(¤t_link, 0, sizeof(current_link)); |
556 | memset(¶ms, 0, sizeof(params)); |
557 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
558 | |
559 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; |
560 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; |
561 | |
562 | if (base->autoneg == AUTONEG_ENABLE) { |
563 | if (!phylink_test(current_link.supported_caps, Autoneg)) { |
564 | DP_INFO(edev, "Auto negotiation is not supported\n" ); |
565 | return -EOPNOTSUPP; |
566 | } |
567 | |
568 | params.autoneg = true; |
569 | params.forced_speed = 0; |
570 | |
571 | linkmode_copy(dst: params.adv_speeds, src: cmd->link_modes.advertising); |
572 | } else { /* forced speed */ |
573 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; |
574 | params.autoneg = false; |
575 | params.forced_speed = base->speed; |
576 | |
577 | for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) { |
578 | map = qede_forced_speed_maps + i; |
579 | |
580 | if (base->speed != map->speed || |
581 | !linkmode_intersects(src1: current_link.supported_caps, |
582 | src2: map->caps)) |
583 | continue; |
584 | |
585 | linkmode_and(dst: params.adv_speeds, |
586 | a: current_link.supported_caps, b: map->caps); |
587 | goto set_link; |
588 | } |
589 | |
590 | DP_INFO(edev, "Unsupported speed %u\n" , base->speed); |
591 | return -EINVAL; |
592 | } |
593 | |
594 | set_link: |
595 | params.link_up = true; |
596 | edev->ops->common->set_link(edev->cdev, ¶ms); |
597 | |
598 | return 0; |
599 | } |
600 | |
601 | static void qede_get_drvinfo(struct net_device *ndev, |
602 | struct ethtool_drvinfo *info) |
603 | { |
604 | char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; |
605 | struct qede_dev *edev = netdev_priv(dev: ndev); |
606 | char mbi[ETHTOOL_FWVERS_LEN]; |
607 | |
608 | strscpy(info->driver, "qede" , sizeof(info->driver)); |
609 | |
610 | snprintf(buf: storm, ETHTOOL_FWVERS_LEN, fmt: "%d.%d.%d.%d" , |
611 | edev->dev_info.common.fw_major, |
612 | edev->dev_info.common.fw_minor, |
613 | edev->dev_info.common.fw_rev, |
614 | edev->dev_info.common.fw_eng); |
615 | |
616 | snprintf(buf: mfw, ETHTOOL_FWVERS_LEN, fmt: "%d.%d.%d.%d" , |
617 | (edev->dev_info.common.mfw_rev >> 24) & 0xFF, |
618 | (edev->dev_info.common.mfw_rev >> 16) & 0xFF, |
619 | (edev->dev_info.common.mfw_rev >> 8) & 0xFF, |
620 | edev->dev_info.common.mfw_rev & 0xFF); |
621 | |
622 | if ((strlen(storm) + strlen("[storm]" )) < |
623 | sizeof(info->version)) |
624 | snprintf(buf: info->version, size: sizeof(info->version), |
625 | fmt: "[storm %s]" , storm); |
626 | else |
627 | snprintf(buf: info->version, size: sizeof(info->version), |
628 | fmt: "%s" , storm); |
629 | |
630 | if (edev->dev_info.common.mbi_version) { |
631 | snprintf(buf: mbi, ETHTOOL_FWVERS_LEN, fmt: "%d.%d.%d" , |
632 | (edev->dev_info.common.mbi_version & |
633 | QED_MBI_VERSION_2_MASK) >> QED_MBI_VERSION_2_OFFSET, |
634 | (edev->dev_info.common.mbi_version & |
635 | QED_MBI_VERSION_1_MASK) >> QED_MBI_VERSION_1_OFFSET, |
636 | (edev->dev_info.common.mbi_version & |
637 | QED_MBI_VERSION_0_MASK) >> QED_MBI_VERSION_0_OFFSET); |
638 | snprintf(buf: info->fw_version, size: sizeof(info->fw_version), |
639 | fmt: "mbi %s [mfw %s]" , mbi, mfw); |
640 | } else { |
641 | snprintf(buf: info->fw_version, size: sizeof(info->fw_version), |
642 | fmt: "mfw %s" , mfw); |
643 | } |
644 | |
645 | strscpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); |
646 | } |
647 | |
648 | static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) |
649 | { |
650 | struct qede_dev *edev = netdev_priv(dev: ndev); |
651 | |
652 | if (edev->dev_info.common.wol_support) { |
653 | wol->supported = WAKE_MAGIC; |
654 | wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; |
655 | } |
656 | } |
657 | |
658 | static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) |
659 | { |
660 | struct qede_dev *edev = netdev_priv(dev: ndev); |
661 | bool wol_requested; |
662 | int rc; |
663 | |
664 | if (wol->wolopts & ~WAKE_MAGIC) { |
665 | DP_INFO(edev, |
666 | "Can't support WoL options other than magic-packet\n" ); |
667 | return -EINVAL; |
668 | } |
669 | |
670 | wol_requested = !!(wol->wolopts & WAKE_MAGIC); |
671 | if (wol_requested == edev->wol_enabled) |
672 | return 0; |
673 | |
674 | /* Need to actually change configuration */ |
675 | if (!edev->dev_info.common.wol_support) { |
676 | DP_INFO(edev, "Device doesn't support WoL\n" ); |
677 | return -EINVAL; |
678 | } |
679 | |
680 | rc = edev->ops->common->update_wol(edev->cdev, wol_requested); |
681 | if (!rc) |
682 | edev->wol_enabled = wol_requested; |
683 | |
684 | return rc; |
685 | } |
686 | |
687 | static u32 qede_get_msglevel(struct net_device *ndev) |
688 | { |
689 | struct qede_dev *edev = netdev_priv(dev: ndev); |
690 | |
691 | return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; |
692 | } |
693 | |
694 | static void qede_set_msglevel(struct net_device *ndev, u32 level) |
695 | { |
696 | struct qede_dev *edev = netdev_priv(dev: ndev); |
697 | u32 dp_module = 0; |
698 | u8 dp_level = 0; |
699 | |
700 | qede_config_debug(debug: level, p_dp_module: &dp_module, p_dp_level: &dp_level); |
701 | |
702 | edev->dp_level = dp_level; |
703 | edev->dp_module = dp_module; |
704 | edev->ops->common->update_msglvl(edev->cdev, |
705 | dp_module, dp_level); |
706 | } |
707 | |
708 | static int qede_nway_reset(struct net_device *dev) |
709 | { |
710 | struct qede_dev *edev = netdev_priv(dev); |
711 | struct qed_link_output current_link; |
712 | struct qed_link_params link_params; |
713 | |
714 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
715 | DP_INFO(edev, "Link settings are not allowed to be changed\n" ); |
716 | return -EOPNOTSUPP; |
717 | } |
718 | |
719 | if (!netif_running(dev)) |
720 | return 0; |
721 | |
722 | memset(¤t_link, 0, sizeof(current_link)); |
723 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
724 | if (!current_link.link_up) |
725 | return 0; |
726 | |
727 | /* Toggle the link */ |
728 | memset(&link_params, 0, sizeof(link_params)); |
729 | link_params.link_up = false; |
730 | edev->ops->common->set_link(edev->cdev, &link_params); |
731 | link_params.link_up = true; |
732 | edev->ops->common->set_link(edev->cdev, &link_params); |
733 | |
734 | return 0; |
735 | } |
736 | |
737 | static u32 qede_get_link(struct net_device *dev) |
738 | { |
739 | struct qede_dev *edev = netdev_priv(dev); |
740 | struct qed_link_output current_link; |
741 | |
742 | memset(¤t_link, 0, sizeof(current_link)); |
743 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
744 | |
745 | return current_link.link_up; |
746 | } |
747 | |
748 | static int qede_flash_device(struct net_device *dev, |
749 | struct ethtool_flash *flash) |
750 | { |
751 | struct qede_dev *edev = netdev_priv(dev); |
752 | |
753 | return edev->ops->common->nvm_flash(edev->cdev, flash->data); |
754 | } |
755 | |
756 | static int qede_get_coalesce(struct net_device *dev, |
757 | struct ethtool_coalesce *coal, |
758 | struct kernel_ethtool_coalesce *kernel_coal, |
759 | struct netlink_ext_ack *extack) |
760 | { |
761 | void *rx_handle = NULL, *tx_handle = NULL; |
762 | struct qede_dev *edev = netdev_priv(dev); |
763 | u16 rx_coal, tx_coal, i, rc = 0; |
764 | struct qede_fastpath *fp; |
765 | |
766 | rx_coal = QED_DEFAULT_RX_USECS; |
767 | tx_coal = QED_DEFAULT_TX_USECS; |
768 | |
769 | memset(coal, 0, sizeof(struct ethtool_coalesce)); |
770 | |
771 | __qede_lock(edev); |
772 | if (edev->state == QEDE_STATE_OPEN) { |
773 | for_each_queue(i) { |
774 | fp = &edev->fp_array[i]; |
775 | |
776 | if (fp->type & QEDE_FASTPATH_RX) { |
777 | rx_handle = fp->rxq->handle; |
778 | break; |
779 | } |
780 | } |
781 | |
782 | rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle); |
783 | if (rc) { |
784 | DP_INFO(edev, "Read Rx coalesce error\n" ); |
785 | goto out; |
786 | } |
787 | |
788 | for_each_queue(i) { |
789 | struct qede_tx_queue *txq; |
790 | |
791 | fp = &edev->fp_array[i]; |
792 | |
793 | /* All TX queues of given fastpath uses same |
794 | * coalescing value, so no need to iterate over |
795 | * all TCs, TC0 txq should suffice. |
796 | */ |
797 | if (fp->type & QEDE_FASTPATH_TX) { |
798 | txq = QEDE_FP_TC0_TXQ(fp); |
799 | tx_handle = txq->handle; |
800 | break; |
801 | } |
802 | } |
803 | |
804 | rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle); |
805 | if (rc) |
806 | DP_INFO(edev, "Read Tx coalesce error\n" ); |
807 | } |
808 | |
809 | out: |
810 | __qede_unlock(edev); |
811 | |
812 | coal->rx_coalesce_usecs = rx_coal; |
813 | coal->tx_coalesce_usecs = tx_coal; |
814 | coal->stats_block_coalesce_usecs = edev->stats_coal_usecs; |
815 | |
816 | return rc; |
817 | } |
818 | |
819 | int qede_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal, |
820 | struct kernel_ethtool_coalesce *kernel_coal, |
821 | struct netlink_ext_ack *extack) |
822 | { |
823 | struct qede_dev *edev = netdev_priv(dev); |
824 | struct qede_fastpath *fp; |
825 | int i, rc = 0; |
826 | u16 rxc, txc; |
827 | |
828 | if (edev->stats_coal_usecs != coal->stats_block_coalesce_usecs) { |
829 | edev->stats_coal_usecs = coal->stats_block_coalesce_usecs; |
830 | if (edev->stats_coal_usecs) { |
831 | edev->stats_coal_ticks = usecs_to_jiffies(u: edev->stats_coal_usecs); |
832 | schedule_delayed_work(dwork: &edev->periodic_task, delay: 0); |
833 | |
834 | DP_INFO(edev, "Configured stats coal ticks=%lu jiffies\n" , |
835 | edev->stats_coal_ticks); |
836 | } else { |
837 | cancel_delayed_work_sync(dwork: &edev->periodic_task); |
838 | } |
839 | } |
840 | |
841 | if (!netif_running(dev)) { |
842 | DP_INFO(edev, "Interface is down\n" ); |
843 | return -EINVAL; |
844 | } |
845 | |
846 | if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || |
847 | coal->tx_coalesce_usecs > QED_COALESCE_MAX) { |
848 | DP_INFO(edev, |
849 | "Can't support requested %s coalesce value [max supported value %d]\n" , |
850 | coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" : |
851 | "tx" , QED_COALESCE_MAX); |
852 | return -EINVAL; |
853 | } |
854 | |
855 | rxc = (u16)coal->rx_coalesce_usecs; |
856 | txc = (u16)coal->tx_coalesce_usecs; |
857 | for_each_queue(i) { |
858 | fp = &edev->fp_array[i]; |
859 | |
860 | if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { |
861 | rc = edev->ops->common->set_coalesce(edev->cdev, |
862 | rxc, 0, |
863 | fp->rxq->handle); |
864 | if (rc) { |
865 | DP_INFO(edev, |
866 | "Set RX coalesce error, rc = %d\n" , rc); |
867 | return rc; |
868 | } |
869 | edev->coal_entry[i].rxc = rxc; |
870 | edev->coal_entry[i].isvalid = true; |
871 | } |
872 | |
873 | if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { |
874 | struct qede_tx_queue *txq; |
875 | |
876 | /* All TX queues of given fastpath uses same |
877 | * coalescing value, so no need to iterate over |
878 | * all TCs, TC0 txq should suffice. |
879 | */ |
880 | txq = QEDE_FP_TC0_TXQ(fp); |
881 | |
882 | rc = edev->ops->common->set_coalesce(edev->cdev, |
883 | 0, txc, |
884 | txq->handle); |
885 | if (rc) { |
886 | DP_INFO(edev, |
887 | "Set TX coalesce error, rc = %d\n" , rc); |
888 | return rc; |
889 | } |
890 | edev->coal_entry[i].txc = txc; |
891 | edev->coal_entry[i].isvalid = true; |
892 | } |
893 | } |
894 | |
895 | return rc; |
896 | } |
897 | |
898 | static void qede_get_ringparam(struct net_device *dev, |
899 | struct ethtool_ringparam *ering, |
900 | struct kernel_ethtool_ringparam *kernel_ering, |
901 | struct netlink_ext_ack *extack) |
902 | { |
903 | struct qede_dev *edev = netdev_priv(dev); |
904 | |
905 | ering->rx_max_pending = NUM_RX_BDS_MAX; |
906 | ering->rx_pending = edev->q_num_rx_buffers; |
907 | ering->tx_max_pending = NUM_TX_BDS_MAX; |
908 | ering->tx_pending = edev->q_num_tx_buffers; |
909 | } |
910 | |
911 | static int qede_set_ringparam(struct net_device *dev, |
912 | struct ethtool_ringparam *ering, |
913 | struct kernel_ethtool_ringparam *kernel_ering, |
914 | struct netlink_ext_ack *extack) |
915 | { |
916 | struct qede_dev *edev = netdev_priv(dev); |
917 | |
918 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
919 | "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n" , |
920 | ering->rx_pending, ering->tx_pending); |
921 | |
922 | /* Validate legality of configuration */ |
923 | if (ering->rx_pending > NUM_RX_BDS_MAX || |
924 | ering->rx_pending < NUM_RX_BDS_MIN || |
925 | ering->tx_pending > NUM_TX_BDS_MAX || |
926 | ering->tx_pending < NUM_TX_BDS_MIN) { |
927 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
928 | "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n" , |
929 | NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, |
930 | NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); |
931 | return -EINVAL; |
932 | } |
933 | |
934 | /* Change ring size and re-load */ |
935 | edev->q_num_rx_buffers = ering->rx_pending; |
936 | edev->q_num_tx_buffers = ering->tx_pending; |
937 | |
938 | qede_reload(edev, NULL, is_locked: false); |
939 | |
940 | return 0; |
941 | } |
942 | |
943 | static void qede_get_pauseparam(struct net_device *dev, |
944 | struct ethtool_pauseparam *epause) |
945 | { |
946 | struct qede_dev *edev = netdev_priv(dev); |
947 | struct qed_link_output current_link; |
948 | |
949 | memset(¤t_link, 0, sizeof(current_link)); |
950 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
951 | |
952 | if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) |
953 | epause->autoneg = true; |
954 | if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) |
955 | epause->rx_pause = true; |
956 | if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) |
957 | epause->tx_pause = true; |
958 | |
959 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
960 | "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n" , |
961 | epause->cmd, epause->autoneg, epause->rx_pause, |
962 | epause->tx_pause); |
963 | } |
964 | |
965 | static int qede_set_pauseparam(struct net_device *dev, |
966 | struct ethtool_pauseparam *epause) |
967 | { |
968 | struct qede_dev *edev = netdev_priv(dev); |
969 | struct qed_link_params params; |
970 | struct qed_link_output current_link; |
971 | |
972 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
973 | DP_INFO(edev, |
974 | "Pause settings are not allowed to be changed\n" ); |
975 | return -EOPNOTSUPP; |
976 | } |
977 | |
978 | memset(¤t_link, 0, sizeof(current_link)); |
979 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
980 | |
981 | memset(¶ms, 0, sizeof(params)); |
982 | params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; |
983 | |
984 | if (epause->autoneg) { |
985 | if (!phylink_test(current_link.supported_caps, Autoneg)) { |
986 | DP_INFO(edev, "autoneg not supported\n" ); |
987 | return -EINVAL; |
988 | } |
989 | |
990 | params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; |
991 | } |
992 | |
993 | if (epause->rx_pause) |
994 | params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; |
995 | if (epause->tx_pause) |
996 | params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; |
997 | |
998 | params.link_up = true; |
999 | edev->ops->common->set_link(edev->cdev, ¶ms); |
1000 | |
1001 | return 0; |
1002 | } |
1003 | |
1004 | static void qede_get_regs(struct net_device *ndev, |
1005 | struct ethtool_regs *regs, void *buffer) |
1006 | { |
1007 | struct qede_dev *edev = netdev_priv(dev: ndev); |
1008 | |
1009 | regs->version = 0; |
1010 | memset(buffer, 0, regs->len); |
1011 | |
1012 | if (edev->ops && edev->ops->common) |
1013 | edev->ops->common->dbg_all_data(edev->cdev, buffer); |
1014 | } |
1015 | |
1016 | static int qede_get_regs_len(struct net_device *ndev) |
1017 | { |
1018 | struct qede_dev *edev = netdev_priv(dev: ndev); |
1019 | |
1020 | if (edev->ops && edev->ops->common) |
1021 | return edev->ops->common->dbg_all_data_size(edev->cdev); |
1022 | else |
1023 | return -EINVAL; |
1024 | } |
1025 | |
1026 | static void qede_update_mtu(struct qede_dev *edev, |
1027 | struct qede_reload_args *args) |
1028 | { |
1029 | edev->ndev->mtu = args->u.mtu; |
1030 | } |
1031 | |
1032 | /* Netdevice NDOs */ |
1033 | int qede_change_mtu(struct net_device *ndev, int new_mtu) |
1034 | { |
1035 | struct qede_dev *edev = netdev_priv(dev: ndev); |
1036 | struct qede_reload_args args; |
1037 | |
1038 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1039 | "Configuring MTU size of %d\n" , new_mtu); |
1040 | |
1041 | if (new_mtu > PAGE_SIZE) |
1042 | ndev->features &= ~NETIF_F_GRO_HW; |
1043 | |
1044 | /* Set the mtu field and re-start the interface if needed */ |
1045 | args.u.mtu = new_mtu; |
1046 | args.func = &qede_update_mtu; |
1047 | qede_reload(edev, args: &args, is_locked: false); |
1048 | #if IS_ENABLED(CONFIG_QED_RDMA) |
1049 | qede_rdma_event_change_mtu(edev); |
1050 | #endif |
1051 | edev->ops->common->update_mtu(edev->cdev, new_mtu); |
1052 | |
1053 | return 0; |
1054 | } |
1055 | |
1056 | static void qede_get_channels(struct net_device *dev, |
1057 | struct ethtool_channels *channels) |
1058 | { |
1059 | struct qede_dev *edev = netdev_priv(dev); |
1060 | |
1061 | channels->max_combined = QEDE_MAX_RSS_CNT(edev); |
1062 | channels->max_rx = QEDE_MAX_RSS_CNT(edev); |
1063 | channels->max_tx = QEDE_MAX_RSS_CNT(edev); |
1064 | channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - |
1065 | edev->fp_num_rx; |
1066 | channels->tx_count = edev->fp_num_tx; |
1067 | channels->rx_count = edev->fp_num_rx; |
1068 | } |
1069 | |
1070 | static int qede_set_channels(struct net_device *dev, |
1071 | struct ethtool_channels *channels) |
1072 | { |
1073 | struct qede_dev *edev = netdev_priv(dev); |
1074 | u32 count; |
1075 | |
1076 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1077 | "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n" , |
1078 | channels->rx_count, channels->tx_count, |
1079 | channels->other_count, channels->combined_count); |
1080 | |
1081 | count = channels->rx_count + channels->tx_count + |
1082 | channels->combined_count; |
1083 | |
1084 | /* We don't support `other' channels */ |
1085 | if (channels->other_count) { |
1086 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1087 | "command parameters not supported\n" ); |
1088 | return -EINVAL; |
1089 | } |
1090 | |
1091 | if (!(channels->combined_count || (channels->rx_count && |
1092 | channels->tx_count))) { |
1093 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1094 | "need to request at least one transmit and one receive channel\n" ); |
1095 | return -EINVAL; |
1096 | } |
1097 | |
1098 | if (count > QEDE_MAX_RSS_CNT(edev)) { |
1099 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1100 | "requested channels = %d max supported channels = %d\n" , |
1101 | count, QEDE_MAX_RSS_CNT(edev)); |
1102 | return -EINVAL; |
1103 | } |
1104 | |
1105 | /* Check if there was a change in the active parameters */ |
1106 | if ((count == QEDE_QUEUE_CNT(edev)) && |
1107 | (channels->tx_count == edev->fp_num_tx) && |
1108 | (channels->rx_count == edev->fp_num_rx)) { |
1109 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1110 | "No change in active parameters\n" ); |
1111 | return 0; |
1112 | } |
1113 | |
1114 | /* We need the number of queues to be divisible between the hwfns */ |
1115 | if ((count % edev->dev_info.common.num_hwfns) || |
1116 | (channels->tx_count % edev->dev_info.common.num_hwfns) || |
1117 | (channels->rx_count % edev->dev_info.common.num_hwfns)) { |
1118 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1119 | "Number of channels must be divisible by %04x\n" , |
1120 | edev->dev_info.common.num_hwfns); |
1121 | return -EINVAL; |
1122 | } |
1123 | |
1124 | /* Set number of queues and reload if necessary */ |
1125 | edev->req_queues = count; |
1126 | edev->req_num_tx = channels->tx_count; |
1127 | edev->req_num_rx = channels->rx_count; |
1128 | /* Reset the indirection table if rx queue count is updated */ |
1129 | if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { |
1130 | edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; |
1131 | memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); |
1132 | } |
1133 | |
1134 | qede_reload(edev, NULL, is_locked: false); |
1135 | |
1136 | return 0; |
1137 | } |
1138 | |
1139 | static int qede_get_ts_info(struct net_device *dev, |
1140 | struct ethtool_ts_info *info) |
1141 | { |
1142 | struct qede_dev *edev = netdev_priv(dev); |
1143 | |
1144 | return qede_ptp_get_ts_info(edev, ts: info); |
1145 | } |
1146 | |
1147 | static int qede_set_phys_id(struct net_device *dev, |
1148 | enum ethtool_phys_id_state state) |
1149 | { |
1150 | struct qede_dev *edev = netdev_priv(dev); |
1151 | u8 led_state = 0; |
1152 | |
1153 | switch (state) { |
1154 | case ETHTOOL_ID_ACTIVE: |
1155 | return 1; /* cycle on/off once per second */ |
1156 | |
1157 | case ETHTOOL_ID_ON: |
1158 | led_state = QED_LED_MODE_ON; |
1159 | break; |
1160 | |
1161 | case ETHTOOL_ID_OFF: |
1162 | led_state = QED_LED_MODE_OFF; |
1163 | break; |
1164 | |
1165 | case ETHTOOL_ID_INACTIVE: |
1166 | led_state = QED_LED_MODE_RESTORE; |
1167 | break; |
1168 | } |
1169 | |
1170 | edev->ops->common->set_led(edev->cdev, led_state); |
1171 | |
1172 | return 0; |
1173 | } |
1174 | |
1175 | static int (struct qede_dev *edev, struct ethtool_rxnfc *info) |
1176 | { |
1177 | info->data = RXH_IP_SRC | RXH_IP_DST; |
1178 | |
1179 | switch (info->flow_type) { |
1180 | case TCP_V4_FLOW: |
1181 | case TCP_V6_FLOW: |
1182 | info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
1183 | break; |
1184 | case UDP_V4_FLOW: |
1185 | if (edev->rss_caps & QED_RSS_IPV4_UDP) |
1186 | info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
1187 | break; |
1188 | case UDP_V6_FLOW: |
1189 | if (edev->rss_caps & QED_RSS_IPV6_UDP) |
1190 | info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
1191 | break; |
1192 | case IPV4_FLOW: |
1193 | case IPV6_FLOW: |
1194 | break; |
1195 | default: |
1196 | info->data = 0; |
1197 | break; |
1198 | } |
1199 | |
1200 | return 0; |
1201 | } |
1202 | |
1203 | static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, |
1204 | u32 *rule_locs) |
1205 | { |
1206 | struct qede_dev *edev = netdev_priv(dev); |
1207 | int rc = 0; |
1208 | |
1209 | switch (info->cmd) { |
1210 | case ETHTOOL_GRXRINGS: |
1211 | info->data = QEDE_RSS_COUNT(edev); |
1212 | break; |
1213 | case ETHTOOL_GRXFH: |
1214 | rc = qede_get_rss_flags(edev, info); |
1215 | break; |
1216 | case ETHTOOL_GRXCLSRLCNT: |
1217 | info->rule_cnt = qede_get_arfs_filter_count(edev); |
1218 | info->data = QEDE_RFS_MAX_FLTR; |
1219 | break; |
1220 | case ETHTOOL_GRXCLSRULE: |
1221 | rc = qede_get_cls_rule_entry(edev, cmd: info); |
1222 | break; |
1223 | case ETHTOOL_GRXCLSRLALL: |
1224 | rc = qede_get_cls_rule_all(edev, info, rule_locs); |
1225 | break; |
1226 | default: |
1227 | DP_ERR(edev, "Command parameters not supported\n" ); |
1228 | rc = -EOPNOTSUPP; |
1229 | } |
1230 | |
1231 | return rc; |
1232 | } |
1233 | |
1234 | static int (struct qede_dev *edev, struct ethtool_rxnfc *info) |
1235 | { |
1236 | struct qed_update_vport_params *vport_update_params; |
1237 | u8 set_caps = 0, clr_caps = 0; |
1238 | int rc = 0; |
1239 | |
1240 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1241 | "Set rss flags command parameters: flow type = %d, data = %llu\n" , |
1242 | info->flow_type, info->data); |
1243 | |
1244 | switch (info->flow_type) { |
1245 | case TCP_V4_FLOW: |
1246 | case TCP_V6_FLOW: |
1247 | /* For TCP only 4-tuple hash is supported */ |
1248 | if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | |
1249 | RXH_L4_B_0_1 | RXH_L4_B_2_3)) { |
1250 | DP_INFO(edev, "Command parameters not supported\n" ); |
1251 | return -EINVAL; |
1252 | } |
1253 | return 0; |
1254 | case UDP_V4_FLOW: |
1255 | /* For UDP either 2-tuple hash or 4-tuple hash is supported */ |
1256 | if (info->data == (RXH_IP_SRC | RXH_IP_DST | |
1257 | RXH_L4_B_0_1 | RXH_L4_B_2_3)) { |
1258 | set_caps = QED_RSS_IPV4_UDP; |
1259 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1260 | "UDP 4-tuple enabled\n" ); |
1261 | } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { |
1262 | clr_caps = QED_RSS_IPV4_UDP; |
1263 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1264 | "UDP 4-tuple disabled\n" ); |
1265 | } else { |
1266 | return -EINVAL; |
1267 | } |
1268 | break; |
1269 | case UDP_V6_FLOW: |
1270 | /* For UDP either 2-tuple hash or 4-tuple hash is supported */ |
1271 | if (info->data == (RXH_IP_SRC | RXH_IP_DST | |
1272 | RXH_L4_B_0_1 | RXH_L4_B_2_3)) { |
1273 | set_caps = QED_RSS_IPV6_UDP; |
1274 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1275 | "UDP 4-tuple enabled\n" ); |
1276 | } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { |
1277 | clr_caps = QED_RSS_IPV6_UDP; |
1278 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1279 | "UDP 4-tuple disabled\n" ); |
1280 | } else { |
1281 | return -EINVAL; |
1282 | } |
1283 | break; |
1284 | case IPV4_FLOW: |
1285 | case IPV6_FLOW: |
1286 | /* For IP only 2-tuple hash is supported */ |
1287 | if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { |
1288 | DP_INFO(edev, "Command parameters not supported\n" ); |
1289 | return -EINVAL; |
1290 | } |
1291 | return 0; |
1292 | case SCTP_V4_FLOW: |
1293 | case AH_ESP_V4_FLOW: |
1294 | case AH_V4_FLOW: |
1295 | case ESP_V4_FLOW: |
1296 | case SCTP_V6_FLOW: |
1297 | case AH_ESP_V6_FLOW: |
1298 | case AH_V6_FLOW: |
1299 | case ESP_V6_FLOW: |
1300 | case IP_USER_FLOW: |
1301 | case ETHER_FLOW: |
1302 | /* RSS is not supported for these protocols */ |
1303 | if (info->data) { |
1304 | DP_INFO(edev, "Command parameters not supported\n" ); |
1305 | return -EINVAL; |
1306 | } |
1307 | return 0; |
1308 | default: |
1309 | return -EINVAL; |
1310 | } |
1311 | |
1312 | /* No action is needed if there is no change in the rss capability */ |
1313 | if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) |
1314 | return 0; |
1315 | |
1316 | /* Update internal configuration */ |
1317 | edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); |
1318 | edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; |
1319 | |
1320 | /* Re-configure if possible */ |
1321 | __qede_lock(edev); |
1322 | if (edev->state == QEDE_STATE_OPEN) { |
1323 | vport_update_params = vzalloc(size: sizeof(*vport_update_params)); |
1324 | if (!vport_update_params) { |
1325 | __qede_unlock(edev); |
1326 | return -ENOMEM; |
1327 | } |
1328 | qede_fill_rss_params(edev, rss: &vport_update_params->rss_params, |
1329 | update: &vport_update_params->update_rss_flg); |
1330 | rc = edev->ops->vport_update(edev->cdev, vport_update_params); |
1331 | vfree(addr: vport_update_params); |
1332 | } |
1333 | __qede_unlock(edev); |
1334 | |
1335 | return rc; |
1336 | } |
1337 | |
1338 | static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) |
1339 | { |
1340 | struct qede_dev *edev = netdev_priv(dev); |
1341 | int rc; |
1342 | |
1343 | switch (info->cmd) { |
1344 | case ETHTOOL_SRXFH: |
1345 | rc = qede_set_rss_flags(edev, info); |
1346 | break; |
1347 | case ETHTOOL_SRXCLSRLINS: |
1348 | rc = qede_add_cls_rule(edev, info); |
1349 | break; |
1350 | case ETHTOOL_SRXCLSRLDEL: |
1351 | rc = qede_delete_flow_filter(edev, cookie: info->fs.location); |
1352 | break; |
1353 | default: |
1354 | DP_INFO(edev, "Command parameters not supported\n" ); |
1355 | rc = -EOPNOTSUPP; |
1356 | } |
1357 | |
1358 | return rc; |
1359 | } |
1360 | |
1361 | static u32 qede_get_rxfh_indir_size(struct net_device *dev) |
1362 | { |
1363 | return QED_RSS_IND_TABLE_SIZE; |
1364 | } |
1365 | |
1366 | static u32 qede_get_rxfh_key_size(struct net_device *dev) |
1367 | { |
1368 | struct qede_dev *edev = netdev_priv(dev); |
1369 | |
1370 | return sizeof(edev->rss_key); |
1371 | } |
1372 | |
1373 | static int qede_get_rxfh(struct net_device *dev, |
1374 | struct ethtool_rxfh_param *rxfh) |
1375 | { |
1376 | struct qede_dev *edev = netdev_priv(dev); |
1377 | int i; |
1378 | |
1379 | rxfh->hfunc = ETH_RSS_HASH_TOP; |
1380 | |
1381 | if (!rxfh->indir) |
1382 | return 0; |
1383 | |
1384 | for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) |
1385 | rxfh->indir[i] = edev->rss_ind_table[i]; |
1386 | |
1387 | if (rxfh->key) |
1388 | memcpy(rxfh->key, edev->rss_key, qede_get_rxfh_key_size(dev)); |
1389 | |
1390 | return 0; |
1391 | } |
1392 | |
1393 | static int qede_set_rxfh(struct net_device *dev, |
1394 | struct ethtool_rxfh_param *rxfh, |
1395 | struct netlink_ext_ack *extack) |
1396 | { |
1397 | struct qed_update_vport_params *vport_update_params; |
1398 | struct qede_dev *edev = netdev_priv(dev); |
1399 | int i, rc = 0; |
1400 | |
1401 | if (edev->dev_info.common.num_hwfns > 1) { |
1402 | DP_INFO(edev, |
1403 | "RSS configuration is not supported for 100G devices\n" ); |
1404 | return -EOPNOTSUPP; |
1405 | } |
1406 | |
1407 | if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && |
1408 | rxfh->hfunc != ETH_RSS_HASH_TOP) |
1409 | return -EOPNOTSUPP; |
1410 | |
1411 | if (!rxfh->indir && !rxfh->key) |
1412 | return 0; |
1413 | |
1414 | if (rxfh->indir) { |
1415 | for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) |
1416 | edev->rss_ind_table[i] = rxfh->indir[i]; |
1417 | edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; |
1418 | } |
1419 | |
1420 | if (rxfh->key) { |
1421 | memcpy(&edev->rss_key, rxfh->key, qede_get_rxfh_key_size(dev)); |
1422 | edev->rss_params_inited |= QEDE_RSS_KEY_INITED; |
1423 | } |
1424 | |
1425 | __qede_lock(edev); |
1426 | if (edev->state == QEDE_STATE_OPEN) { |
1427 | vport_update_params = vzalloc(size: sizeof(*vport_update_params)); |
1428 | if (!vport_update_params) { |
1429 | __qede_unlock(edev); |
1430 | return -ENOMEM; |
1431 | } |
1432 | qede_fill_rss_params(edev, rss: &vport_update_params->rss_params, |
1433 | update: &vport_update_params->update_rss_flg); |
1434 | rc = edev->ops->vport_update(edev->cdev, vport_update_params); |
1435 | vfree(addr: vport_update_params); |
1436 | } |
1437 | __qede_unlock(edev); |
1438 | |
1439 | return rc; |
1440 | } |
1441 | |
1442 | /* This function enables the interrupt generation and the NAPI on the device */ |
1443 | static void qede_netif_start(struct qede_dev *edev) |
1444 | { |
1445 | int i; |
1446 | |
1447 | if (!netif_running(dev: edev->ndev)) |
1448 | return; |
1449 | |
1450 | for_each_queue(i) { |
1451 | /* Update and reenable interrupts */ |
1452 | qed_sb_ack(sb_info: edev->fp_array[i].sb_info, int_cmd: IGU_INT_ENABLE, upd_flg: 1); |
1453 | napi_enable(n: &edev->fp_array[i].napi); |
1454 | } |
1455 | } |
1456 | |
1457 | /* This function disables the NAPI and the interrupt generation on the device */ |
1458 | static void qede_netif_stop(struct qede_dev *edev) |
1459 | { |
1460 | int i; |
1461 | |
1462 | for_each_queue(i) { |
1463 | napi_disable(n: &edev->fp_array[i].napi); |
1464 | /* Disable interrupts */ |
1465 | qed_sb_ack(sb_info: edev->fp_array[i].sb_info, int_cmd: IGU_INT_DISABLE, upd_flg: 0); |
1466 | } |
1467 | } |
1468 | |
1469 | static int qede_selftest_transmit_traffic(struct qede_dev *edev, |
1470 | struct sk_buff *skb) |
1471 | { |
1472 | struct qede_tx_queue *txq = NULL; |
1473 | struct eth_tx_1st_bd *first_bd; |
1474 | dma_addr_t mapping; |
1475 | int i, idx; |
1476 | u16 val; |
1477 | |
1478 | for_each_queue(i) { |
1479 | struct qede_fastpath *fp = &edev->fp_array[i]; |
1480 | |
1481 | if (fp->type & QEDE_FASTPATH_TX) { |
1482 | txq = QEDE_FP_TC0_TXQ(fp); |
1483 | break; |
1484 | } |
1485 | } |
1486 | |
1487 | if (!txq) { |
1488 | DP_NOTICE(edev, "Tx path is not available\n" ); |
1489 | return -1; |
1490 | } |
1491 | |
1492 | /* Fill the entry in the SW ring and the BDs in the FW ring */ |
1493 | idx = txq->sw_tx_prod; |
1494 | txq->sw_tx_ring.skbs[idx].skb = skb; |
1495 | first_bd = qed_chain_produce(p_chain: &txq->tx_pbl); |
1496 | memset(first_bd, 0, sizeof(*first_bd)); |
1497 | val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; |
1498 | first_bd->data.bd_flags.bitfields = val; |
1499 | val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; |
1500 | val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; |
1501 | first_bd->data.bitfields |= cpu_to_le16(val); |
1502 | |
1503 | /* Map skb linear data for DMA and set in the first BD */ |
1504 | mapping = dma_map_single(&edev->pdev->dev, skb->data, |
1505 | skb_headlen(skb), DMA_TO_DEVICE); |
1506 | if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { |
1507 | DP_NOTICE(edev, "SKB mapping failed\n" ); |
1508 | return -ENOMEM; |
1509 | } |
1510 | BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); |
1511 | |
1512 | /* update the first BD with the actual num BDs */ |
1513 | first_bd->data.nbds = 1; |
1514 | txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; |
1515 | /* 'next page' entries are counted in the producer value */ |
1516 | val = qed_chain_get_prod_idx(chain: &txq->tx_pbl); |
1517 | txq->tx_db.data.bd_prod = cpu_to_le16(val); |
1518 | |
1519 | /* wmb makes sure that the BDs data is updated before updating the |
1520 | * producer, otherwise FW may read old data from the BDs. |
1521 | */ |
1522 | wmb(); |
1523 | barrier(); |
1524 | writel(val: txq->tx_db.raw, addr: txq->doorbell_addr); |
1525 | |
1526 | for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { |
1527 | if (qede_txq_has_work(txq)) |
1528 | break; |
1529 | usleep_range(min: 100, max: 200); |
1530 | } |
1531 | |
1532 | if (!qede_txq_has_work(txq)) { |
1533 | DP_NOTICE(edev, "Tx completion didn't happen\n" ); |
1534 | return -1; |
1535 | } |
1536 | |
1537 | first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(p_chain: &txq->tx_pbl); |
1538 | dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), |
1539 | BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); |
1540 | txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; |
1541 | txq->sw_tx_ring.skbs[idx].skb = NULL; |
1542 | |
1543 | return 0; |
1544 | } |
1545 | |
1546 | static int qede_selftest_receive_traffic(struct qede_dev *edev) |
1547 | { |
1548 | u16 sw_rx_index, len; |
1549 | struct eth_fast_path_rx_reg_cqe *fp_cqe; |
1550 | struct qede_rx_queue *rxq = NULL; |
1551 | struct sw_rx_data *sw_rx_data; |
1552 | union eth_rx_cqe *cqe; |
1553 | int i, iter, rc = 0; |
1554 | u8 *data_ptr; |
1555 | |
1556 | for_each_queue(i) { |
1557 | if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { |
1558 | rxq = edev->fp_array[i].rxq; |
1559 | break; |
1560 | } |
1561 | } |
1562 | |
1563 | if (!rxq) { |
1564 | DP_NOTICE(edev, "Rx path is not available\n" ); |
1565 | return -1; |
1566 | } |
1567 | |
1568 | /* The packet is expected to receive on rx-queue 0 even though RSS is |
1569 | * enabled. This is because the queue 0 is configured as the default |
1570 | * queue and that the loopback traffic is not IP. |
1571 | */ |
1572 | for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { |
1573 | if (!qede_has_rx_work(rxq)) { |
1574 | usleep_range(min: 100, max: 200); |
1575 | continue; |
1576 | } |
1577 | |
1578 | /* Get the CQE from the completion ring */ |
1579 | cqe = (union eth_rx_cqe *)qed_chain_consume(p_chain: &rxq->rx_comp_ring); |
1580 | |
1581 | /* Get the data from the SW ring */ |
1582 | sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; |
1583 | sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; |
1584 | fp_cqe = &cqe->fast_path_regular; |
1585 | len = le16_to_cpu(fp_cqe->len_on_first_bd); |
1586 | data_ptr = (u8 *)(page_address(sw_rx_data->data) + |
1587 | fp_cqe->placement_offset + |
1588 | sw_rx_data->page_offset + |
1589 | rxq->rx_headroom); |
1590 | if (ether_addr_equal(addr1: data_ptr, addr2: edev->ndev->dev_addr) && |
1591 | ether_addr_equal(addr1: data_ptr + ETH_ALEN, |
1592 | addr2: edev->ndev->dev_addr)) { |
1593 | for (i = ETH_HLEN; i < len; i++) |
1594 | if (data_ptr[i] != (unsigned char)(i & 0xff)) { |
1595 | rc = -1; |
1596 | break; |
1597 | } |
1598 | |
1599 | qede_recycle_rx_bd_ring(rxq, count: 1); |
1600 | qed_chain_recycle_consumed(p_chain: &rxq->rx_comp_ring); |
1601 | break; |
1602 | } |
1603 | |
1604 | DP_INFO(edev, "Not the transmitted packet\n" ); |
1605 | qede_recycle_rx_bd_ring(rxq, count: 1); |
1606 | qed_chain_recycle_consumed(p_chain: &rxq->rx_comp_ring); |
1607 | } |
1608 | |
1609 | if (iter == QEDE_SELFTEST_POLL_COUNT) { |
1610 | DP_NOTICE(edev, "Failed to receive the traffic\n" ); |
1611 | return -1; |
1612 | } |
1613 | |
1614 | qede_update_rx_prod(edev, rxq); |
1615 | |
1616 | return rc; |
1617 | } |
1618 | |
1619 | static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) |
1620 | { |
1621 | struct qed_link_params link_params; |
1622 | struct sk_buff *skb = NULL; |
1623 | int rc = 0, i; |
1624 | u32 pkt_size; |
1625 | u8 *packet; |
1626 | |
1627 | if (!netif_running(dev: edev->ndev)) { |
1628 | DP_NOTICE(edev, "Interface is down\n" ); |
1629 | return -EINVAL; |
1630 | } |
1631 | |
1632 | qede_netif_stop(edev); |
1633 | |
1634 | /* Bring up the link in Loopback mode */ |
1635 | memset(&link_params, 0, sizeof(link_params)); |
1636 | link_params.link_up = true; |
1637 | link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; |
1638 | link_params.loopback_mode = loopback_mode; |
1639 | edev->ops->common->set_link(edev->cdev, &link_params); |
1640 | |
1641 | /* Wait for loopback configuration to apply */ |
1642 | msleep_interruptible(msecs: 500); |
1643 | |
1644 | /* Setting max packet size to 1.5K to avoid data being split over |
1645 | * multiple BDs in cases where MTU > PAGE_SIZE. |
1646 | */ |
1647 | pkt_size = (((edev->ndev->mtu < ETH_DATA_LEN) ? |
1648 | edev->ndev->mtu : ETH_DATA_LEN) + ETH_HLEN); |
1649 | |
1650 | skb = netdev_alloc_skb(dev: edev->ndev, length: pkt_size); |
1651 | if (!skb) { |
1652 | DP_INFO(edev, "Can't allocate skb\n" ); |
1653 | rc = -ENOMEM; |
1654 | goto test_loopback_exit; |
1655 | } |
1656 | packet = skb_put(skb, len: pkt_size); |
1657 | ether_addr_copy(dst: packet, src: edev->ndev->dev_addr); |
1658 | ether_addr_copy(dst: packet + ETH_ALEN, src: edev->ndev->dev_addr); |
1659 | memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); |
1660 | for (i = ETH_HLEN; i < pkt_size; i++) |
1661 | packet[i] = (unsigned char)(i & 0xff); |
1662 | |
1663 | rc = qede_selftest_transmit_traffic(edev, skb); |
1664 | if (rc) |
1665 | goto test_loopback_exit; |
1666 | |
1667 | rc = qede_selftest_receive_traffic(edev); |
1668 | if (rc) |
1669 | goto test_loopback_exit; |
1670 | |
1671 | DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n" ); |
1672 | |
1673 | test_loopback_exit: |
1674 | dev_kfree_skb(skb); |
1675 | |
1676 | /* Bring up the link in Normal mode */ |
1677 | memset(&link_params, 0, sizeof(link_params)); |
1678 | link_params.link_up = true; |
1679 | link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; |
1680 | link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; |
1681 | edev->ops->common->set_link(edev->cdev, &link_params); |
1682 | |
1683 | /* Wait for loopback configuration to apply */ |
1684 | msleep_interruptible(msecs: 500); |
1685 | |
1686 | qede_netif_start(edev); |
1687 | |
1688 | return rc; |
1689 | } |
1690 | |
1691 | static void qede_self_test(struct net_device *dev, |
1692 | struct ethtool_test *etest, u64 *buf) |
1693 | { |
1694 | struct qede_dev *edev = netdev_priv(dev); |
1695 | |
1696 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1697 | "Self-test command parameters: offline = %d, external_lb = %d\n" , |
1698 | (etest->flags & ETH_TEST_FL_OFFLINE), |
1699 | (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); |
1700 | |
1701 | memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); |
1702 | |
1703 | if (etest->flags & ETH_TEST_FL_OFFLINE) { |
1704 | if (qede_selftest_run_loopback(edev, |
1705 | QED_LINK_LOOPBACK_INT_PHY)) { |
1706 | buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; |
1707 | etest->flags |= ETH_TEST_FL_FAILED; |
1708 | } |
1709 | } |
1710 | |
1711 | if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { |
1712 | buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; |
1713 | etest->flags |= ETH_TEST_FL_FAILED; |
1714 | } |
1715 | |
1716 | if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { |
1717 | buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; |
1718 | etest->flags |= ETH_TEST_FL_FAILED; |
1719 | } |
1720 | |
1721 | if (edev->ops->common->selftest->selftest_register(edev->cdev)) { |
1722 | buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; |
1723 | etest->flags |= ETH_TEST_FL_FAILED; |
1724 | } |
1725 | |
1726 | if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { |
1727 | buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; |
1728 | etest->flags |= ETH_TEST_FL_FAILED; |
1729 | } |
1730 | |
1731 | if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { |
1732 | buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; |
1733 | etest->flags |= ETH_TEST_FL_FAILED; |
1734 | } |
1735 | } |
1736 | |
1737 | static int qede_set_tunable(struct net_device *dev, |
1738 | const struct ethtool_tunable *tuna, |
1739 | const void *data) |
1740 | { |
1741 | struct qede_dev *edev = netdev_priv(dev); |
1742 | u32 val; |
1743 | |
1744 | switch (tuna->id) { |
1745 | case ETHTOOL_RX_COPYBREAK: |
1746 | val = *(u32 *)data; |
1747 | if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { |
1748 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1749 | "Invalid rx copy break value, range is [%u, %u]" , |
1750 | QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); |
1751 | return -EINVAL; |
1752 | } |
1753 | |
1754 | edev->rx_copybreak = *(u32 *)data; |
1755 | break; |
1756 | default: |
1757 | return -EOPNOTSUPP; |
1758 | } |
1759 | |
1760 | return 0; |
1761 | } |
1762 | |
1763 | static int qede_get_tunable(struct net_device *dev, |
1764 | const struct ethtool_tunable *tuna, void *data) |
1765 | { |
1766 | struct qede_dev *edev = netdev_priv(dev); |
1767 | |
1768 | switch (tuna->id) { |
1769 | case ETHTOOL_RX_COPYBREAK: |
1770 | *(u32 *)data = edev->rx_copybreak; |
1771 | break; |
1772 | default: |
1773 | return -EOPNOTSUPP; |
1774 | } |
1775 | |
1776 | return 0; |
1777 | } |
1778 | |
1779 | static int qede_get_eee(struct net_device *dev, struct ethtool_keee *edata) |
1780 | { |
1781 | struct qede_dev *edev = netdev_priv(dev); |
1782 | struct qed_link_output current_link; |
1783 | |
1784 | memset(¤t_link, 0, sizeof(current_link)); |
1785 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
1786 | |
1787 | if (!current_link.eee_supported) { |
1788 | DP_INFO(edev, "EEE is not supported\n" ); |
1789 | return -EOPNOTSUPP; |
1790 | } |
1791 | |
1792 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1793 | addr: edata->advertised, |
1794 | set: current_link.eee.adv_caps & QED_EEE_1G_ADV); |
1795 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1796 | addr: edata->advertised, |
1797 | set: current_link.eee.adv_caps & QED_EEE_10G_ADV); |
1798 | |
1799 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1800 | addr: edata->supported, |
1801 | set: current_link.sup_caps & QED_EEE_1G_ADV); |
1802 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1803 | addr: edata->supported, |
1804 | set: current_link.sup_caps & QED_EEE_10G_ADV); |
1805 | |
1806 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1807 | addr: edata->lp_advertised, |
1808 | set: current_link.eee.lp_adv_caps & QED_EEE_1G_ADV); |
1809 | linkmode_mod_bit(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1810 | addr: edata->lp_advertised, |
1811 | set: current_link.eee.lp_adv_caps & QED_EEE_10G_ADV); |
1812 | |
1813 | edata->tx_lpi_timer = current_link.eee.tx_lpi_timer; |
1814 | edata->eee_enabled = current_link.eee.enable; |
1815 | edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable; |
1816 | edata->eee_active = current_link.eee_active; |
1817 | |
1818 | return 0; |
1819 | } |
1820 | |
1821 | static int qede_set_eee(struct net_device *dev, struct ethtool_keee *edata) |
1822 | { |
1823 | __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = {}; |
1824 | __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp) = {}; |
1825 | struct qede_dev *edev = netdev_priv(dev); |
1826 | struct qed_link_output current_link; |
1827 | struct qed_link_params params; |
1828 | bool unsupp; |
1829 | |
1830 | if (!edev->ops->common->can_link_change(edev->cdev)) { |
1831 | DP_INFO(edev, "Link settings are not allowed to be changed\n" ); |
1832 | return -EOPNOTSUPP; |
1833 | } |
1834 | |
1835 | memset(¤t_link, 0, sizeof(current_link)); |
1836 | edev->ops->common->get_link(edev->cdev, ¤t_link); |
1837 | |
1838 | if (!current_link.eee_supported) { |
1839 | DP_INFO(edev, "EEE is not supported\n" ); |
1840 | return -EOPNOTSUPP; |
1841 | } |
1842 | |
1843 | memset(¶ms, 0, sizeof(params)); |
1844 | params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG; |
1845 | |
1846 | linkmode_set_bit(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1847 | addr: supported); |
1848 | linkmode_set_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1849 | addr: supported); |
1850 | |
1851 | unsupp = linkmode_andnot(dst: tmp, src1: edata->advertised, src2: supported); |
1852 | if (unsupp) { |
1853 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
1854 | "Invalid advertised capabilities %*pb\n" , |
1855 | __ETHTOOL_LINK_MODE_MASK_NBITS, edata->advertised); |
1856 | return -EINVAL; |
1857 | } |
1858 | |
1859 | if (linkmode_test_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1860 | addr: edata->advertised)) |
1861 | params.eee.adv_caps = QED_EEE_1G_ADV; |
1862 | if (linkmode_test_bit(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1863 | addr: edata->advertised)) |
1864 | params.eee.adv_caps = QED_EEE_10G_ADV; |
1865 | |
1866 | params.eee.enable = edata->eee_enabled; |
1867 | params.eee.tx_lpi_enable = edata->tx_lpi_enabled; |
1868 | params.eee.tx_lpi_timer = edata->tx_lpi_timer; |
1869 | |
1870 | params.link_up = true; |
1871 | edev->ops->common->set_link(edev->cdev, ¶ms); |
1872 | |
1873 | return 0; |
1874 | } |
1875 | |
1876 | static u32 qede_link_to_ethtool_fec(u32 link_fec) |
1877 | { |
1878 | u32 eth_fec = 0; |
1879 | |
1880 | if (link_fec & QED_FEC_MODE_NONE) |
1881 | eth_fec |= ETHTOOL_FEC_OFF; |
1882 | if (link_fec & QED_FEC_MODE_FIRECODE) |
1883 | eth_fec |= ETHTOOL_FEC_BASER; |
1884 | if (link_fec & QED_FEC_MODE_RS) |
1885 | eth_fec |= ETHTOOL_FEC_RS; |
1886 | if (link_fec & QED_FEC_MODE_AUTO) |
1887 | eth_fec |= ETHTOOL_FEC_AUTO; |
1888 | if (link_fec & QED_FEC_MODE_UNSUPPORTED) |
1889 | eth_fec |= ETHTOOL_FEC_NONE; |
1890 | |
1891 | return eth_fec; |
1892 | } |
1893 | |
1894 | static u32 qede_ethtool_to_link_fec(u32 eth_fec) |
1895 | { |
1896 | u32 link_fec = 0; |
1897 | |
1898 | if (eth_fec & ETHTOOL_FEC_OFF) |
1899 | link_fec |= QED_FEC_MODE_NONE; |
1900 | if (eth_fec & ETHTOOL_FEC_BASER) |
1901 | link_fec |= QED_FEC_MODE_FIRECODE; |
1902 | if (eth_fec & ETHTOOL_FEC_RS) |
1903 | link_fec |= QED_FEC_MODE_RS; |
1904 | if (eth_fec & ETHTOOL_FEC_AUTO) |
1905 | link_fec |= QED_FEC_MODE_AUTO; |
1906 | if (eth_fec & ETHTOOL_FEC_NONE) |
1907 | link_fec |= QED_FEC_MODE_UNSUPPORTED; |
1908 | |
1909 | return link_fec; |
1910 | } |
1911 | |
1912 | static int qede_get_fecparam(struct net_device *dev, |
1913 | struct ethtool_fecparam *fecparam) |
1914 | { |
1915 | struct qede_dev *edev = netdev_priv(dev); |
1916 | struct qed_link_output curr_link; |
1917 | |
1918 | memset(&curr_link, 0, sizeof(curr_link)); |
1919 | edev->ops->common->get_link(edev->cdev, &curr_link); |
1920 | |
1921 | fecparam->active_fec = qede_link_to_ethtool_fec(link_fec: curr_link.active_fec); |
1922 | fecparam->fec = qede_link_to_ethtool_fec(link_fec: curr_link.sup_fec); |
1923 | |
1924 | return 0; |
1925 | } |
1926 | |
1927 | static int qede_set_fecparam(struct net_device *dev, |
1928 | struct ethtool_fecparam *fecparam) |
1929 | { |
1930 | struct qede_dev *edev = netdev_priv(dev); |
1931 | struct qed_link_params params; |
1932 | |
1933 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
1934 | DP_INFO(edev, "Link settings are not allowed to be changed\n" ); |
1935 | return -EOPNOTSUPP; |
1936 | } |
1937 | |
1938 | memset(¶ms, 0, sizeof(params)); |
1939 | params.override_flags |= QED_LINK_OVERRIDE_FEC_CONFIG; |
1940 | params.fec = qede_ethtool_to_link_fec(eth_fec: fecparam->fec); |
1941 | params.link_up = true; |
1942 | |
1943 | edev->ops->common->set_link(edev->cdev, ¶ms); |
1944 | |
1945 | return 0; |
1946 | } |
1947 | |
1948 | static int qede_get_module_info(struct net_device *dev, |
1949 | struct ethtool_modinfo *modinfo) |
1950 | { |
1951 | struct qede_dev *edev = netdev_priv(dev); |
1952 | u8 buf[4]; |
1953 | int rc; |
1954 | |
1955 | /* Read first 4 bytes to find the sfp type */ |
1956 | rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, |
1957 | QED_I2C_DEV_ADDR_A0, 0, 4); |
1958 | if (rc) { |
1959 | DP_ERR(edev, "Failed reading EEPROM data %d\n" , rc); |
1960 | return rc; |
1961 | } |
1962 | |
1963 | switch (buf[0]) { |
1964 | case 0x3: /* SFP, SFP+, SFP-28 */ |
1965 | modinfo->type = ETH_MODULE_SFF_8472; |
1966 | modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; |
1967 | break; |
1968 | case 0xc: /* QSFP */ |
1969 | case 0xd: /* QSFP+ */ |
1970 | modinfo->type = ETH_MODULE_SFF_8436; |
1971 | modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; |
1972 | break; |
1973 | case 0x11: /* QSFP-28 */ |
1974 | modinfo->type = ETH_MODULE_SFF_8636; |
1975 | modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; |
1976 | break; |
1977 | default: |
1978 | DP_ERR(edev, "Unknown transceiver type 0x%x\n" , buf[0]); |
1979 | return -EINVAL; |
1980 | } |
1981 | |
1982 | return 0; |
1983 | } |
1984 | |
1985 | static int qede_get_module_eeprom(struct net_device *dev, |
1986 | struct ethtool_eeprom *ee, u8 *data) |
1987 | { |
1988 | struct qede_dev *edev = netdev_priv(dev); |
1989 | u32 start_addr = ee->offset, size = 0; |
1990 | u8 *buf = data; |
1991 | int rc = 0; |
1992 | |
1993 | /* Read A0 section */ |
1994 | if (ee->offset < ETH_MODULE_SFF_8079_LEN) { |
1995 | /* Limit transfer size to the A0 section boundary */ |
1996 | if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN) |
1997 | size = ETH_MODULE_SFF_8079_LEN - ee->offset; |
1998 | else |
1999 | size = ee->len; |
2000 | |
2001 | rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, |
2002 | QED_I2C_DEV_ADDR_A0, |
2003 | start_addr, size); |
2004 | if (rc) { |
2005 | DP_ERR(edev, "Failed reading A0 section %d\n" , rc); |
2006 | return rc; |
2007 | } |
2008 | |
2009 | buf += size; |
2010 | start_addr += size; |
2011 | } |
2012 | |
2013 | /* Read A2 section */ |
2014 | if (start_addr >= ETH_MODULE_SFF_8079_LEN && |
2015 | start_addr < ETH_MODULE_SFF_8472_LEN) { |
2016 | size = ee->len - size; |
2017 | /* Limit transfer size to the A2 section boundary */ |
2018 | if (start_addr + size > ETH_MODULE_SFF_8472_LEN) |
2019 | size = ETH_MODULE_SFF_8472_LEN - start_addr; |
2020 | start_addr -= ETH_MODULE_SFF_8079_LEN; |
2021 | rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, |
2022 | QED_I2C_DEV_ADDR_A2, |
2023 | start_addr, size); |
2024 | if (rc) { |
2025 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
2026 | "Failed reading A2 section %d\n" , rc); |
2027 | return 0; |
2028 | } |
2029 | } |
2030 | |
2031 | return rc; |
2032 | } |
2033 | |
2034 | static int qede_set_dump(struct net_device *dev, struct ethtool_dump *val) |
2035 | { |
2036 | struct qede_dev *edev = netdev_priv(dev); |
2037 | int rc = 0; |
2038 | |
2039 | if (edev->dump_info.cmd == QEDE_DUMP_CMD_NONE) { |
2040 | if (val->flag > QEDE_DUMP_CMD_MAX) { |
2041 | DP_ERR(edev, "Invalid command %d\n" , val->flag); |
2042 | return -EINVAL; |
2043 | } |
2044 | edev->dump_info.cmd = val->flag; |
2045 | edev->dump_info.num_args = 0; |
2046 | return 0; |
2047 | } |
2048 | |
2049 | if (edev->dump_info.num_args == QEDE_DUMP_MAX_ARGS) { |
2050 | DP_ERR(edev, "Arg count = %d\n" , edev->dump_info.num_args); |
2051 | return -EINVAL; |
2052 | } |
2053 | |
2054 | switch (edev->dump_info.cmd) { |
2055 | case QEDE_DUMP_CMD_NVM_CFG: |
2056 | edev->dump_info.args[edev->dump_info.num_args] = val->flag; |
2057 | edev->dump_info.num_args++; |
2058 | break; |
2059 | case QEDE_DUMP_CMD_GRCDUMP: |
2060 | rc = edev->ops->common->set_grc_config(edev->cdev, |
2061 | val->flag, 1); |
2062 | break; |
2063 | default: |
2064 | break; |
2065 | } |
2066 | |
2067 | return rc; |
2068 | } |
2069 | |
2070 | static int qede_get_dump_flag(struct net_device *dev, |
2071 | struct ethtool_dump *dump) |
2072 | { |
2073 | struct qede_dev *edev = netdev_priv(dev); |
2074 | |
2075 | if (!edev->ops || !edev->ops->common) { |
2076 | DP_ERR(edev, "Edev ops not populated\n" ); |
2077 | return -EINVAL; |
2078 | } |
2079 | |
2080 | dump->version = QEDE_DUMP_VERSION; |
2081 | switch (edev->dump_info.cmd) { |
2082 | case QEDE_DUMP_CMD_NVM_CFG: |
2083 | dump->flag = QEDE_DUMP_CMD_NVM_CFG; |
2084 | dump->len = edev->ops->common->read_nvm_cfg_len(edev->cdev, |
2085 | edev->dump_info.args[0]); |
2086 | break; |
2087 | case QEDE_DUMP_CMD_GRCDUMP: |
2088 | dump->flag = QEDE_DUMP_CMD_GRCDUMP; |
2089 | dump->len = edev->ops->common->dbg_all_data_size(edev->cdev); |
2090 | break; |
2091 | default: |
2092 | DP_ERR(edev, "Invalid cmd = %d\n" , edev->dump_info.cmd); |
2093 | return -EINVAL; |
2094 | } |
2095 | |
2096 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
2097 | "dump->version = 0x%x dump->flag = %d dump->len = %d\n" , |
2098 | dump->version, dump->flag, dump->len); |
2099 | return 0; |
2100 | } |
2101 | |
2102 | static int qede_get_dump_data(struct net_device *dev, |
2103 | struct ethtool_dump *dump, void *buf) |
2104 | { |
2105 | struct qede_dev *edev = netdev_priv(dev); |
2106 | int rc = 0; |
2107 | |
2108 | if (!edev->ops || !edev->ops->common) { |
2109 | DP_ERR(edev, "Edev ops not populated\n" ); |
2110 | rc = -EINVAL; |
2111 | goto err; |
2112 | } |
2113 | |
2114 | switch (edev->dump_info.cmd) { |
2115 | case QEDE_DUMP_CMD_NVM_CFG: |
2116 | if (edev->dump_info.num_args != QEDE_DUMP_NVM_ARG_COUNT) { |
2117 | DP_ERR(edev, "Arg count = %d required = %d\n" , |
2118 | edev->dump_info.num_args, |
2119 | QEDE_DUMP_NVM_ARG_COUNT); |
2120 | rc = -EINVAL; |
2121 | goto err; |
2122 | } |
2123 | rc = edev->ops->common->read_nvm_cfg(edev->cdev, (u8 **)&buf, |
2124 | edev->dump_info.args[0], |
2125 | edev->dump_info.args[1]); |
2126 | break; |
2127 | case QEDE_DUMP_CMD_GRCDUMP: |
2128 | memset(buf, 0, dump->len); |
2129 | rc = edev->ops->common->dbg_all_data(edev->cdev, buf); |
2130 | break; |
2131 | default: |
2132 | DP_ERR(edev, "Invalid cmd = %d\n" , edev->dump_info.cmd); |
2133 | rc = -EINVAL; |
2134 | break; |
2135 | } |
2136 | |
2137 | err: |
2138 | edev->dump_info.cmd = QEDE_DUMP_CMD_NONE; |
2139 | edev->dump_info.num_args = 0; |
2140 | memset(edev->dump_info.args, 0, sizeof(edev->dump_info.args)); |
2141 | |
2142 | return rc; |
2143 | } |
2144 | |
2145 | int qede_set_per_coalesce(struct net_device *dev, u32 queue, |
2146 | struct ethtool_coalesce *coal) |
2147 | { |
2148 | struct qede_dev *edev = netdev_priv(dev); |
2149 | struct qede_fastpath *fp; |
2150 | u16 rxc, txc; |
2151 | int rc = 0; |
2152 | |
2153 | if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || |
2154 | coal->tx_coalesce_usecs > QED_COALESCE_MAX) { |
2155 | DP_INFO(edev, |
2156 | "Can't support requested %s coalesce value [max supported value %d]\n" , |
2157 | coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" |
2158 | : "tx" , |
2159 | QED_COALESCE_MAX); |
2160 | return -EINVAL; |
2161 | } |
2162 | |
2163 | rxc = (u16)coal->rx_coalesce_usecs; |
2164 | txc = (u16)coal->tx_coalesce_usecs; |
2165 | |
2166 | __qede_lock(edev); |
2167 | if (queue >= edev->num_queues) { |
2168 | DP_INFO(edev, "Invalid queue\n" ); |
2169 | rc = -EINVAL; |
2170 | goto out; |
2171 | } |
2172 | |
2173 | if (edev->state != QEDE_STATE_OPEN) { |
2174 | rc = -EINVAL; |
2175 | goto out; |
2176 | } |
2177 | |
2178 | fp = &edev->fp_array[queue]; |
2179 | |
2180 | if (edev->fp_array[queue].type & QEDE_FASTPATH_RX) { |
2181 | rc = edev->ops->common->set_coalesce(edev->cdev, |
2182 | rxc, 0, |
2183 | fp->rxq->handle); |
2184 | if (rc) { |
2185 | DP_INFO(edev, |
2186 | "Set RX coalesce error, rc = %d\n" , rc); |
2187 | goto out; |
2188 | } |
2189 | edev->coal_entry[queue].rxc = rxc; |
2190 | edev->coal_entry[queue].isvalid = true; |
2191 | } |
2192 | |
2193 | if (edev->fp_array[queue].type & QEDE_FASTPATH_TX) { |
2194 | rc = edev->ops->common->set_coalesce(edev->cdev, |
2195 | 0, txc, |
2196 | fp->txq->handle); |
2197 | if (rc) { |
2198 | DP_INFO(edev, |
2199 | "Set TX coalesce error, rc = %d\n" , rc); |
2200 | goto out; |
2201 | } |
2202 | edev->coal_entry[queue].txc = txc; |
2203 | edev->coal_entry[queue].isvalid = true; |
2204 | } |
2205 | out: |
2206 | __qede_unlock(edev); |
2207 | |
2208 | return rc; |
2209 | } |
2210 | |
2211 | static int qede_get_per_coalesce(struct net_device *dev, |
2212 | u32 queue, |
2213 | struct ethtool_coalesce *coal) |
2214 | { |
2215 | void *rx_handle = NULL, *tx_handle = NULL; |
2216 | struct qede_dev *edev = netdev_priv(dev); |
2217 | struct qede_fastpath *fp; |
2218 | u16 rx_coal, tx_coal; |
2219 | int rc = 0; |
2220 | |
2221 | rx_coal = QED_DEFAULT_RX_USECS; |
2222 | tx_coal = QED_DEFAULT_TX_USECS; |
2223 | |
2224 | memset(coal, 0, sizeof(struct ethtool_coalesce)); |
2225 | |
2226 | __qede_lock(edev); |
2227 | if (queue >= edev->num_queues) { |
2228 | DP_INFO(edev, "Invalid queue\n" ); |
2229 | rc = -EINVAL; |
2230 | goto out; |
2231 | } |
2232 | |
2233 | if (edev->state != QEDE_STATE_OPEN) { |
2234 | rc = -EINVAL; |
2235 | goto out; |
2236 | } |
2237 | |
2238 | fp = &edev->fp_array[queue]; |
2239 | |
2240 | if (fp->type & QEDE_FASTPATH_RX) |
2241 | rx_handle = fp->rxq->handle; |
2242 | |
2243 | rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, |
2244 | rx_handle); |
2245 | if (rc) { |
2246 | DP_INFO(edev, "Read Rx coalesce error\n" ); |
2247 | goto out; |
2248 | } |
2249 | |
2250 | fp = &edev->fp_array[queue]; |
2251 | if (fp->type & QEDE_FASTPATH_TX) |
2252 | tx_handle = fp->txq->handle; |
2253 | |
2254 | rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, |
2255 | tx_handle); |
2256 | if (rc) |
2257 | DP_INFO(edev, "Read Tx coalesce error\n" ); |
2258 | |
2259 | out: |
2260 | __qede_unlock(edev); |
2261 | |
2262 | coal->rx_coalesce_usecs = rx_coal; |
2263 | coal->tx_coalesce_usecs = tx_coal; |
2264 | |
2265 | return rc; |
2266 | } |
2267 | |
2268 | static const struct ethtool_ops qede_ethtool_ops = { |
2269 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
2270 | ETHTOOL_COALESCE_STATS_BLOCK_USECS, |
2271 | .get_link_ksettings = qede_get_link_ksettings, |
2272 | .set_link_ksettings = qede_set_link_ksettings, |
2273 | .get_drvinfo = qede_get_drvinfo, |
2274 | .get_regs_len = qede_get_regs_len, |
2275 | .get_regs = qede_get_regs, |
2276 | .get_wol = qede_get_wol, |
2277 | .set_wol = qede_set_wol, |
2278 | .get_msglevel = qede_get_msglevel, |
2279 | .set_msglevel = qede_set_msglevel, |
2280 | .nway_reset = qede_nway_reset, |
2281 | .get_link = qede_get_link, |
2282 | .get_coalesce = qede_get_coalesce, |
2283 | .set_coalesce = qede_set_coalesce, |
2284 | .get_ringparam = qede_get_ringparam, |
2285 | .set_ringparam = qede_set_ringparam, |
2286 | .get_pauseparam = qede_get_pauseparam, |
2287 | .set_pauseparam = qede_set_pauseparam, |
2288 | .get_strings = qede_get_strings, |
2289 | .set_phys_id = qede_set_phys_id, |
2290 | .get_ethtool_stats = qede_get_ethtool_stats, |
2291 | .get_priv_flags = qede_get_priv_flags, |
2292 | .set_priv_flags = qede_set_priv_flags, |
2293 | .get_sset_count = qede_get_sset_count, |
2294 | .get_rxnfc = qede_get_rxnfc, |
2295 | .set_rxnfc = qede_set_rxnfc, |
2296 | .get_rxfh_indir_size = qede_get_rxfh_indir_size, |
2297 | .get_rxfh_key_size = qede_get_rxfh_key_size, |
2298 | .get_rxfh = qede_get_rxfh, |
2299 | .set_rxfh = qede_set_rxfh, |
2300 | .get_ts_info = qede_get_ts_info, |
2301 | .get_channels = qede_get_channels, |
2302 | .set_channels = qede_set_channels, |
2303 | .self_test = qede_self_test, |
2304 | .get_module_info = qede_get_module_info, |
2305 | .get_module_eeprom = qede_get_module_eeprom, |
2306 | .get_eee = qede_get_eee, |
2307 | .set_eee = qede_set_eee, |
2308 | .get_fecparam = qede_get_fecparam, |
2309 | .set_fecparam = qede_set_fecparam, |
2310 | .get_tunable = qede_get_tunable, |
2311 | .set_tunable = qede_set_tunable, |
2312 | .get_per_queue_coalesce = qede_get_per_coalesce, |
2313 | .set_per_queue_coalesce = qede_set_per_coalesce, |
2314 | .flash_device = qede_flash_device, |
2315 | .get_dump_flag = qede_get_dump_flag, |
2316 | .get_dump_data = qede_get_dump_data, |
2317 | .set_dump = qede_set_dump, |
2318 | }; |
2319 | |
2320 | static const struct ethtool_ops qede_vf_ethtool_ops = { |
2321 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
2322 | ETHTOOL_COALESCE_STATS_BLOCK_USECS, |
2323 | .get_link_ksettings = qede_get_link_ksettings, |
2324 | .get_drvinfo = qede_get_drvinfo, |
2325 | .get_msglevel = qede_get_msglevel, |
2326 | .set_msglevel = qede_set_msglevel, |
2327 | .get_link = qede_get_link, |
2328 | .get_coalesce = qede_get_coalesce, |
2329 | .set_coalesce = qede_set_coalesce, |
2330 | .get_ringparam = qede_get_ringparam, |
2331 | .set_ringparam = qede_set_ringparam, |
2332 | .get_strings = qede_get_strings, |
2333 | .get_ethtool_stats = qede_get_ethtool_stats, |
2334 | .get_priv_flags = qede_get_priv_flags, |
2335 | .get_sset_count = qede_get_sset_count, |
2336 | .get_rxnfc = qede_get_rxnfc, |
2337 | .set_rxnfc = qede_set_rxnfc, |
2338 | .get_rxfh_indir_size = qede_get_rxfh_indir_size, |
2339 | .get_rxfh_key_size = qede_get_rxfh_key_size, |
2340 | .get_rxfh = qede_get_rxfh, |
2341 | .set_rxfh = qede_set_rxfh, |
2342 | .get_channels = qede_get_channels, |
2343 | .set_channels = qede_set_channels, |
2344 | .get_per_queue_coalesce = qede_get_per_coalesce, |
2345 | .set_per_queue_coalesce = qede_set_per_coalesce, |
2346 | .get_tunable = qede_get_tunable, |
2347 | .set_tunable = qede_set_tunable, |
2348 | }; |
2349 | |
2350 | void qede_set_ethtool_ops(struct net_device *dev) |
2351 | { |
2352 | struct qede_dev *edev = netdev_priv(dev); |
2353 | |
2354 | if (IS_VF(edev)) |
2355 | dev->ethtool_ops = &qede_vf_ethtool_ops; |
2356 | else |
2357 | dev->ethtool_ops = &qede_ethtool_ops; |
2358 | } |
2359 | |