Commit | Line | Data |
---|---|---|
7268f33e | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
133fac0e | 2 | /* QLogic qede NIC Driver |
e8f1cb50 | 3 | * Copyright (c) 2015-2017 QLogic Corporation |
c4fad2a5 | 4 | * Copyright (c) 2019-2020 Marvell International Ltd. |
e8f1cb50 | 5 | */ |
7268f33e | 6 | |
133fac0e SK |
7 | #include <linux/types.h> |
8 | #include <linux/netdevice.h> | |
16f46bf0 | 9 | #include <linux/etherdevice.h> |
133fac0e SK |
10 | #include <linux/ethtool.h> |
11 | #include <linux/string.h> | |
12 | #include <linux/pci.h> | |
13 | #include <linux/capability.h> | |
f29ffdb6 | 14 | #include <linux/vmalloc.h> |
bdb5d8ec AL |
15 | #include <linux/phylink.h> |
16 | ||
133fac0e | 17 | #include "qede.h" |
4c55215c | 18 | #include "qede_ptp.h" |
133fac0e | 19 | |
133fac0e SK |
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)} | |
16f46bf0 SRK |
25 | |
26 | #define QEDE_SELFTEST_POLL_COUNT 100 | |
d44a3ced | 27 | #define QEDE_DUMP_VERSION 0x1 |
d44a3ced | 28 | #define QEDE_DUMP_NVM_ARG_COUNT 2 |
16f46bf0 | 29 | |
133fac0e SK |
30 | static const struct { |
31 | u64 offset; | |
32 | char string[ETH_GSTRING_LEN]; | |
33 | } qede_rqstats_arr[] = { | |
68db9ec2 | 34 | QEDE_RQSTAT(rcv_pkts), |
133fac0e SK |
35 | QEDE_RQSTAT(rx_hw_errors), |
36 | QEDE_RQSTAT(rx_alloc_errors), | |
c72a6125 | 37 | QEDE_RQSTAT(rx_ip_frags), |
496e0517 | 38 | QEDE_RQSTAT(xdp_no_pass), |
133fac0e SK |
39 | }; |
40 | ||
41 | #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) | |
68db9ec2 SRK |
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), | |
dcc6abae | 54 | QEDE_TQSTAT(tx_mem_alloc_err), |
68db9ec2 SRK |
55 | }; |
56 | ||
9c79ddaa MY |
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)) | |
133fac0e SK |
77 | static const struct { |
78 | u64 offset; | |
79 | char string[ETH_GSTRING_LEN]; | |
9c79ddaa MY |
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 | |
133fac0e SK |
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), | |
d4967cf3 YM |
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), | |
9c79ddaa MY |
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), | |
133fac0e SK |
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), | |
9c79ddaa MY |
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), | |
133fac0e SK |
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), | |
9c79ddaa MY |
136 | QEDE_PF_BB_STAT(tx_lpi_entry_count), |
137 | QEDE_PF_BB_STAT(tx_total_collisions), | |
133fac0e SK |
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), | |
608e00d0 | 143 | QEDE_PF_STAT(gft_filter_drop), |
133fac0e | 144 | QEDE_STAT(tx_err_drop_pkts), |
1a5a366f SRK |
145 | QEDE_STAT(ttl0_discard), |
146 | QEDE_STAT(packet_too_big_discard), | |
133fac0e SK |
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), | |
32d26a68 SRK |
153 | |
154 | QEDE_STAT(link_change_count), | |
9adebac3 | 155 | QEDE_STAT(ptp_skip_txts), |
133fac0e SK |
156 | }; |
157 | ||
133fac0e | 158 | #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) |
9c79ddaa MY |
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) | |
133fac0e | 165 | |
f3e72109 YM |
166 | enum { |
167 | QEDE_PRI_FLAG_CMT, | |
f15cff04 | 168 | QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */ |
7d9acd87 | 169 | QEDE_PRI_FLAG_RECOVER_ON_ERROR, |
823163ba MC |
170 | QEDE_PRI_FLAG_ESL_SUPPORT, /* MFW supports Enhanced System Lockdown */ |
171 | QEDE_PRI_FLAG_ESL_ACTIVE, /* Enhanced System Lockdown Active status */ | |
f3e72109 YM |
172 | QEDE_PRI_FLAG_LEN, |
173 | }; | |
174 | ||
175 | static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { | |
176 | "Coupled-Function", | |
f15cff04 | 177 | "SmartAN capable", |
7d9acd87 | 178 | "Recover on error", |
823163ba MC |
179 | "ESL capable", |
180 | "ESL active", | |
f3e72109 YM |
181 | }; |
182 | ||
3044a02e | 183 | enum qede_ethtool_tests { |
16f46bf0 | 184 | QEDE_ETHTOOL_INT_LOOPBACK, |
3044a02e SRK |
185 | QEDE_ETHTOOL_INTERRUPT_TEST, |
186 | QEDE_ETHTOOL_MEMORY_TEST, | |
187 | QEDE_ETHTOOL_REGISTER_TEST, | |
188 | QEDE_ETHTOOL_CLOCK_TEST, | |
7a4b21b7 | 189 | QEDE_ETHTOOL_NVRAM_TEST, |
3044a02e SRK |
190 | QEDE_ETHTOOL_TEST_MAX |
191 | }; | |
192 | ||
193 | static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { | |
16f46bf0 | 194 | "Internal loopback (offline)", |
3044a02e SRK |
195 | "Interrupt (online)\t", |
196 | "Memory (online)\t\t", | |
197 | "Register (online)\t", | |
198 | "Clock (online)\t\t", | |
7a4b21b7 | 199 | "Nvram (online)\t\t", |
3044a02e SRK |
200 | }; |
201 | ||
1d4e4ecc AL |
202 | /* Forced speed capabilities maps */ |
203 | ||
1d4e4ecc AL |
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 | ||
a5b65cd2 PG |
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), | |
1d4e4ecc AL |
260 | }; |
261 | ||
262 | void __init qede_forced_speed_maps_init(void) | |
263 | { | |
a5b65cd2 PG |
264 | ethtool_forced_speed_maps_init(qede_forced_speed_maps, |
265 | ARRAY_SIZE(qede_forced_speed_maps)); | |
1d4e4ecc AL |
266 | } |
267 | ||
268 | /* Ethtool callbacks */ | |
269 | ||
4dbcd640 MY |
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++) { | |
cb6aeb07 MY |
276 | if (txq->is_xdp) |
277 | sprintf(*buf, "%d [XDP]: %s", | |
278 | QEDE_TXQ_XDP_TO_IDX(edev, txq), | |
279 | qede_tqstats_arr[i].string); | |
280 | else | |
5e7baf0f | 281 | sprintf(*buf, "%d_%d: %s", txq->index, txq->cos, |
cb6aeb07 | 282 | qede_tqstats_arr[i].string); |
4dbcd640 MY |
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, "%d: %s", rxq->rxq_id, | |
294 | qede_rqstats_arr[i].string); | |
295 | *buf += ETH_GSTRING_LEN; | |
296 | } | |
297 | } | |
298 | ||
9c79ddaa MY |
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 | ||
133fac0e SK |
306 | static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) |
307 | { | |
4dbcd640 MY |
308 | struct qede_fastpath *fp; |
309 | int i; | |
133fac0e | 310 | |
4dbcd640 MY |
311 | /* Account for queue statistics */ |
312 | for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { | |
313 | fp = &edev->fp_array[i]; | |
68db9ec2 | 314 | |
4dbcd640 MY |
315 | if (fp->type & QEDE_FASTPATH_RX) |
316 | qede_get_strings_stats_rxq(edev, fp->rxq, &buf); | |
cbbf049a | 317 | |
cb6aeb07 MY |
318 | if (fp->type & QEDE_FASTPATH_XDP) |
319 | qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf); | |
320 | ||
5e7baf0f MC |
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 | &fp->txq[cos], &buf); | |
327 | } | |
68db9ec2 SRK |
328 | } |
329 | ||
4dbcd640 MY |
330 | /* Account for non-queue statistics */ |
331 | for (i = 0; i < QEDE_NUM_STATS; i++) { | |
9c79ddaa | 332 | if (qede_is_irrelevant_stat(edev, i)) |
fefb0202 | 333 | continue; |
4dbcd640 MY |
334 | strcpy(buf, qede_stats_arr[i].string); |
335 | buf += ETH_GSTRING_LEN; | |
133fac0e | 336 | } |
133fac0e SK |
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; | |
f3e72109 YM |
347 | case ETH_SS_PRIV_FLAGS: |
348 | memcpy(buf, qede_private_arr, | |
349 | ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); | |
350 | break; | |
3044a02e SRK |
351 | case ETH_SS_TEST: |
352 | memcpy(buf, qede_tests_str_arr, | |
353 | ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); | |
354 | break; | |
133fac0e SK |
355 | default: |
356 | DP_VERBOSE(edev, QED_MSG_DEBUG, | |
357 | "Unsupported stringset 0x%08x\n", stringset); | |
358 | } | |
359 | } | |
360 | ||
4dbcd640 MY |
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 | ||
133fac0e SK |
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); | |
4dbcd640 MY |
385 | struct qede_fastpath *fp; |
386 | int i; | |
133fac0e SK |
387 | |
388 | qede_fill_by_demand_stats(edev); | |
389 | ||
567b3c12 MY |
390 | /* Need to protect the access to the fastpath array */ |
391 | __qede_lock(edev); | |
392 | ||
4dbcd640 MY |
393 | for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { |
394 | fp = &edev->fp_array[i]; | |
133fac0e | 395 | |
4dbcd640 MY |
396 | if (fp->type & QEDE_FASTPATH_RX) |
397 | qede_get_ethtool_stats_rxq(fp->rxq, &buf); | |
68db9ec2 | 398 | |
cb6aeb07 MY |
399 | if (fp->type & QEDE_FASTPATH_XDP) |
400 | qede_get_ethtool_stats_txq(fp->xdp_tx, &buf); | |
401 | ||
5e7baf0f MC |
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(&fp->txq[cos], &buf); | |
407 | } | |
68db9ec2 SRK |
408 | } |
409 | ||
42510dff MC |
410 | spin_lock(&edev->stats_lock); |
411 | ||
4dbcd640 | 412 | for (i = 0; i < QEDE_NUM_STATS; i++) { |
9c79ddaa | 413 | if (qede_is_irrelevant_stat(edev, i)) |
fefb0202 | 414 | continue; |
4dbcd640 MY |
415 | *buf = *((u64 *)(((void *)&edev->stats) + |
416 | qede_stats_arr[i].offset)); | |
417 | ||
418 | buf++; | |
fefb0202 | 419 | } |
133fac0e | 420 | |
42510dff MC |
421 | spin_unlock(&edev->stats_lock); |
422 | ||
567b3c12 | 423 | __qede_unlock(edev); |
133fac0e SK |
424 | } |
425 | ||
426 | static int qede_get_sset_count(struct net_device *dev, int stringset) | |
427 | { | |
428 | struct qede_dev *edev = netdev_priv(dev); | |
9c79ddaa | 429 | int num_stats = QEDE_NUM_STATS, i; |
133fac0e SK |
430 | |
431 | switch (stringset) { | |
432 | case ETH_SS_STATS: | |
9c79ddaa MY |
433 | for (i = 0; i < QEDE_NUM_STATS; i++) |
434 | if (qede_is_irrelevant_stat(edev, i)) | |
435 | num_stats--; | |
4dbcd640 MY |
436 | |
437 | /* Account for the Regular Tx statistics */ | |
5e7baf0f MC |
438 | num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * |
439 | edev->dev_info.num_tc; | |
4dbcd640 MY |
440 | |
441 | /* Account for the Regular Rx statistics */ | |
442 | num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; | |
443 | ||
cb6aeb07 MY |
444 | /* Account for XDP statistics [if needed] */ |
445 | if (edev->xdp_prog) | |
446 | num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; | |
4dbcd640 MY |
447 | return num_stats; |
448 | ||
f3e72109 YM |
449 | case ETH_SS_PRIV_FLAGS: |
450 | return QEDE_PRI_FLAG_LEN; | |
3044a02e | 451 | case ETH_SS_TEST: |
6ecb0a0c YM |
452 | if (!IS_VF(edev)) |
453 | return QEDE_ETHTOOL_TEST_MAX; | |
454 | else | |
455 | return 0; | |
133fac0e SK |
456 | default: |
457 | DP_VERBOSE(edev, QED_MSG_DEBUG, | |
458 | "Unsupported stringset 0x%08x\n", stringset); | |
459 | return -EINVAL; | |
460 | } | |
461 | } | |
462 | ||
f3e72109 YM |
463 | static u32 qede_get_priv_flags(struct net_device *dev) |
464 | { | |
465 | struct qede_dev *edev = netdev_priv(dev); | |
823163ba | 466 | bool esl_active; |
f15cff04 | 467 | u32 flags = 0; |
f3e72109 | 468 | |
f15cff04 SRK |
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 | ||
7d9acd87 IR |
475 | if (edev->err_flags & BIT(QEDE_ERR_IS_RECOVERABLE)) |
476 | flags |= BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR); | |
477 | ||
823163ba MC |
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 | ||
f15cff04 | 486 | return flags; |
f3e72109 YM |
487 | } |
488 | ||
7d9acd87 IR |
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, &edev->err_flags); | |
501 | else | |
502 | clear_bit(QEDE_ERR_IS_RECOVERABLE, &edev->err_flags); | |
503 | ||
504 | return 0; | |
505 | } | |
506 | ||
054c67d1 SRK |
507 | static int qede_get_link_ksettings(struct net_device *dev, |
508 | struct ethtool_link_ksettings *cmd) | |
133fac0e | 509 | { |
bdb5d8ec | 510 | typeof(cmd->link_modes) *link_modes = &cmd->link_modes; |
054c67d1 | 511 | struct ethtool_link_settings *base = &cmd->base; |
133fac0e SK |
512 | struct qede_dev *edev = netdev_priv(dev); |
513 | struct qed_link_output current_link; | |
514 | ||
567b3c12 MY |
515 | __qede_lock(edev); |
516 | ||
133fac0e SK |
517 | memset(¤t_link, 0, sizeof(current_link)); |
518 | edev->ops->common->get_link(edev->cdev, ¤t_link); | |
519 | ||
bdb5d8ec AL |
520 | linkmode_copy(link_modes->supported, current_link.supported_caps); |
521 | linkmode_copy(link_modes->advertising, current_link.advertised_caps); | |
522 | linkmode_copy(link_modes->lp_advertising, current_link.lp_caps); | |
054c67d1 | 523 | |
133fac0e | 524 | if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { |
054c67d1 SRK |
525 | base->speed = current_link.speed; |
526 | base->duplex = current_link.duplex; | |
133fac0e | 527 | } else { |
054c67d1 SRK |
528 | base->speed = SPEED_UNKNOWN; |
529 | base->duplex = DUPLEX_UNKNOWN; | |
133fac0e | 530 | } |
567b3c12 MY |
531 | |
532 | __qede_unlock(edev); | |
533 | ||
054c67d1 SRK |
534 | base->port = current_link.port; |
535 | base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : | |
536 | AUTONEG_DISABLE; | |
133fac0e SK |
537 | |
538 | return 0; | |
539 | } | |
540 | ||
054c67d1 SRK |
541 | static int qede_set_link_ksettings(struct net_device *dev, |
542 | const struct ethtool_link_ksettings *cmd) | |
133fac0e | 543 | { |
054c67d1 | 544 | const struct ethtool_link_settings *base = &cmd->base; |
a5b65cd2 | 545 | const struct ethtool_forced_speed_map *map; |
133fac0e SK |
546 | struct qede_dev *edev = netdev_priv(dev); |
547 | struct qed_link_output current_link; | |
548 | struct qed_link_params params; | |
1d4e4ecc | 549 | u32 i; |
133fac0e | 550 | |
fe7cd2bf | 551 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
054c67d1 | 552 | DP_INFO(edev, "Link settings are not allowed to be changed\n"); |
133fac0e SK |
553 | return -EOPNOTSUPP; |
554 | } | |
133fac0e SK |
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 | ||
133fac0e SK |
559 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; |
560 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; | |
bdb5d8ec | 561 | |
054c67d1 | 562 | if (base->autoneg == AUTONEG_ENABLE) { |
bdb5d8ec | 563 | if (!phylink_test(current_link.supported_caps, Autoneg)) { |
161adb04 | 564 | DP_INFO(edev, "Auto negotiation is not supported\n"); |
565 | return -EOPNOTSUPP; | |
566 | } | |
567 | ||
133fac0e SK |
568 | params.autoneg = true; |
569 | params.forced_speed = 0; | |
bdb5d8ec AL |
570 | |
571 | linkmode_copy(params.adv_speeds, cmd->link_modes.advertising); | |
054c67d1 | 572 | } else { /* forced speed */ |
133fac0e SK |
573 | params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; |
574 | params.autoneg = false; | |
054c67d1 | 575 | params.forced_speed = base->speed; |
bdb5d8ec | 576 | |
1d4e4ecc AL |
577 | for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) { |
578 | map = qede_forced_speed_maps + i; | |
bdb5d8ec | 579 | |
1d4e4ecc AL |
580 | if (base->speed != map->speed || |
581 | !linkmode_intersects(current_link.supported_caps, | |
582 | map->caps)) | |
583 | continue; | |
584 | ||
585 | linkmode_and(params.adv_speeds, | |
586 | current_link.supported_caps, map->caps); | |
587 | goto set_link; | |
bdb5d8ec AL |
588 | } |
589 | ||
1d4e4ecc AL |
590 | DP_INFO(edev, "Unsupported speed %u\n", base->speed); |
591 | return -EINVAL; | |
133fac0e SK |
592 | } |
593 | ||
1d4e4ecc | 594 | set_link: |
133fac0e SK |
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(ndev); | |
a88381de | 606 | char mbi[ETHTOOL_FWVERS_LEN]; |
133fac0e | 607 | |
f029c781 | 608 | strscpy(info->driver, "qede", sizeof(info->driver)); |
133fac0e SK |
609 | |
610 | snprintf(storm, ETHTOOL_FWVERS_LEN, "%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(mfw, ETHTOOL_FWVERS_LEN, "%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 | ||
88ea96f8 | 622 | if ((strlen(storm) + strlen("[storm]")) < |
a88381de SRK |
623 | sizeof(info->version)) |
624 | snprintf(info->version, sizeof(info->version), | |
88ea96f8 | 625 | "[storm %s]", storm); |
a88381de SRK |
626 | else |
627 | snprintf(info->version, sizeof(info->version), | |
88ea96f8 | 628 | "%s", storm); |
a88381de SRK |
629 | |
630 | if (edev->dev_info.common.mbi_version) { | |
631 | snprintf(mbi, ETHTOOL_FWVERS_LEN, "%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); | |
133fac0e | 638 | snprintf(info->fw_version, sizeof(info->fw_version), |
a88381de | 639 | "mbi %s [mfw %s]", mbi, mfw); |
133fac0e SK |
640 | } else { |
641 | snprintf(info->fw_version, sizeof(info->fw_version), | |
a88381de | 642 | "mfw %s", mfw); |
133fac0e SK |
643 | } |
644 | ||
f029c781 | 645 | strscpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); |
133fac0e SK |
646 | } |
647 | ||
14d39648 MY |
648 | static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) |
649 | { | |
650 | struct qede_dev *edev = netdev_priv(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(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 | ||
133fac0e SK |
687 | static u32 qede_get_msglevel(struct net_device *ndev) |
688 | { | |
689 | struct qede_dev *edev = netdev_priv(ndev); | |
690 | ||
1a635e48 | 691 | return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; |
133fac0e SK |
692 | } |
693 | ||
694 | static void qede_set_msglevel(struct net_device *ndev, u32 level) | |
695 | { | |
696 | struct qede_dev *edev = netdev_priv(ndev); | |
697 | u32 dp_module = 0; | |
698 | u8 dp_level = 0; | |
699 | ||
700 | qede_config_debug(level, &dp_module, &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 | ||
32a7a570 SK |
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 | ||
fe7cd2bf | 714 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
1a635e48 | 715 | DP_INFO(edev, "Link settings are not allowed to be changed\n"); |
fe7cd2bf YM |
716 | return -EOPNOTSUPP; |
717 | } | |
718 | ||
32a7a570 SK |
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 | ||
133fac0e SK |
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 | ||
ccfa110c SRK |
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 | ||
d552fa84 | 756 | static int qede_get_coalesce(struct net_device *dev, |
f3ccfda1 YM |
757 | struct ethtool_coalesce *coal, |
758 | struct kernel_ethtool_coalesce *kernel_coal, | |
759 | struct netlink_ext_ack *extack) | |
d552fa84 | 760 | { |
bf5a94bf | 761 | void *rx_handle = NULL, *tx_handle = NULL; |
d552fa84 | 762 | struct qede_dev *edev = netdev_priv(dev); |
bf5a94bf RV |
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; | |
d552fa84 SRK |
768 | |
769 | memset(coal, 0, sizeof(struct ethtool_coalesce)); | |
d2890dea | 770 | |
bf5a94bf RV |
771 | __qede_lock(edev); |
772 | if (edev->state == QEDE_STATE_OPEN) { | |
773 | for_each_queue(i) { | |
774 | fp = &edev->fp_array[i]; | |
d552fa84 | 775 | |
bf5a94bf RV |
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) { | |
5e7baf0f MC |
789 | struct qede_tx_queue *txq; |
790 | ||
bf5a94bf | 791 | fp = &edev->fp_array[i]; |
5e7baf0f MC |
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 | */ | |
bf5a94bf | 797 | if (fp->type & QEDE_FASTPATH_TX) { |
5e7baf0f MC |
798 | txq = QEDE_FP_TC0_TXQ(fp); |
799 | tx_handle = txq->handle; | |
bf5a94bf RV |
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; | |
42510dff | 814 | coal->stats_block_coalesce_usecs = edev->stats_coal_usecs; |
bf5a94bf RV |
815 | |
816 | return rc; | |
d552fa84 SRK |
817 | } |
818 | ||
f3ccfda1 YM |
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) | |
d552fa84 SRK |
822 | { |
823 | struct qede_dev *edev = netdev_priv(dev); | |
477f2d14 | 824 | struct qede_fastpath *fp; |
d552fa84 | 825 | int i, rc = 0; |
477f2d14 | 826 | u16 rxc, txc; |
d552fa84 | 827 | |
42510dff MC |
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(edev->stats_coal_usecs); | |
832 | schedule_delayed_work(&edev->periodic_task, 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(&edev->periodic_task); | |
838 | } | |
839 | } | |
840 | ||
d552fa84 SRK |
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", | |
477f2d14 RV |
850 | coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" : |
851 | "tx", QED_COALESCE_MAX); | |
d552fa84 SRK |
852 | return -EINVAL; |
853 | } | |
854 | ||
855 | rxc = (u16)coal->rx_coalesce_usecs; | |
856 | txc = (u16)coal->tx_coalesce_usecs; | |
9a4d7e86 | 857 | for_each_queue(i) { |
477f2d14 RV |
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 | } | |
b0ec5489 BU |
869 | edev->coal_entry[i].rxc = rxc; |
870 | edev->coal_entry[i].isvalid = true; | |
477f2d14 RV |
871 | } |
872 | ||
873 | if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { | |
5e7baf0f MC |
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 | ||
477f2d14 RV |
882 | rc = edev->ops->common->set_coalesce(edev->cdev, |
883 | 0, txc, | |
5e7baf0f | 884 | txq->handle); |
477f2d14 RV |
885 | if (rc) { |
886 | DP_INFO(edev, | |
887 | "Set TX coalesce error, rc = %d\n", rc); | |
888 | return rc; | |
889 | } | |
b0ec5489 BU |
890 | edev->coal_entry[i].txc = txc; |
891 | edev->coal_entry[i].isvalid = true; | |
d552fa84 SRK |
892 | } |
893 | } | |
894 | ||
895 | return rc; | |
896 | } | |
897 | ||
01ef7e05 | 898 | static void qede_get_ringparam(struct net_device *dev, |
74624944 HC |
899 | struct ethtool_ringparam *ering, |
900 | struct kernel_ethtool_ringparam *kernel_ering, | |
901 | struct netlink_ext_ack *extack) | |
01ef7e05 SK |
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, | |
74624944 HC |
912 | struct ethtool_ringparam *ering, |
913 | struct kernel_ethtool_ringparam *kernel_ering, | |
914 | struct netlink_ext_ack *extack) | |
01ef7e05 SK |
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 | ||
567b3c12 | 938 | qede_reload(edev, NULL, false); |
01ef7e05 SK |
939 | |
940 | return 0; | |
941 | } | |
942 | ||
0f7db144 SK |
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 | ||
fe7cd2bf | 972 | if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { |
0f7db144 | 973 | DP_INFO(edev, |
fe7cd2bf | 974 | "Pause settings are not allowed to be changed\n"); |
0f7db144 SK |
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; | |
bdb5d8ec | 983 | |
0f7db144 | 984 | if (epause->autoneg) { |
bdb5d8ec | 985 | if (!phylink_test(current_link.supported_caps, Autoneg)) { |
0f7db144 SK |
986 | DP_INFO(edev, "autoneg not supported\n"); |
987 | return -EINVAL; | |
988 | } | |
bdb5d8ec | 989 | |
0f7db144 SK |
990 | params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; |
991 | } | |
bdb5d8ec | 992 | |
0f7db144 SK |
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 | ||
e0971c83 TT |
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(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(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 | ||
567b3c12 MY |
1026 | static void qede_update_mtu(struct qede_dev *edev, |
1027 | struct qede_reload_args *args) | |
133fac0e | 1028 | { |
1eb2cded | 1029 | WRITE_ONCE(edev->ndev->mtu, args->u.mtu); |
133fac0e SK |
1030 | } |
1031 | ||
1032 | /* Netdevice NDOs */ | |
133fac0e SK |
1033 | int qede_change_mtu(struct net_device *ndev, int new_mtu) |
1034 | { | |
1035 | struct qede_dev *edev = netdev_priv(ndev); | |
567b3c12 | 1036 | struct qede_reload_args args; |
133fac0e | 1037 | |
133fac0e SK |
1038 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1039 | "Configuring MTU size of %d\n", new_mtu); | |
1040 | ||
18c602de MC |
1041 | if (new_mtu > PAGE_SIZE) |
1042 | ndev->features &= ~NETIF_F_GRO_HW; | |
1043 | ||
567b3c12 MY |
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, false); | |
97fb3e33 MK |
1048 | #if IS_ENABLED(CONFIG_QED_RDMA) |
1049 | qede_rdma_event_change_mtu(edev); | |
1050 | #endif | |
567b3c12 | 1051 | edev->ops->common->update_mtu(edev->cdev, new_mtu); |
0fefbfba | 1052 | |
133fac0e SK |
1053 | return 0; |
1054 | } | |
1055 | ||
8edf049d SK |
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); | |
bdc8cbd3 SRK |
1062 | channels->max_rx = QEDE_MAX_RSS_CNT(edev); |
1063 | channels->max_tx = QEDE_MAX_RSS_CNT(edev); | |
9a4d7e86 SRK |
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; | |
8edf049d SK |
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); | |
9a4d7e86 | 1074 | u32 count; |
8edf049d SK |
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 | ||
9a4d7e86 SRK |
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) { | |
8edf049d SK |
1086 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
1087 | "command parameters not supported\n"); | |
1088 | return -EINVAL; | |
1089 | } | |
1090 | ||
9a4d7e86 SRK |
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 | ||
8edf049d | 1105 | /* Check if there was a change in the active parameters */ |
9a4d7e86 SRK |
1106 | if ((count == QEDE_QUEUE_CNT(edev)) && |
1107 | (channels->tx_count == edev->fp_num_tx) && | |
1108 | (channels->rx_count == edev->fp_num_rx)) { | |
8edf049d SK |
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 */ | |
9a4d7e86 SRK |
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)) { | |
8edf049d | 1118 | DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), |
9a4d7e86 | 1119 | "Number of channels must be divisible by %04x\n", |
8edf049d SK |
1120 | edev->dev_info.common.num_hwfns); |
1121 | return -EINVAL; | |
1122 | } | |
1123 | ||
1124 | /* Set number of queues and reload if necessary */ | |
9a4d7e86 SRK |
1125 | edev->req_queues = count; |
1126 | edev->req_num_tx = channels->tx_count; | |
1127 | edev->req_num_rx = channels->rx_count; | |
ed0dd915 SRK |
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; | |
f29ffdb6 | 1131 | memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); |
ed0dd915 SRK |
1132 | } |
1133 | ||
567b3c12 | 1134 | qede_reload(edev, NULL, false); |
8edf049d SK |
1135 | |
1136 | return 0; | |
1137 | } | |
1138 | ||
4c55215c | 1139 | static int qede_get_ts_info(struct net_device *dev, |
2111375b | 1140 | struct kernel_ethtool_ts_info *info) |
4c55215c SRK |
1141 | { |
1142 | struct qede_dev *edev = netdev_priv(dev); | |
1143 | ||
1144 | return qede_ptp_get_ts_info(edev, info); | |
1145 | } | |
1146 | ||
3d971cbd SK |
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 | ||
961acdea SRK |
1175 | static int qede_get_rss_flags(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: | |
f29ffdb6 | 1185 | if (edev->rss_caps & QED_RSS_IPV4_UDP) |
961acdea SRK |
1186 | info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
1187 | break; | |
1188 | case UDP_V6_FLOW: | |
f29ffdb6 | 1189 | if (edev->rss_caps & QED_RSS_IPV6_UDP) |
961acdea SRK |
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, | |
ec9b8dbd | 1204 | u32 *rule_locs) |
961acdea SRK |
1205 | { |
1206 | struct qede_dev *edev = netdev_priv(dev); | |
ec9b8dbd | 1207 | int rc = 0; |
961acdea SRK |
1208 | |
1209 | switch (info->cmd) { | |
1210 | case ETHTOOL_GRXRINGS: | |
9a4d7e86 | 1211 | info->data = QEDE_RSS_COUNT(edev); |
ec9b8dbd | 1212 | break; |
961acdea | 1213 | case ETHTOOL_GRXFH: |
ec9b8dbd CM |
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, info); | |
1222 | break; | |
1223 | case ETHTOOL_GRXCLSRLALL: | |
1224 | rc = qede_get_cls_rule_all(edev, info, rule_locs); | |
1225 | break; | |
961acdea SRK |
1226 | default: |
1227 | DP_ERR(edev, "Command parameters not supported\n"); | |
ec9b8dbd | 1228 | rc = -EOPNOTSUPP; |
961acdea | 1229 | } |
ec9b8dbd CM |
1230 | |
1231 | return rc; | |
961acdea SRK |
1232 | } |
1233 | ||
1234 | static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) | |
1235 | { | |
f29ffdb6 | 1236 | struct qed_update_vport_params *vport_update_params; |
961acdea | 1237 | u8 set_caps = 0, clr_caps = 0; |
f29ffdb6 | 1238 | int rc = 0; |
961acdea SRK |
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 */ | |
f29ffdb6 | 1313 | if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) |
961acdea SRK |
1314 | return 0; |
1315 | ||
1316 | /* Update internal configuration */ | |
f29ffdb6 | 1317 | edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); |
961acdea SRK |
1318 | edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; |
1319 | ||
1320 | /* Re-configure if possible */ | |
f29ffdb6 MY |
1321 | __qede_lock(edev); |
1322 | if (edev->state == QEDE_STATE_OPEN) { | |
1323 | vport_update_params = vzalloc(sizeof(*vport_update_params)); | |
1324 | if (!vport_update_params) { | |
1325 | __qede_unlock(edev); | |
1326 | return -ENOMEM; | |
1327 | } | |
1328 | qede_fill_rss_params(edev, &vport_update_params->rss_params, | |
1329 | &vport_update_params->update_rss_flg); | |
1330 | rc = edev->ops->vport_update(edev->cdev, vport_update_params); | |
1331 | vfree(vport_update_params); | |
961acdea | 1332 | } |
f29ffdb6 | 1333 | __qede_unlock(edev); |
961acdea | 1334 | |
f29ffdb6 | 1335 | return rc; |
961acdea SRK |
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); | |
3f2a2b8b | 1341 | int rc; |
961acdea SRK |
1342 | |
1343 | switch (info->cmd) { | |
1344 | case ETHTOOL_SRXFH: | |
3f2a2b8b CM |
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: | |
2ce9c93e | 1351 | rc = qede_delete_flow_filter(edev, info->fs.location); |
3f2a2b8b | 1352 | break; |
961acdea SRK |
1353 | default: |
1354 | DP_INFO(edev, "Command parameters not supported\n"); | |
3f2a2b8b | 1355 | rc = -EOPNOTSUPP; |
961acdea | 1356 | } |
3f2a2b8b CM |
1357 | |
1358 | return rc; | |
961acdea SRK |
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 | ||
f29ffdb6 | 1370 | return sizeof(edev->rss_key); |
961acdea SRK |
1371 | } |
1372 | ||
fb6e30a7 AZ |
1373 | static int qede_get_rxfh(struct net_device *dev, |
1374 | struct ethtool_rxfh_param *rxfh) | |
961acdea SRK |
1375 | { |
1376 | struct qede_dev *edev = netdev_priv(dev); | |
1377 | int i; | |
1378 | ||
fb6e30a7 | 1379 | rxfh->hfunc = ETH_RSS_HASH_TOP; |
961acdea | 1380 | |
fb6e30a7 | 1381 | if (!rxfh->indir) |
961acdea SRK |
1382 | return 0; |
1383 | ||
1384 | for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) | |
fb6e30a7 | 1385 | rxfh->indir[i] = edev->rss_ind_table[i]; |
961acdea | 1386 | |
fb6e30a7 AZ |
1387 | if (rxfh->key) |
1388 | memcpy(rxfh->key, edev->rss_key, qede_get_rxfh_key_size(dev)); | |
961acdea SRK |
1389 | |
1390 | return 0; | |
1391 | } | |
1392 | ||
fb6e30a7 AZ |
1393 | static int qede_set_rxfh(struct net_device *dev, |
1394 | struct ethtool_rxfh_param *rxfh, | |
1395 | struct netlink_ext_ack *extack) | |
961acdea | 1396 | { |
f29ffdb6 | 1397 | struct qed_update_vport_params *vport_update_params; |
961acdea | 1398 | struct qede_dev *edev = netdev_priv(dev); |
f29ffdb6 | 1399 | int i, rc = 0; |
961acdea | 1400 | |
ba300ce3 SRK |
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 | ||
fb6e30a7 AZ |
1407 | if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && |
1408 | rxfh->hfunc != ETH_RSS_HASH_TOP) | |
961acdea SRK |
1409 | return -EOPNOTSUPP; |
1410 | ||
fb6e30a7 | 1411 | if (!rxfh->indir && !rxfh->key) |
961acdea SRK |
1412 | return 0; |
1413 | ||
fb6e30a7 | 1414 | if (rxfh->indir) { |
961acdea | 1415 | for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) |
fb6e30a7 | 1416 | edev->rss_ind_table[i] = rxfh->indir[i]; |
961acdea SRK |
1417 | edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; |
1418 | } | |
1419 | ||
fb6e30a7 AZ |
1420 | if (rxfh->key) { |
1421 | memcpy(&edev->rss_key, rxfh->key, qede_get_rxfh_key_size(dev)); | |
961acdea SRK |
1422 | edev->rss_params_inited |= QEDE_RSS_KEY_INITED; |
1423 | } | |
1424 | ||
f29ffdb6 MY |
1425 | __qede_lock(edev); |
1426 | if (edev->state == QEDE_STATE_OPEN) { | |
1427 | vport_update_params = vzalloc(sizeof(*vport_update_params)); | |
1428 | if (!vport_update_params) { | |
1429 | __qede_unlock(edev); | |
1430 | return -ENOMEM; | |
1431 | } | |
1432 | qede_fill_rss_params(edev, &vport_update_params->rss_params, | |
1433 | &vport_update_params->update_rss_flg); | |
1434 | rc = edev->ops->vport_update(edev->cdev, vport_update_params); | |
1435 | vfree(vport_update_params); | |
961acdea | 1436 | } |
f29ffdb6 | 1437 | __qede_unlock(edev); |
961acdea | 1438 | |
f29ffdb6 | 1439 | return rc; |
961acdea SRK |
1440 | } |
1441 | ||
16f46bf0 SRK |
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(edev->ndev)) | |
1448 | return; | |
1449 | ||
9a4d7e86 | 1450 | for_each_queue(i) { |
16f46bf0 SRK |
1451 | /* Update and reenable interrupts */ |
1452 | qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); | |
1453 | napi_enable(&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 | ||
9a4d7e86 | 1462 | for_each_queue(i) { |
16f46bf0 SRK |
1463 | napi_disable(&edev->fp_array[i].napi); |
1464 | /* Disable interrupts */ | |
1465 | qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); | |
1466 | } | |
1467 | } | |
1468 | ||
1469 | static int qede_selftest_transmit_traffic(struct qede_dev *edev, | |
1470 | struct sk_buff *skb) | |
1471 | { | |
9a4d7e86 | 1472 | struct qede_tx_queue *txq = NULL; |
16f46bf0 SRK |
1473 | struct eth_tx_1st_bd *first_bd; |
1474 | dma_addr_t mapping; | |
48848a06 MC |
1475 | int i, idx; |
1476 | u16 val; | |
16f46bf0 | 1477 | |
9a4d7e86 | 1478 | for_each_queue(i) { |
5e7baf0f MC |
1479 | struct qede_fastpath *fp = &edev->fp_array[i]; |
1480 | ||
1481 | if (fp->type & QEDE_FASTPATH_TX) { | |
1482 | txq = QEDE_FP_TC0_TXQ(fp); | |
9a4d7e86 SRK |
1483 | break; |
1484 | } | |
1485 | } | |
1486 | ||
1487 | if (!txq) { | |
1488 | DP_NOTICE(edev, "Tx path is not available\n"); | |
1489 | return -1; | |
1490 | } | |
1491 | ||
16f46bf0 | 1492 | /* Fill the entry in the SW ring and the BDs in the FW ring */ |
5a052d62 | 1493 | idx = txq->sw_tx_prod; |
cb6aeb07 | 1494 | txq->sw_tx_ring.skbs[idx].skb = skb; |
16f46bf0 SRK |
1495 | first_bd = qed_chain_produce(&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; | |
351a4ded | 1499 | val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; |
48848a06 MC |
1500 | val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; |
1501 | first_bd->data.bitfields |= cpu_to_le16(val); | |
16f46bf0 SRK |
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; | |
5a052d62 | 1514 | txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; |
16f46bf0 | 1515 | /* 'next page' entries are counted in the producer value */ |
48848a06 MC |
1516 | val = qed_chain_get_prod_idx(&txq->tx_pbl); |
1517 | txq->tx_db.data.bd_prod = cpu_to_le16(val); | |
16f46bf0 SRK |
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(txq->tx_db.raw, txq->doorbell_addr); | |
1525 | ||
16f46bf0 SRK |
1526 | for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { |
1527 | if (qede_txq_has_work(txq)) | |
1528 | break; | |
1529 | usleep_range(100, 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(&txq->tx_pbl); | |
fabd545c MC |
1538 | dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), |
1539 | BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); | |
5a052d62 | 1540 | txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; |
cb6aeb07 | 1541 | txq->sw_tx_ring.skbs[idx].skb = NULL; |
16f46bf0 SRK |
1542 | |
1543 | return 0; | |
1544 | } | |
1545 | ||
1546 | static int qede_selftest_receive_traffic(struct qede_dev *edev) | |
1547 | { | |
10ee4b87 | 1548 | u16 sw_rx_index, len; |
16f46bf0 | 1549 | struct eth_fast_path_rx_reg_cqe *fp_cqe; |
9a4d7e86 | 1550 | struct qede_rx_queue *rxq = NULL; |
16f46bf0 SRK |
1551 | struct sw_rx_data *sw_rx_data; |
1552 | union eth_rx_cqe *cqe; | |
afe981d6 | 1553 | int i, iter, rc = 0; |
16f46bf0 | 1554 | u8 *data_ptr; |
16f46bf0 | 1555 | |
9a4d7e86 SRK |
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 | ||
16f46bf0 SRK |
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 | */ | |
afe981d6 | 1572 | for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { |
837d4eb6 SRK |
1573 | if (!qede_has_rx_work(rxq)) { |
1574 | usleep_range(100, 200); | |
1575 | continue; | |
1576 | } | |
1577 | ||
837d4eb6 SRK |
1578 | /* Get the CQE from the completion ring */ |
1579 | cqe = (union eth_rx_cqe *)qed_chain_consume(&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 + | |
8a863397 MC |
1588 | sw_rx_data->page_offset + |
1589 | rxq->rx_headroom); | |
837d4eb6 SRK |
1590 | if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && |
1591 | ether_addr_equal(data_ptr + ETH_ALEN, | |
1592 | 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 | ||
9eb22357 | 1599 | qede_recycle_rx_bd_ring(rxq, 1); |
837d4eb6 | 1600 | qed_chain_recycle_consumed(&rxq->rx_comp_ring); |
16f46bf0 | 1601 | break; |
837d4eb6 SRK |
1602 | } |
1603 | ||
1604 | DP_INFO(edev, "Not the transmitted packet\n"); | |
9eb22357 | 1605 | qede_recycle_rx_bd_ring(rxq, 1); |
837d4eb6 | 1606 | qed_chain_recycle_consumed(&rxq->rx_comp_ring); |
16f46bf0 SRK |
1607 | } |
1608 | ||
afe981d6 | 1609 | if (iter == QEDE_SELFTEST_POLL_COUNT) { |
16f46bf0 SRK |
1610 | DP_NOTICE(edev, "Failed to receive the traffic\n"); |
1611 | return -1; | |
1612 | } | |
1613 | ||
837d4eb6 | 1614 | qede_update_rx_prod(edev, rxq); |
16f46bf0 | 1615 | |
837d4eb6 | 1616 | return rc; |
16f46bf0 SRK |
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(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(500); | |
1643 | ||
b89869da SRK |
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); | |
16f46bf0 SRK |
1649 | |
1650 | skb = netdev_alloc_skb(edev->ndev, 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, pkt_size); | |
1657 | ether_addr_copy(packet, edev->ndev->dev_addr); | |
1658 | ether_addr_copy(packet + ETH_ALEN, 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(500); | |
1685 | ||
1686 | qede_netif_start(edev); | |
1687 | ||
1688 | return rc; | |
1689 | } | |
1690 | ||
3044a02e SRK |
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 | ||
16f46bf0 SRK |
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 | ||
3044a02e SRK |
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 | } | |
7a4b21b7 MY |
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 | } | |
3044a02e SRK |
1735 | } |
1736 | ||
3d789994 MC |
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 | ||
d80a5233 | 1779 | static int qede_get_eee(struct net_device *dev, struct ethtool_keee *edata) |
c3dc48f7 SRK |
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 | ||
9f8b8adc AL |
1792 | linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1793 | edata->advertised, | |
1794 | current_link.eee.adv_caps & QED_EEE_1G_ADV); | |
1795 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, | |
1796 | edata->advertised, | |
1797 | current_link.eee.adv_caps & QED_EEE_10G_ADV); | |
1798 | ||
1799 | linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, | |
1800 | edata->supported, | |
1801 | current_link.sup_caps & QED_EEE_1G_ADV); | |
1802 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, | |
1803 | edata->supported, | |
1804 | current_link.sup_caps & QED_EEE_10G_ADV); | |
1805 | ||
1806 | linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, | |
1807 | edata->lp_advertised, | |
1808 | current_link.eee.lp_adv_caps & QED_EEE_1G_ADV); | |
1809 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, | |
1810 | edata->lp_advertised, | |
1811 | current_link.eee.lp_adv_caps & QED_EEE_10G_ADV); | |
c3dc48f7 SRK |
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 | ||
d80a5233 | 1821 | static int qede_set_eee(struct net_device *dev, struct ethtool_keee *edata) |
c3dc48f7 | 1822 | { |
9f8b8adc AL |
1823 | __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = {}; |
1824 | __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp) = {}; | |
c3dc48f7 SRK |
1825 | struct qede_dev *edev = netdev_priv(dev); |
1826 | struct qed_link_output current_link; | |
1827 | struct qed_link_params params; | |
9f8b8adc | 1828 | bool unsupp; |
c3dc48f7 SRK |
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 | ||
9f8b8adc AL |
1846 | linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1847 | supported); | |
1848 | linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, | |
1849 | supported); | |
1850 | ||
1851 | unsupp = linkmode_andnot(tmp, edata->advertised, supported); | |
1852 | if (unsupp) { | |
c3dc48f7 | 1853 | DP_VERBOSE(edev, QED_MSG_DEBUG, |
9f8b8adc AL |
1854 | "Invalid advertised capabilities %*pb\n", |
1855 | __ETHTOOL_LINK_MODE_MASK_NBITS, edata->advertised); | |
c3dc48f7 SRK |
1856 | return -EINVAL; |
1857 | } | |
1858 | ||
9f8b8adc AL |
1859 | if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
1860 | edata->advertised)) | |
c3dc48f7 | 1861 | params.eee.adv_caps = QED_EEE_1G_ADV; |
9f8b8adc AL |
1862 | if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, |
1863 | edata->advertised)) | |
1864 | params.eee.adv_caps = QED_EEE_10G_ADV; | |
1865 | ||
c3dc48f7 SRK |
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 | ||
9bdca14a AL |
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(curr_link.active_fec); | |
1922 | fecparam->fec = qede_link_to_ethtool_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(fecparam->fec); | |
1941 | params.link_up = true; | |
1942 | ||
1943 | edev->ops->common->set_link(edev->cdev, ¶ms); | |
1944 | ||
1945 | return 0; | |
1946 | } | |
1947 | ||
97df0d65 SRK |
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 | ||
d44a3ced SRK |
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; | |
849dbf09 SRK |
2059 | case QEDE_DUMP_CMD_GRCDUMP: |
2060 | rc = edev->ops->common->set_grc_config(edev->cdev, | |
2061 | val->flag, 1); | |
2062 | break; | |
d44a3ced SRK |
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 | ||
849dbf09 SRK |
2075 | if (!edev->ops || !edev->ops->common) { |
2076 | DP_ERR(edev, "Edev ops not populated\n"); | |
2077 | return -EINVAL; | |
2078 | } | |
2079 | ||
d44a3ced SRK |
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; | |
9e54ba7c SRK |
2084 | dump->len = edev->ops->common->read_nvm_cfg_len(edev->cdev, |
2085 | edev->dump_info.args[0]); | |
d44a3ced | 2086 | break; |
849dbf09 SRK |
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); | |
d44a3ced | 2090 | break; |
849dbf09 SRK |
2091 | default: |
2092 | DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd); | |
2093 | return -EINVAL; | |
d44a3ced SRK |
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); | |
849dbf09 SRK |
2106 | int rc = 0; |
2107 | ||
2108 | if (!edev->ops || !edev->ops->common) { | |
2109 | DP_ERR(edev, "Edev ops not populated\n"); | |
9e54ba7c SRK |
2110 | rc = -EINVAL; |
2111 | goto err; | |
849dbf09 | 2112 | } |
d44a3ced SRK |
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); | |
9e54ba7c SRK |
2120 | rc = -EINVAL; |
2121 | goto err; | |
d44a3ced SRK |
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; | |
849dbf09 SRK |
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; | |
d44a3ced SRK |
2131 | default: |
2132 | DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd); | |
2133 | rc = -EINVAL; | |
2134 | break; | |
2135 | } | |
2136 | ||
9e54ba7c | 2137 | err: |
d44a3ced SRK |
2138 | edev->dump_info.cmd = QEDE_DUMP_CMD_NONE; |
2139 | edev->dump_info.num_args = 0; | |
9e54ba7c | 2140 | memset(edev->dump_info.args, 0, sizeof(edev->dump_info.args)); |
d44a3ced SRK |
2141 | |
2142 | return rc; | |
2143 | } | |
2144 | ||
b0ec5489 BU |
2145 | int qede_set_per_coalesce(struct net_device *dev, u32 queue, |
2146 | struct ethtool_coalesce *coal) | |
a0d2d97d BU |
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 | } | |
b0ec5489 BU |
2189 | edev->coal_entry[queue].rxc = rxc; |
2190 | edev->coal_entry[queue].isvalid = true; | |
a0d2d97d BU |
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 | } | |
b0ec5489 BU |
2202 | edev->coal_entry[queue].txc = txc; |
2203 | edev->coal_entry[queue].isvalid = true; | |
a0d2d97d BU |
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 | ||
133fac0e | 2268 | static const struct ethtool_ops qede_ethtool_ops = { |
42510dff MC |
2269 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
2270 | ETHTOOL_COALESCE_STATS_BLOCK_USECS, | |
46076157 AL |
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, | |
9bdca14a AL |
2308 | .get_fecparam = qede_get_fecparam, |
2309 | .set_fecparam = qede_set_fecparam, | |
46076157 AL |
2310 | .get_tunable = qede_get_tunable, |
2311 | .set_tunable = qede_set_tunable, | |
a0d2d97d BU |
2312 | .get_per_queue_coalesce = qede_get_per_coalesce, |
2313 | .set_per_queue_coalesce = qede_set_per_coalesce, | |
46076157 AL |
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, | |
133fac0e SK |
2318 | }; |
2319 | ||
fefb0202 | 2320 | static const struct ethtool_ops qede_vf_ethtool_ops = { |
42510dff MC |
2321 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
2322 | ETHTOOL_COALESCE_STATS_BLOCK_USECS, | |
46076157 AL |
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, | |
a0d2d97d BU |
2344 | .get_per_queue_coalesce = qede_get_per_coalesce, |
2345 | .set_per_queue_coalesce = qede_set_per_coalesce, | |
46076157 AL |
2346 | .get_tunable = qede_get_tunable, |
2347 | .set_tunable = qede_set_tunable, | |
fefb0202 YM |
2348 | }; |
2349 | ||
133fac0e SK |
2350 | void qede_set_ethtool_ops(struct net_device *dev) |
2351 | { | |
fefb0202 YM |
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; | |
133fac0e | 2358 | } |