xref: /linux/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c (revision 08990494e59d1ee43f02a687042b7b30ca260bad)
1 /*
2  * aQuantia Corporation Network Driver
3  * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  */
9 
10 /* File aq_ethtool.c: Definition of ethertool related functions. */
11 
12 #include "aq_ethtool.h"
13 #include "aq_nic.h"
14 #include "aq_vec.h"
15 #include "aq_filters.h"
16 
17 static void aq_ethtool_get_regs(struct net_device *ndev,
18 				struct ethtool_regs *regs, void *p)
19 {
20 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
21 	u32 regs_count = aq_nic_get_regs_count(aq_nic);
22 
23 	memset(p, 0, regs_count * sizeof(u32));
24 	aq_nic_get_regs(aq_nic, regs, p);
25 }
26 
27 static int aq_ethtool_get_regs_len(struct net_device *ndev)
28 {
29 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
30 	u32 regs_count = aq_nic_get_regs_count(aq_nic);
31 
32 	return regs_count * sizeof(u32);
33 }
34 
35 static u32 aq_ethtool_get_link(struct net_device *ndev)
36 {
37 	return ethtool_op_get_link(ndev);
38 }
39 
40 static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
41 					 struct ethtool_link_ksettings *cmd)
42 {
43 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
44 
45 	aq_nic_get_link_ksettings(aq_nic, cmd);
46 	cmd->base.speed = netif_carrier_ok(ndev) ?
47 				aq_nic_get_link_speed(aq_nic) : 0U;
48 
49 	return 0;
50 }
51 
52 static int
53 aq_ethtool_set_link_ksettings(struct net_device *ndev,
54 			      const struct ethtool_link_ksettings *cmd)
55 {
56 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
57 
58 	return aq_nic_set_link_ksettings(aq_nic, cmd);
59 }
60 
61 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
62 	"InPackets",
63 	"InUCast",
64 	"InMCast",
65 	"InBCast",
66 	"InErrors",
67 	"OutPackets",
68 	"OutUCast",
69 	"OutMCast",
70 	"OutBCast",
71 	"InUCastOctets",
72 	"OutUCastOctets",
73 	"InMCastOctets",
74 	"OutMCastOctets",
75 	"InBCastOctets",
76 	"OutBCastOctets",
77 	"InOctets",
78 	"OutOctets",
79 	"InPacketsDma",
80 	"OutPacketsDma",
81 	"InOctetsDma",
82 	"OutOctetsDma",
83 	"InDroppedDma",
84 };
85 
86 static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
87 	"Queue[%d] InPackets",
88 	"Queue[%d] OutPackets",
89 	"Queue[%d] Restarts",
90 	"Queue[%d] InJumboPackets",
91 	"Queue[%d] InLroPackets",
92 	"Queue[%d] InErrors",
93 };
94 
95 static void aq_ethtool_stats(struct net_device *ndev,
96 			     struct ethtool_stats *stats, u64 *data)
97 {
98 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
99 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
100 
101 	memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
102 			 ARRAY_SIZE(aq_ethtool_queue_stat_names) *
103 			 cfg->vecs) * sizeof(u64));
104 	aq_nic_get_stats(aq_nic, data);
105 }
106 
107 static void aq_ethtool_get_drvinfo(struct net_device *ndev,
108 				   struct ethtool_drvinfo *drvinfo)
109 {
110 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
111 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
112 	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
113 	u32 firmware_version = aq_nic_get_fw_version(aq_nic);
114 	u32 regs_count = aq_nic_get_regs_count(aq_nic);
115 
116 	strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
117 	strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
118 
119 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
120 		 "%u.%u.%u", firmware_version >> 24,
121 		 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
122 
123 	strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
124 		sizeof(drvinfo->bus_info));
125 	drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
126 		cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
127 	drvinfo->testinfo_len = 0;
128 	drvinfo->regdump_len = regs_count;
129 	drvinfo->eedump_len = 0;
130 }
131 
132 static void aq_ethtool_get_strings(struct net_device *ndev,
133 				   u32 stringset, u8 *data)
134 {
135 	int i, si;
136 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
137 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
138 	u8 *p = data;
139 
140 	if (stringset == ETH_SS_STATS) {
141 		memcpy(p, *aq_ethtool_stat_names,
142 		       sizeof(aq_ethtool_stat_names));
143 		p = p + sizeof(aq_ethtool_stat_names);
144 		for (i = 0; i < cfg->vecs; i++) {
145 			for (si = 0;
146 				si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
147 				si++) {
148 				snprintf(p, ETH_GSTRING_LEN,
149 					 aq_ethtool_queue_stat_names[si], i);
150 				p += ETH_GSTRING_LEN;
151 			}
152 		}
153 	}
154 }
155 
156 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
157 {
158 	int ret = 0;
159 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
160 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
161 
162 	switch (stringset) {
163 	case ETH_SS_STATS:
164 		ret = ARRAY_SIZE(aq_ethtool_stat_names) +
165 			cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
166 		break;
167 	default:
168 		ret = -EOPNOTSUPP;
169 	}
170 	return ret;
171 }
172 
173 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
174 {
175 	return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
176 }
177 
178 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
179 {
180 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
181 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
182 
183 	return sizeof(cfg->aq_rss.hash_secret_key);
184 }
185 
186 static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
187 			      u8 *hfunc)
188 {
189 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
190 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
191 	unsigned int i = 0U;
192 
193 	if (hfunc)
194 		*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
195 	if (indir) {
196 		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
197 			indir[i] = cfg->aq_rss.indirection_table[i];
198 	}
199 	if (key)
200 		memcpy(key, cfg->aq_rss.hash_secret_key,
201 		       sizeof(cfg->aq_rss.hash_secret_key));
202 	return 0;
203 }
204 
205 static int aq_ethtool_get_rxnfc(struct net_device *ndev,
206 				struct ethtool_rxnfc *cmd,
207 				u32 *rule_locs)
208 {
209 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
210 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
211 	int err = 0;
212 
213 	switch (cmd->cmd) {
214 	case ETHTOOL_GRXRINGS:
215 		cmd->data = cfg->vecs;
216 		break;
217 	case ETHTOOL_GRXCLSRLCNT:
218 		cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
219 		break;
220 	case ETHTOOL_GRXCLSRULE:
221 		err = aq_get_rxnfc_rule(aq_nic, cmd);
222 		break;
223 	case ETHTOOL_GRXCLSRLALL:
224 		err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
225 		break;
226 	default:
227 		err = -EOPNOTSUPP;
228 		break;
229 	}
230 
231 	return err;
232 }
233 
234 static int aq_ethtool_set_rxnfc(struct net_device *ndev,
235 				struct ethtool_rxnfc *cmd)
236 {
237 	int err = 0;
238 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
239 
240 	switch (cmd->cmd) {
241 	case ETHTOOL_SRXCLSRLINS:
242 		err = aq_add_rxnfc_rule(aq_nic, cmd);
243 		break;
244 	case ETHTOOL_SRXCLSRLDEL:
245 		err = aq_del_rxnfc_rule(aq_nic, cmd);
246 		break;
247 	default:
248 		err = -EOPNOTSUPP;
249 		break;
250 	}
251 
252 	return err;
253 }
254 
255 static int aq_ethtool_get_coalesce(struct net_device *ndev,
256 				   struct ethtool_coalesce *coal)
257 {
258 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
259 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
260 
261 	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
262 	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
263 		coal->rx_coalesce_usecs = cfg->rx_itr;
264 		coal->tx_coalesce_usecs = cfg->tx_itr;
265 		coal->rx_max_coalesced_frames = 0;
266 		coal->tx_max_coalesced_frames = 0;
267 	} else {
268 		coal->rx_coalesce_usecs = 0;
269 		coal->tx_coalesce_usecs = 0;
270 		coal->rx_max_coalesced_frames = 1;
271 		coal->tx_max_coalesced_frames = 1;
272 	}
273 	return 0;
274 }
275 
276 static int aq_ethtool_set_coalesce(struct net_device *ndev,
277 				   struct ethtool_coalesce *coal)
278 {
279 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
280 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
281 
282 	/* This is not yet supported
283 	 */
284 	if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
285 		return -EOPNOTSUPP;
286 
287 	/* Atlantic only supports timing based coalescing
288 	 */
289 	if (coal->rx_max_coalesced_frames > 1 ||
290 	    coal->rx_coalesce_usecs_irq ||
291 	    coal->rx_max_coalesced_frames_irq)
292 		return -EOPNOTSUPP;
293 
294 	if (coal->tx_max_coalesced_frames > 1 ||
295 	    coal->tx_coalesce_usecs_irq ||
296 	    coal->tx_max_coalesced_frames_irq)
297 		return -EOPNOTSUPP;
298 
299 	/* We do not support frame counting. Check this
300 	 */
301 	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
302 		return -EOPNOTSUPP;
303 	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
304 		return -EOPNOTSUPP;
305 
306 	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
307 	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
308 		return -EINVAL;
309 
310 	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
311 
312 	cfg->rx_itr = coal->rx_coalesce_usecs;
313 	cfg->tx_itr = coal->tx_coalesce_usecs;
314 
315 	return aq_nic_update_interrupt_moderation_settings(aq_nic);
316 }
317 
318 static void aq_ethtool_get_wol(struct net_device *ndev,
319 			       struct ethtool_wolinfo *wol)
320 {
321 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
322 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
323 
324 	wol->supported = WAKE_MAGIC;
325 	wol->wolopts = 0;
326 
327 	if (cfg->wol)
328 		wol->wolopts |= WAKE_MAGIC;
329 }
330 
331 static int aq_ethtool_set_wol(struct net_device *ndev,
332 			      struct ethtool_wolinfo *wol)
333 {
334 	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
335 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
336 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
337 	int err = 0;
338 
339 	if (wol->wolopts & WAKE_MAGIC)
340 		cfg->wol |= AQ_NIC_WOL_ENABLED;
341 	else
342 		cfg->wol &= ~AQ_NIC_WOL_ENABLED;
343 	err = device_set_wakeup_enable(&pdev->dev, wol->wolopts);
344 
345 	return err;
346 }
347 
348 static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
349 {
350 	u32 rate = 0;
351 
352 	if (speed & AQ_NIC_RATE_EEE_10G)
353 		rate |= SUPPORTED_10000baseT_Full;
354 
355 	if (speed & AQ_NIC_RATE_EEE_2GS)
356 		rate |= SUPPORTED_2500baseX_Full;
357 
358 	if (speed & AQ_NIC_RATE_EEE_1G)
359 		rate |= SUPPORTED_1000baseT_Full;
360 
361 	return rate;
362 }
363 
364 static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
365 {
366 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
367 	u32 rate, supported_rates;
368 	int err = 0;
369 
370 	if (!aq_nic->aq_fw_ops->get_eee_rate)
371 		return -EOPNOTSUPP;
372 
373 	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
374 					      &supported_rates);
375 	if (err < 0)
376 		return err;
377 
378 	eee->supported = eee_mask_to_ethtool_mask(supported_rates);
379 
380 	if (aq_nic->aq_nic_cfg.eee_speeds)
381 		eee->advertised = eee->supported;
382 
383 	eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
384 
385 	eee->eee_enabled = !!eee->advertised;
386 
387 	eee->tx_lpi_enabled = eee->eee_enabled;
388 	if (eee->advertised & eee->lp_advertised)
389 		eee->eee_active = true;
390 
391 	return 0;
392 }
393 
394 static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
395 {
396 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
397 	u32 rate, supported_rates;
398 	struct aq_nic_cfg_s *cfg;
399 	int err = 0;
400 
401 	cfg = aq_nic_get_cfg(aq_nic);
402 
403 	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
404 		     !aq_nic->aq_fw_ops->set_eee_rate))
405 		return -EOPNOTSUPP;
406 
407 	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
408 					      &supported_rates);
409 	if (err < 0)
410 		return err;
411 
412 	if (eee->eee_enabled) {
413 		rate = supported_rates;
414 		cfg->eee_speeds = rate;
415 	} else {
416 		rate = 0;
417 		cfg->eee_speeds = 0;
418 	}
419 
420 	return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
421 }
422 
423 static int aq_ethtool_nway_reset(struct net_device *ndev)
424 {
425 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
426 
427 	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
428 		return -EOPNOTSUPP;
429 
430 	if (netif_running(ndev))
431 		return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
432 
433 	return 0;
434 }
435 
436 static void aq_ethtool_get_pauseparam(struct net_device *ndev,
437 				      struct ethtool_pauseparam *pause)
438 {
439 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
440 	u32 fc = aq_nic->aq_nic_cfg.flow_control;
441 
442 	pause->autoneg = 0;
443 
444 	pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
445 	pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
446 
447 }
448 
449 static int aq_ethtool_set_pauseparam(struct net_device *ndev,
450 				     struct ethtool_pauseparam *pause)
451 {
452 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
453 	int err = 0;
454 
455 	if (!aq_nic->aq_fw_ops->set_flow_control)
456 		return -EOPNOTSUPP;
457 
458 	if (pause->autoneg == AUTONEG_ENABLE)
459 		return -EOPNOTSUPP;
460 
461 	if (pause->rx_pause)
462 		aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX;
463 	else
464 		aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX;
465 
466 	if (pause->tx_pause)
467 		aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX;
468 	else
469 		aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
470 
471 	err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
472 
473 	return err;
474 }
475 
476 static void aq_get_ringparam(struct net_device *ndev,
477 			     struct ethtool_ringparam *ring)
478 {
479 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
480 	struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
481 
482 	ring->rx_pending = aq_nic_cfg->rxds;
483 	ring->tx_pending = aq_nic_cfg->txds;
484 
485 	ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max;
486 	ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max;
487 }
488 
489 static int aq_set_ringparam(struct net_device *ndev,
490 			    struct ethtool_ringparam *ring)
491 {
492 	int err = 0;
493 	bool ndev_running = false;
494 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
495 	struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
496 	const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps;
497 
498 	if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
499 		err = -EOPNOTSUPP;
500 		goto err_exit;
501 	}
502 
503 	if (netif_running(ndev)) {
504 		ndev_running = true;
505 		dev_close(ndev);
506 	}
507 
508 	aq_nic_free_vectors(aq_nic);
509 
510 	aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
511 	aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max);
512 	aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE);
513 
514 	aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
515 	aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max);
516 	aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE);
517 
518 	for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs;
519 	     aq_nic->aq_vecs++) {
520 		aq_nic->aq_vec[aq_nic->aq_vecs] =
521 		    aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg);
522 		if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
523 			err = -ENOMEM;
524 			goto err_exit;
525 		}
526 	}
527 	if (ndev_running)
528 		err = dev_open(ndev);
529 
530 err_exit:
531 	return err;
532 }
533 
534 const struct ethtool_ops aq_ethtool_ops = {
535 	.get_link            = aq_ethtool_get_link,
536 	.get_regs_len        = aq_ethtool_get_regs_len,
537 	.get_regs            = aq_ethtool_get_regs,
538 	.get_drvinfo         = aq_ethtool_get_drvinfo,
539 	.get_strings         = aq_ethtool_get_strings,
540 	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
541 	.get_wol             = aq_ethtool_get_wol,
542 	.set_wol             = aq_ethtool_set_wol,
543 	.nway_reset          = aq_ethtool_nway_reset,
544 	.get_ringparam       = aq_get_ringparam,
545 	.set_ringparam       = aq_set_ringparam,
546 	.get_eee             = aq_ethtool_get_eee,
547 	.set_eee             = aq_ethtool_set_eee,
548 	.get_pauseparam      = aq_ethtool_get_pauseparam,
549 	.set_pauseparam      = aq_ethtool_set_pauseparam,
550 	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
551 	.get_rxfh            = aq_ethtool_get_rss,
552 	.get_rxnfc           = aq_ethtool_get_rxnfc,
553 	.set_rxnfc           = aq_ethtool_set_rxnfc,
554 	.get_sset_count      = aq_ethtool_get_sset_count,
555 	.get_ethtool_stats   = aq_ethtool_stats,
556 	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
557 	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
558 	.get_coalesce	     = aq_ethtool_get_coalesce,
559 	.set_coalesce	     = aq_ethtool_set_coalesce,
560 };
561