xref: /linux/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
3 
4 #include <linux/pci.h>
5 #include <linux/phy.h>
6 #include <linux/ethtool.h>
7 
8 #include "wx_type.h"
9 #include "wx_ethtool.h"
10 #include "wx_hw.h"
11 #include "wx_lib.h"
12 #include "wx_vf_common.h"
13 #include "wx_vf_lib.h"
14 
15 struct wx_stats {
16 	char stat_string[ETH_GSTRING_LEN];
17 	size_t sizeof_stat;
18 	off_t stat_offset;
19 };
20 
21 #define WX_STAT(str, m) { \
22 		.stat_string = str, \
23 		.sizeof_stat = sizeof(((struct wx *)0)->m), \
24 		.stat_offset = offsetof(struct wx, m) }
25 
26 static const struct wx_stats wx_gstrings_stats[] = {
27 	WX_STAT("rx_dma_pkts", stats.gprc),
28 	WX_STAT("tx_dma_pkts", stats.gptc),
29 	WX_STAT("rx_dma_bytes", stats.gorc),
30 	WX_STAT("tx_dma_bytes", stats.gotc),
31 	WX_STAT("rx_total_pkts", stats.tpr),
32 	WX_STAT("tx_total_pkts", stats.tpt),
33 	WX_STAT("rx_long_length_count", stats.roc),
34 	WX_STAT("rx_short_length_count", stats.ruc),
35 	WX_STAT("os2bmc_rx_by_bmc", stats.o2bgptc),
36 	WX_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
37 	WX_STAT("os2bmc_tx_by_host", stats.o2bspc),
38 	WX_STAT("os2bmc_rx_by_host", stats.b2ogprc),
39 	WX_STAT("rx_no_dma_resources", stats.rdmdrop),
40 	WX_STAT("tx_busy", tx_busy),
41 	WX_STAT("non_eop_descs", non_eop_descs),
42 	WX_STAT("tx_restart_queue", restart_queue),
43 	WX_STAT("rx_csum_offload_good_count", hw_csum_rx_good),
44 	WX_STAT("rx_csum_offload_errors", hw_csum_rx_error),
45 	WX_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed),
46 	WX_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
47 	WX_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
48 	WX_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
49 };
50 
51 static const struct wx_stats wx_gstrings_fdir_stats[] = {
52 	WX_STAT("fdir_match", stats.fdirmatch),
53 	WX_STAT("fdir_miss", stats.fdirmiss),
54 };
55 
56 static const struct wx_stats wx_gstrings_rsc_stats[] = {
57 	WX_STAT("rsc_aggregated", rsc_count),
58 	WX_STAT("rsc_flushed", rsc_flush),
59 };
60 
61 /* drivers allocates num_tx_queues and num_rx_queues symmetrically so
62  * we set the num_rx_queues to evaluate to num_tx_queues. This is
63  * used because we do not have a good way to get the max number of
64  * rx queues with CONFIG_RPS disabled.
65  */
66 #define WX_NUM_RX_QUEUES netdev->num_tx_queues
67 #define WX_NUM_TX_QUEUES netdev->num_tx_queues
68 
69 #define WX_QUEUE_STATS_LEN ( \
70 		(WX_NUM_TX_QUEUES + WX_NUM_RX_QUEUES) * \
71 		(sizeof(struct wx_queue_stats) / sizeof(u64)))
72 #define WX_GLOBAL_STATS_LEN  ARRAY_SIZE(wx_gstrings_stats)
73 #define WX_FDIR_STATS_LEN  ARRAY_SIZE(wx_gstrings_fdir_stats)
74 #define WX_RSC_STATS_LEN  ARRAY_SIZE(wx_gstrings_rsc_stats)
75 #define WX_STATS_LEN (WX_GLOBAL_STATS_LEN + WX_QUEUE_STATS_LEN)
76 
wx_get_sset_count(struct net_device * netdev,int sset)77 int wx_get_sset_count(struct net_device *netdev, int sset)
78 {
79 	struct wx *wx = netdev_priv(netdev);
80 	int len = WX_STATS_LEN;
81 
82 	switch (sset) {
83 	case ETH_SS_STATS:
84 		if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
85 			len += WX_FDIR_STATS_LEN;
86 		if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags))
87 			len += WX_RSC_STATS_LEN;
88 		return len;
89 	default:
90 		return -EOPNOTSUPP;
91 	}
92 }
93 EXPORT_SYMBOL(wx_get_sset_count);
94 
wx_get_strings(struct net_device * netdev,u32 stringset,u8 * data)95 void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
96 {
97 	struct wx *wx = netdev_priv(netdev);
98 	u8 *p = data;
99 	int i;
100 
101 	switch (stringset) {
102 	case ETH_SS_STATS:
103 		for (i = 0; i < WX_GLOBAL_STATS_LEN; i++)
104 			ethtool_puts(&p, wx_gstrings_stats[i].stat_string);
105 		if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
106 			for (i = 0; i < WX_FDIR_STATS_LEN; i++)
107 				ethtool_puts(&p, wx_gstrings_fdir_stats[i].stat_string);
108 		}
109 		if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) {
110 			for (i = 0; i < WX_RSC_STATS_LEN; i++)
111 				ethtool_puts(&p, wx_gstrings_rsc_stats[i].stat_string);
112 		}
113 		for (i = 0; i < netdev->num_tx_queues; i++) {
114 			ethtool_sprintf(&p, "tx_queue_%u_packets", i);
115 			ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
116 		}
117 		for (i = 0; i < WX_NUM_RX_QUEUES; i++) {
118 			ethtool_sprintf(&p, "rx_queue_%u_packets", i);
119 			ethtool_sprintf(&p, "rx_queue_%u_bytes", i);
120 		}
121 		break;
122 	}
123 }
124 EXPORT_SYMBOL(wx_get_strings);
125 
wx_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)126 void wx_get_ethtool_stats(struct net_device *netdev,
127 			  struct ethtool_stats *stats, u64 *data)
128 {
129 	struct wx *wx = netdev_priv(netdev);
130 	struct wx_ring *ring;
131 	unsigned int start;
132 	int i, j, k;
133 	char *p;
134 
135 	wx_update_stats(wx);
136 
137 	for (i = 0; i < WX_GLOBAL_STATS_LEN; i++) {
138 		p = (char *)wx + wx_gstrings_stats[i].stat_offset;
139 		data[i] = (wx_gstrings_stats[i].sizeof_stat ==
140 			   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
141 	}
142 
143 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
144 		for (k = 0; k < WX_FDIR_STATS_LEN; k++) {
145 			p = (char *)wx + wx_gstrings_fdir_stats[k].stat_offset;
146 			data[i++] = *(u64 *)p;
147 		}
148 	}
149 
150 	if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) {
151 		for (k = 0; k < WX_RSC_STATS_LEN; k++) {
152 			p = (char *)wx + wx_gstrings_rsc_stats[k].stat_offset;
153 			data[i++] = *(u64 *)p;
154 		}
155 	}
156 
157 	for (j = 0; j < netdev->num_tx_queues; j++) {
158 		ring = wx->tx_ring[j];
159 		if (!ring) {
160 			data[i++] = 0;
161 			data[i++] = 0;
162 			continue;
163 		}
164 
165 		do {
166 			start = u64_stats_fetch_begin(&ring->syncp);
167 			data[i] = ring->stats.packets;
168 			data[i + 1] = ring->stats.bytes;
169 		} while (u64_stats_fetch_retry(&ring->syncp, start));
170 		i += 2;
171 	}
172 	for (j = 0; j < WX_NUM_RX_QUEUES; j++) {
173 		ring = wx->rx_ring[j];
174 		if (!ring) {
175 			data[i++] = 0;
176 			data[i++] = 0;
177 			continue;
178 		}
179 
180 		do {
181 			start = u64_stats_fetch_begin(&ring->syncp);
182 			data[i] = ring->stats.packets;
183 			data[i + 1] = ring->stats.bytes;
184 		} while (u64_stats_fetch_retry(&ring->syncp, start));
185 		i += 2;
186 	}
187 }
188 EXPORT_SYMBOL(wx_get_ethtool_stats);
189 
wx_get_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * mac_stats)190 void wx_get_mac_stats(struct net_device *netdev,
191 		      struct ethtool_eth_mac_stats *mac_stats)
192 {
193 	struct wx *wx = netdev_priv(netdev);
194 	struct wx_hw_stats *hwstats;
195 
196 	wx_update_stats(wx);
197 
198 	hwstats = &wx->stats;
199 	mac_stats->MulticastFramesXmittedOK = hwstats->mptc;
200 	mac_stats->BroadcastFramesXmittedOK = hwstats->bptc;
201 	mac_stats->MulticastFramesReceivedOK = hwstats->mprc;
202 	mac_stats->BroadcastFramesReceivedOK = hwstats->bprc;
203 }
204 EXPORT_SYMBOL(wx_get_mac_stats);
205 
wx_get_pause_stats(struct net_device * netdev,struct ethtool_pause_stats * stats)206 void wx_get_pause_stats(struct net_device *netdev,
207 			struct ethtool_pause_stats *stats)
208 {
209 	struct wx *wx = netdev_priv(netdev);
210 	struct wx_hw_stats *hwstats;
211 
212 	wx_update_stats(wx);
213 
214 	hwstats = &wx->stats;
215 	stats->tx_pause_frames = hwstats->lxontxc + hwstats->lxofftxc;
216 	stats->rx_pause_frames = hwstats->lxonrxc + hwstats->lxoffrxc;
217 }
218 EXPORT_SYMBOL(wx_get_pause_stats);
219 
wx_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)220 void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
221 {
222 	unsigned int stats_len = WX_STATS_LEN;
223 	struct wx *wx = netdev_priv(netdev);
224 
225 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
226 		stats_len += WX_FDIR_STATS_LEN;
227 
228 	strscpy(info->driver, wx->driver_name, sizeof(info->driver));
229 	strscpy(info->fw_version, wx->eeprom_id, sizeof(info->fw_version));
230 	strscpy(info->bus_info, pci_name(wx->pdev), sizeof(info->bus_info));
231 	if (wx->num_tx_queues <= WX_NUM_TX_QUEUES) {
232 		info->n_stats = stats_len -
233 				   (WX_NUM_TX_QUEUES - wx->num_tx_queues) *
234 				   (sizeof(struct wx_queue_stats) / sizeof(u64)) * 2;
235 	} else {
236 		info->n_stats = stats_len;
237 	}
238 }
239 EXPORT_SYMBOL(wx_get_drvinfo);
240 
wx_nway_reset(struct net_device * netdev)241 int wx_nway_reset(struct net_device *netdev)
242 {
243 	struct wx *wx = netdev_priv(netdev);
244 
245 	return phylink_ethtool_nway_reset(wx->phylink);
246 }
247 EXPORT_SYMBOL(wx_nway_reset);
248 
wx_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)249 int wx_get_link_ksettings(struct net_device *netdev,
250 			  struct ethtool_link_ksettings *cmd)
251 {
252 	struct wx *wx = netdev_priv(netdev);
253 
254 	return phylink_ethtool_ksettings_get(wx->phylink, cmd);
255 }
256 EXPORT_SYMBOL(wx_get_link_ksettings);
257 
wx_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)258 int wx_set_link_ksettings(struct net_device *netdev,
259 			  const struct ethtool_link_ksettings *cmd)
260 {
261 	struct wx *wx = netdev_priv(netdev);
262 
263 	return phylink_ethtool_ksettings_set(wx->phylink, cmd);
264 }
265 EXPORT_SYMBOL(wx_set_link_ksettings);
266 
wx_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)267 void wx_get_wol(struct net_device *netdev,
268 		struct ethtool_wolinfo *wol)
269 {
270 	struct wx *wx = netdev_priv(netdev);
271 
272 	if (!wx->wol_hw_supported)
273 		return;
274 	wol->supported = WAKE_MAGIC;
275 	wol->wolopts = 0;
276 	if (wx->wol & WX_PSR_WKUP_CTL_MAG)
277 		wol->wolopts |= WAKE_MAGIC;
278 }
279 EXPORT_SYMBOL(wx_get_wol);
280 
wx_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)281 int wx_set_wol(struct net_device *netdev,
282 	       struct ethtool_wolinfo *wol)
283 {
284 	struct wx *wx = netdev_priv(netdev);
285 	struct pci_dev *pdev = wx->pdev;
286 
287 	if (!wx->wol_hw_supported)
288 		return -EOPNOTSUPP;
289 
290 	wx->wol = 0;
291 	if (wol->wolopts & WAKE_MAGIC)
292 		wx->wol = WX_PSR_WKUP_CTL_MAG;
293 	wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
294 	device_set_wakeup_enable(&pdev->dev, !!(wx->wol));
295 
296 	return 0;
297 }
298 EXPORT_SYMBOL(wx_set_wol);
299 
wx_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)300 void wx_get_pauseparam(struct net_device *netdev,
301 		       struct ethtool_pauseparam *pause)
302 {
303 	struct wx *wx = netdev_priv(netdev);
304 
305 	phylink_ethtool_get_pauseparam(wx->phylink, pause);
306 }
307 EXPORT_SYMBOL(wx_get_pauseparam);
308 
wx_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)309 int wx_set_pauseparam(struct net_device *netdev,
310 		      struct ethtool_pauseparam *pause)
311 {
312 	struct wx *wx = netdev_priv(netdev);
313 
314 	return phylink_ethtool_set_pauseparam(wx->phylink, pause);
315 }
316 EXPORT_SYMBOL(wx_set_pauseparam);
317 
wx_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)318 void wx_get_ringparam(struct net_device *netdev,
319 		      struct ethtool_ringparam *ring,
320 		      struct kernel_ethtool_ringparam *kernel_ring,
321 		      struct netlink_ext_ack *extack)
322 {
323 	struct wx *wx = netdev_priv(netdev);
324 
325 	ring->rx_max_pending = WX_MAX_RXD;
326 	ring->tx_max_pending = WX_MAX_TXD;
327 	ring->rx_mini_max_pending = 0;
328 	ring->rx_jumbo_max_pending = 0;
329 	ring->rx_pending = wx->rx_ring_count;
330 	ring->tx_pending = wx->tx_ring_count;
331 	ring->rx_mini_pending = 0;
332 	ring->rx_jumbo_pending = 0;
333 }
334 EXPORT_SYMBOL(wx_get_ringparam);
335 
wx_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)336 int wx_get_coalesce(struct net_device *netdev,
337 		    struct ethtool_coalesce *ec,
338 		    struct kernel_ethtool_coalesce *kernel_coal,
339 		    struct netlink_ext_ack *extack)
340 {
341 	struct wx *wx = netdev_priv(netdev);
342 
343 	ec->tx_max_coalesced_frames_irq = wx->tx_work_limit;
344 	/* only valid if in constant ITR mode */
345 	if (wx->rx_itr_setting <= 1)
346 		ec->rx_coalesce_usecs = wx->rx_itr_setting;
347 	else
348 		ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2;
349 
350 	if (wx->adaptive_itr) {
351 		ec->use_adaptive_rx_coalesce = 1;
352 		ec->use_adaptive_tx_coalesce = 1;
353 	}
354 
355 	/* if in mixed tx/rx queues per vector mode, report only rx settings */
356 	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
357 		return 0;
358 
359 	/* only valid if in constant ITR mode */
360 	if (wx->tx_itr_setting <= 1)
361 		ec->tx_coalesce_usecs = wx->tx_itr_setting;
362 	else
363 		ec->tx_coalesce_usecs = wx->tx_itr_setting >> 2;
364 
365 	return 0;
366 }
367 EXPORT_SYMBOL(wx_get_coalesce);
368 
wx_update_rsc(struct wx * wx)369 static void wx_update_rsc(struct wx *wx)
370 {
371 	struct net_device *netdev = wx->netdev;
372 	bool need_reset = false;
373 
374 	/* nothing to do if LRO or RSC are not enabled */
375 	if (!test_bit(WX_FLAG_RSC_CAPABLE, wx->flags) ||
376 	    !(netdev->features & NETIF_F_LRO))
377 		return;
378 
379 	/* check the feature flag value and enable RSC if necessary */
380 	if (wx->rx_itr_setting == 1 ||
381 	    wx->rx_itr_setting > WX_MIN_RSC_ITR) {
382 		if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
383 			set_bit(WX_FLAG_RSC_ENABLED, wx->flags);
384 			dev_info(&wx->pdev->dev,
385 				 "rx-usecs value high enough to re-enable RSC\n");
386 
387 			need_reset = true;
388 		}
389 	/* if interrupt rate is too high then disable RSC */
390 	} else if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) {
391 		clear_bit(WX_FLAG_RSC_ENABLED, wx->flags);
392 		dev_info(&wx->pdev->dev,
393 			 "rx-usecs set too low, disabling RSC\n");
394 
395 		need_reset = true;
396 	}
397 
398 	/* reset the device to apply the new RSC setting */
399 	if (need_reset && wx->do_reset)
400 		wx->do_reset(netdev, true);
401 }
402 
wx_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)403 int wx_set_coalesce(struct net_device *netdev,
404 		    struct ethtool_coalesce *ec,
405 		    struct kernel_ethtool_coalesce *kernel_coal,
406 		    struct netlink_ext_ack *extack)
407 {
408 	struct wx *wx = netdev_priv(netdev);
409 	u16 tx_itr_param, rx_itr_param;
410 	struct wx_q_vector *q_vector;
411 	u16 max_eitr;
412 	int i;
413 
414 	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count) {
415 		/* reject Tx specific changes in case of mixed RxTx vectors */
416 		if (ec->tx_coalesce_usecs)
417 			return -EOPNOTSUPP;
418 	}
419 
420 	if (ec->tx_max_coalesced_frames_irq > U16_MAX  ||
421 	    !ec->tx_max_coalesced_frames_irq)
422 		return -EINVAL;
423 
424 	wx->tx_work_limit = ec->tx_max_coalesced_frames_irq;
425 
426 	switch (wx->mac.type) {
427 	case wx_mac_sp:
428 		max_eitr = WX_SP_MAX_EITR;
429 		rx_itr_param = WX_20K_ITR;
430 		tx_itr_param = WX_12K_ITR;
431 		break;
432 	case wx_mac_aml:
433 	case wx_mac_aml40:
434 		max_eitr = WX_AML_MAX_EITR;
435 		rx_itr_param = WX_20K_ITR;
436 		tx_itr_param = WX_12K_ITR;
437 		break;
438 	default:
439 		max_eitr = WX_EM_MAX_EITR;
440 		rx_itr_param = WX_7K_ITR;
441 		tx_itr_param = WX_7K_ITR;
442 		break;
443 	}
444 
445 	if ((ec->rx_coalesce_usecs > (max_eitr >> 2)) ||
446 	    (ec->tx_coalesce_usecs > (max_eitr >> 2)))
447 		return -EINVAL;
448 
449 	if (ec->use_adaptive_rx_coalesce) {
450 		wx->adaptive_itr = true;
451 		wx->rx_itr_setting = 1;
452 		wx->tx_itr_setting = 1;
453 		return 0;
454 	}
455 
456 	if (ec->rx_coalesce_usecs > 1)
457 		wx->rx_itr_setting = ec->rx_coalesce_usecs << 2;
458 	else
459 		wx->rx_itr_setting = ec->rx_coalesce_usecs;
460 
461 	if (ec->tx_coalesce_usecs > 1)
462 		wx->tx_itr_setting = ec->tx_coalesce_usecs << 2;
463 	else
464 		wx->tx_itr_setting = ec->tx_coalesce_usecs;
465 
466 	if (wx->adaptive_itr) {
467 		wx->adaptive_itr = false;
468 		wx->rx_itr_setting = rx_itr_param;
469 		wx->tx_itr_setting = tx_itr_param;
470 	} else if (wx->rx_itr_setting == 1 || wx->tx_itr_setting == 1) {
471 		wx->adaptive_itr = true;
472 	}
473 
474 	if (wx->rx_itr_setting != 1)
475 		rx_itr_param = wx->rx_itr_setting;
476 
477 	if (wx->tx_itr_setting != 1)
478 		tx_itr_param = wx->tx_itr_setting;
479 
480 	/* mixed Rx/Tx */
481 	if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
482 		wx->tx_itr_setting = wx->rx_itr_setting;
483 
484 	for (i = 0; i < wx->num_q_vectors; i++) {
485 		q_vector = wx->q_vector[i];
486 		if (q_vector->tx.count && !q_vector->rx.count)
487 			/* tx only */
488 			q_vector->itr = tx_itr_param;
489 		else
490 			/* rx only or mixed */
491 			q_vector->itr = rx_itr_param;
492 		if (wx->pdev->is_virtfn)
493 			wx_write_eitr_vf(q_vector);
494 		else
495 			wx_write_eitr(q_vector);
496 	}
497 
498 	wx_update_rsc(wx);
499 
500 	return 0;
501 }
502 EXPORT_SYMBOL(wx_set_coalesce);
503 
wx_max_channels(struct wx * wx)504 static unsigned int wx_max_channels(struct wx *wx)
505 {
506 	unsigned int max_combined;
507 
508 	if (!wx->msix_q_entries) {
509 		/* We only support one q_vector without MSI-X */
510 		max_combined = 1;
511 	} else {
512 		/* support up to max allowed queues with RSS */
513 		if (test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags))
514 			max_combined = 63;
515 		else
516 			max_combined = 8;
517 	}
518 
519 	return max_combined;
520 }
521 
wx_get_channels(struct net_device * dev,struct ethtool_channels * ch)522 void wx_get_channels(struct net_device *dev,
523 		     struct ethtool_channels *ch)
524 {
525 	struct wx *wx = netdev_priv(dev);
526 
527 	/* report maximum channels */
528 	ch->max_combined = wx_max_channels(wx);
529 
530 	/* report info for other vector */
531 	if (wx->msix_q_entries) {
532 		ch->max_other = 1;
533 		ch->other_count = 1;
534 	}
535 
536 	/* record RSS queues */
537 	ch->combined_count = wx->ring_feature[RING_F_RSS].indices;
538 
539 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
540 		ch->combined_count = wx->ring_feature[RING_F_FDIR].indices;
541 }
542 EXPORT_SYMBOL(wx_get_channels);
543 
wx_set_channels(struct net_device * dev,struct ethtool_channels * ch)544 int wx_set_channels(struct net_device *dev,
545 		    struct ethtool_channels *ch)
546 {
547 	unsigned int count = ch->combined_count;
548 	struct wx *wx = netdev_priv(dev);
549 
550 	/* verify other_count has not changed */
551 	if (ch->other_count != 1)
552 		return -EINVAL;
553 
554 	/* verify the number of channels does not exceed hardware limits */
555 	if (count > wx_max_channels(wx))
556 		return -EINVAL;
557 
558 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
559 		wx->ring_feature[RING_F_FDIR].limit = count;
560 
561 	wx->ring_feature[RING_F_RSS].limit = count;
562 
563 	return wx->setup_tc(dev, netdev_get_num_tc(dev));
564 }
565 EXPORT_SYMBOL(wx_set_channels);
566 
wx_rss_indir_size(struct net_device * netdev)567 u32 wx_rss_indir_size(struct net_device *netdev)
568 {
569 	struct wx *wx = netdev_priv(netdev);
570 
571 	return wx_rss_indir_tbl_entries(wx);
572 }
573 EXPORT_SYMBOL(wx_rss_indir_size);
574 
wx_get_rxfh_key_size(struct net_device * netdev)575 u32 wx_get_rxfh_key_size(struct net_device *netdev)
576 {
577 	return WX_RSS_KEY_SIZE;
578 }
579 EXPORT_SYMBOL(wx_get_rxfh_key_size);
580 
wx_get_reta(struct wx * wx,u32 * indir)581 static void wx_get_reta(struct wx *wx, u32 *indir)
582 {
583 	u32 reta_size = wx_rss_indir_tbl_entries(wx);
584 	u16 rss_m = wx->ring_feature[RING_F_RSS].mask;
585 
586 	if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags))
587 		rss_m = wx->ring_feature[RING_F_RSS].indices - 1;
588 
589 	for (u32 i = 0; i < reta_size; i++)
590 		indir[i] = wx->rss_indir_tbl[i] & rss_m;
591 }
592 
wx_get_rxfh(struct net_device * netdev,struct ethtool_rxfh_param * rxfh)593 int wx_get_rxfh(struct net_device *netdev,
594 		struct ethtool_rxfh_param *rxfh)
595 {
596 	struct wx *wx = netdev_priv(netdev);
597 
598 	rxfh->hfunc = ETH_RSS_HASH_TOP;
599 
600 	if (rxfh->indir)
601 		wx_get_reta(wx, rxfh->indir);
602 
603 	if (rxfh->key)
604 		memcpy(rxfh->key, wx->rss_key, WX_RSS_KEY_SIZE);
605 
606 	return 0;
607 }
608 EXPORT_SYMBOL(wx_get_rxfh);
609 
wx_set_rxfh(struct net_device * netdev,struct ethtool_rxfh_param * rxfh,struct netlink_ext_ack * extack)610 int wx_set_rxfh(struct net_device *netdev,
611 		struct ethtool_rxfh_param *rxfh,
612 		struct netlink_ext_ack *extack)
613 {
614 	struct wx *wx = netdev_priv(netdev);
615 	u32 reta_entries, i;
616 
617 	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
618 	    rxfh->hfunc != ETH_RSS_HASH_TOP)
619 		return -EOPNOTSUPP;
620 
621 	reta_entries = wx_rss_indir_tbl_entries(wx);
622 	/* Fill out the redirection table */
623 	if (rxfh->indir) {
624 		for (i = 0; i < reta_entries; i++)
625 			wx->rss_indir_tbl[i] = rxfh->indir[i];
626 
627 		wx_store_reta(wx);
628 	}
629 
630 	/* Fill out the rss hash key */
631 	if (rxfh->key) {
632 		memcpy(wx->rss_key, rxfh->key, WX_RSS_KEY_SIZE);
633 		wx_store_rsskey(wx);
634 	}
635 
636 	return 0;
637 }
638 EXPORT_SYMBOL(wx_set_rxfh);
639 
640 static const struct wx_rss_flow_map rss_flow_table[] = {
641 	{ TCP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_TCP },
642 	{ TCP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_TCP },
643 	{ UDP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_UDP },
644 	{ UDP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_UDP },
645 	{ SCTP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_SCTP },
646 	{ SCTP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_SCTP },
647 };
648 
wx_get_rxfh_fields(struct net_device * dev,struct ethtool_rxfh_fields * nfc)649 int wx_get_rxfh_fields(struct net_device *dev,
650 		       struct ethtool_rxfh_fields *nfc)
651 {
652 	struct wx *wx = netdev_priv(dev);
653 
654 	nfc->data = RXH_IP_SRC | RXH_IP_DST;
655 
656 	for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
657 		const struct wx_rss_flow_map *entry = &rss_flow_table[i];
658 
659 		if (entry->flow_type == nfc->flow_type) {
660 			if (wx->rss_flags & entry->flag)
661 				nfc->data |= entry->data;
662 			break;
663 		}
664 	}
665 
666 	return 0;
667 }
668 EXPORT_SYMBOL(wx_get_rxfh_fields);
669 
wx_set_rxfh_fields(struct net_device * dev,const struct ethtool_rxfh_fields * nfc,struct netlink_ext_ack * extack)670 int wx_set_rxfh_fields(struct net_device *dev,
671 		       const struct ethtool_rxfh_fields *nfc,
672 		       struct netlink_ext_ack *extack)
673 {
674 	struct wx *wx = netdev_priv(dev);
675 	u8 flags = wx->rss_flags;
676 
677 	if (!(nfc->data & RXH_IP_SRC) ||
678 	    !(nfc->data & RXH_IP_DST))
679 		return -EINVAL;
680 
681 	for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
682 		const struct wx_rss_flow_map *entry = &rss_flow_table[i];
683 
684 		if (entry->flow_type == nfc->flow_type) {
685 			if (nfc->data & entry->data)
686 				flags |= entry->flag;
687 			else
688 				flags &= ~entry->flag;
689 
690 			if (flags != wx->rss_flags) {
691 				wx->rss_flags = flags;
692 				wx_config_rss_field(wx);
693 			}
694 
695 			return 0;
696 		}
697 	}
698 
699 	return -EINVAL;
700 }
701 EXPORT_SYMBOL(wx_set_rxfh_fields);
702 
wx_get_msglevel(struct net_device * netdev)703 u32 wx_get_msglevel(struct net_device *netdev)
704 {
705 	struct wx *wx = netdev_priv(netdev);
706 
707 	return wx->msg_enable;
708 }
709 EXPORT_SYMBOL(wx_get_msglevel);
710 
wx_set_msglevel(struct net_device * netdev,u32 data)711 void wx_set_msglevel(struct net_device *netdev, u32 data)
712 {
713 	struct wx *wx = netdev_priv(netdev);
714 
715 	wx->msg_enable = data;
716 }
717 EXPORT_SYMBOL(wx_set_msglevel);
718 
wx_get_ts_info(struct net_device * dev,struct kernel_ethtool_ts_info * info)719 int wx_get_ts_info(struct net_device *dev,
720 		   struct kernel_ethtool_ts_info *info)
721 {
722 	struct wx *wx = netdev_priv(dev);
723 
724 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
725 			   BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
726 			   BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
727 			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
728 			   BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
729 			   BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
730 			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
731 			   BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
732 			   BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
733 			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
734 			   BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
735 			   BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
736 
737 	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
738 				SOF_TIMESTAMPING_TX_HARDWARE |
739 				SOF_TIMESTAMPING_RX_HARDWARE |
740 				SOF_TIMESTAMPING_RAW_HARDWARE;
741 
742 	if (wx->ptp_clock)
743 		info->phc_index = ptp_clock_index(wx->ptp_clock);
744 	else
745 		info->phc_index = -1;
746 
747 	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
748 			 BIT(HWTSTAMP_TX_ON);
749 
750 	return 0;
751 }
752 EXPORT_SYMBOL(wx_get_ts_info);
753 
wx_get_ptp_stats(struct net_device * dev,struct ethtool_ts_stats * ts_stats)754 void wx_get_ptp_stats(struct net_device *dev,
755 		      struct ethtool_ts_stats *ts_stats)
756 {
757 	struct wx *wx = netdev_priv(dev);
758 
759 	if (wx->ptp_clock) {
760 		ts_stats->pkts = wx->tx_hwtstamp_pkts;
761 		ts_stats->lost = wx->tx_hwtstamp_timeouts +
762 				 wx->tx_hwtstamp_skipped +
763 				 wx->rx_hwtstamp_cleared;
764 		ts_stats->err = wx->tx_hwtstamp_errors;
765 	}
766 }
767 EXPORT_SYMBOL(wx_get_ptp_stats);
768 
wx_get_link_ksettings_vf(struct net_device * netdev,struct ethtool_link_ksettings * cmd)769 static int wx_get_link_ksettings_vf(struct net_device *netdev,
770 				    struct ethtool_link_ksettings *cmd)
771 {
772 	struct wx *wx = netdev_priv(netdev);
773 
774 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
775 	cmd->base.autoneg = AUTONEG_DISABLE;
776 	cmd->base.port = PORT_NONE;
777 	cmd->base.duplex = DUPLEX_FULL;
778 	cmd->base.speed = wx->speed;
779 
780 	return 0;
781 }
782 
wx_set_ringparam_vf(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)783 static int wx_set_ringparam_vf(struct net_device *netdev,
784 			       struct ethtool_ringparam *ring,
785 			       struct kernel_ethtool_ringparam *kernel_ring,
786 			       struct netlink_ext_ack *extack)
787 {
788 	struct wx *wx = netdev_priv(netdev);
789 	u32 new_rx_count, new_tx_count;
790 	struct wx_ring *temp_ring;
791 	int i, err = 0;
792 
793 	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
794 	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
795 
796 	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
797 	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
798 
799 	if (new_tx_count == wx->tx_ring_count &&
800 	    new_rx_count == wx->rx_ring_count)
801 		return 0;
802 
803 	mutex_lock(&wx->reset_lock);
804 	set_bit(WX_STATE_RESETTING, wx->state);
805 
806 	if (!netif_running(wx->netdev)) {
807 		for (i = 0; i < wx->num_tx_queues; i++)
808 			wx->tx_ring[i]->count = new_tx_count;
809 		for (i = 0; i < wx->num_rx_queues; i++)
810 			wx->rx_ring[i]->count = new_rx_count;
811 		wx->tx_ring_count = new_tx_count;
812 		wx->rx_ring_count = new_rx_count;
813 
814 		goto clear_reset;
815 	}
816 
817 	/* allocate temporary buffer to store rings in */
818 	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
819 	temp_ring = kvmalloc_objs(struct wx_ring, i);
820 	if (!temp_ring) {
821 		err = -ENOMEM;
822 		goto clear_reset;
823 	}
824 
825 	wxvf_down(wx);
826 	/* wx_set_ring() may partially apply changes before
827 	 * returning an error. The error indicates that not all
828 	 * requested ring parameters could be configured.
829 	 */
830 	err = wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
831 	if (err)
832 		wx_err(wx, "failed to set ring parameters: %d", err);
833 	wx_configure_vf(wx);
834 	wxvf_up_complete(wx);
835 	kvfree(temp_ring);
836 clear_reset:
837 	clear_bit(WX_STATE_RESETTING, wx->state);
838 	mutex_unlock(&wx->reset_lock);
839 	return err;
840 }
841 
842 static const struct ethtool_ops wx_ethtool_ops_vf = {
843 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
844 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
845 				     ETHTOOL_COALESCE_USE_ADAPTIVE,
846 	.get_drvinfo		= wx_get_drvinfo,
847 	.get_link		= ethtool_op_get_link,
848 	.get_ringparam		= wx_get_ringparam,
849 	.set_ringparam		= wx_set_ringparam_vf,
850 	.get_msglevel		= wx_get_msglevel,
851 	.get_coalesce		= wx_get_coalesce,
852 	.set_coalesce		= wx_set_coalesce,
853 	.get_ts_info		= ethtool_op_get_ts_info,
854 	.get_link_ksettings	= wx_get_link_ksettings_vf,
855 };
856 
wx_set_ethtool_ops_vf(struct net_device * netdev)857 void wx_set_ethtool_ops_vf(struct net_device *netdev)
858 {
859 	netdev->ethtool_ops = &wx_ethtool_ops_vf;
860 }
861 EXPORT_SYMBOL(wx_set_ethtool_ops_vf);
862