File Index
Files and directories
Sign in
FILE

aq_ethtool.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Atlantic Network Driver
   3 *
   4 * Copyright (C) 2014-2019 aQuantia Corporation
   5 * Copyright (C) 2019-2020 Marvell International Ltd.
   6 */
   7
   8/* File aq_ethtool.c: Definition of ethertool related functions. */
   9
  10#include "aq_ethtool.h"
  11#include "aq_nic.h"
  12#include "aq_vec.h"
  13#include "aq_ptp.h"
  14#include "aq_filters.h"
  15#include "aq_macsec.h"
  16#include "aq_main.h"
  17
  18#include <linux/ethtool.h>
  19#include <linux/linkmode.h>
  20#include <linux/ptp_clock_kernel.h>
  21
  22static void aq_ethtool_get_regs(struct net_device *ndev,
  23				struct ethtool_regs *regs, void *p)
  24{
  25	struct aq_nic_s *aq_nic = netdev_priv(ndev);
  26	u32 regs_count;
  27
  28	regs_count = aq_nic_get_regs_count(aq_nic);
  29
  30	memset(p, 0, regs_count * sizeof(u32));
  31	aq_nic_get_regs(aq_nic, regs, p);
  32}
  33
  34static int aq_ethtool_get_regs_len(struct net_device *ndev)
  35{
  36	struct aq_nic_s *aq_nic = netdev_priv(ndev);
  37	u32 regs_count;
  38
  39	regs_count = aq_nic_get_regs_count(aq_nic);
  40
  41	return regs_count * sizeof(u32);
  42}
  43
  44static u32 aq_ethtool_get_link(struct net_device *ndev)
  45{
  46	return ethtool_op_get_link(ndev);
  47}
  48
  49static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
  50					 struct ethtool_link_ksettings *cmd)
  51{
  52	struct aq_nic_s *aq_nic = netdev_priv(ndev);
  53
  54	aq_nic_get_link_ksettings(aq_nic, cmd);
  55	cmd->base.speed = netif_carrier_ok(ndev) ?
  56				aq_nic_get_link_speed(aq_nic) : 0U;
  57
  58	return 0;
  59}
  60
  61static int
  62aq_ethtool_set_link_ksettings(struct net_device *ndev,
  63			      const struct ethtool_link_ksettings *cmd)
  64{
  65	struct aq_nic_s *aq_nic = netdev_priv(ndev);
  66
  67	return aq_nic_set_link_ksettings(aq_nic, cmd);
  68}
  69
  70static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  71	"InPackets",
  72	"InUCast",
  73	"InMCast",
  74	"InBCast",
  75	"InErrors",
  76	"OutPackets",
  77	"OutUCast",
  78	"OutMCast",
  79	"OutBCast",
  80	"InUCastOctets",
  81	"OutUCastOctets",
  82	"InMCastOctets",
  83	"OutMCastOctets",
  84	"InBCastOctets",
  85	"OutBCastOctets",
  86	"InOctets",
  87	"OutOctets",
  88	"InPacketsDma",
  89	"OutPacketsDma",
  90	"InOctetsDma",
  91	"OutOctetsDma",
  92	"InDroppedDma",
  93};
  94
  95static const char * const aq_ethtool_queue_rx_stat_names[] = {
  96	"%sQueue[%d] InPackets",
  97	"%sQueue[%d] InJumboPackets",
  98	"%sQueue[%d] InLroPackets",
  99	"%sQueue[%d] InErrors",
 100	"%sQueue[%d] AllocFails",
 101	"%sQueue[%d] SkbAllocFails",
 102	"%sQueue[%d] Polls",
 103	"%sQueue[%d] PageFlips",
 104	"%sQueue[%d] PageReuses",
 105	"%sQueue[%d] PageFrees",
 106	"%sQueue[%d] XdpAbort",
 107	"%sQueue[%d] XdpDrop",
 108	"%sQueue[%d] XdpPass",
 109	"%sQueue[%d] XdpTx",
 110	"%sQueue[%d] XdpInvalid",
 111	"%sQueue[%d] XdpRedirect",
 112};
 113
 114static const char * const aq_ethtool_queue_tx_stat_names[] = {
 115	"%sQueue[%d] OutPackets",
 116	"%sQueue[%d] Restarts",
 117};
 118
 119#if IS_ENABLED(CONFIG_MACSEC)
 120static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
 121	"MACSec InCtlPackets",
 122	"MACSec InTaggedMissPackets",
 123	"MACSec InUntaggedMissPackets",
 124	"MACSec InNotagPackets",
 125	"MACSec InUntaggedPackets",
 126	"MACSec InBadTagPackets",
 127	"MACSec InNoSciPackets",
 128	"MACSec InUnknownSciPackets",
 129	"MACSec InCtrlPortPassPackets",
 130	"MACSec InUnctrlPortPassPackets",
 131	"MACSec InCtrlPortFailPackets",
 132	"MACSec InUnctrlPortFailPackets",
 133	"MACSec InTooLongPackets",
 134	"MACSec InIgpocCtlPackets",
 135	"MACSec InEccErrorPackets",
 136	"MACSec InUnctrlHitDropRedir",
 137	"MACSec OutCtlPackets",
 138	"MACSec OutUnknownSaPackets",
 139	"MACSec OutUntaggedPackets",
 140	"MACSec OutTooLong",
 141	"MACSec OutEccErrorPackets",
 142	"MACSec OutUnctrlHitDropRedir",
 143};
 144
 145static const char * const aq_macsec_txsc_stat_names[] = {
 146	"MACSecTXSC%d ProtectedPkts",
 147	"MACSecTXSC%d EncryptedPkts",
 148	"MACSecTXSC%d ProtectedOctets",
 149	"MACSecTXSC%d EncryptedOctets",
 150};
 151
 152static const char * const aq_macsec_txsa_stat_names[] = {
 153	"MACSecTXSC%dSA%d HitDropRedirect",
 154	"MACSecTXSC%dSA%d Protected2Pkts",
 155	"MACSecTXSC%dSA%d ProtectedPkts",
 156	"MACSecTXSC%dSA%d EncryptedPkts",
 157};
 158
 159static const char * const aq_macsec_rxsa_stat_names[] = {
 160	"MACSecRXSC%dSA%d UntaggedHitPkts",
 161	"MACSecRXSC%dSA%d CtrlHitDrpRedir",
 162	"MACSecRXSC%dSA%d NotUsingSa",
 163	"MACSecRXSC%dSA%d UnusedSa",
 164	"MACSecRXSC%dSA%d NotValidPkts",
 165	"MACSecRXSC%dSA%d InvalidPkts",
 166	"MACSecRXSC%dSA%d OkPkts",
 167	"MACSecRXSC%dSA%d LatePkts",
 168	"MACSecRXSC%dSA%d DelayedPkts",
 169	"MACSecRXSC%dSA%d UncheckedPkts",
 170	"MACSecRXSC%dSA%d ValidatedOctets",
 171	"MACSecRXSC%dSA%d DecryptedOctets",
 172};
 173#endif
 174
 175static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
 176	"DMASystemLoopback",
 177	"PKTSystemLoopback",
 178	"DMANetworkLoopback",
 179	"PHYInternalLoopback",
 180	"PHYExternalLoopback",
 181};
 182
 183static u32 aq_ethtool_n_stats(struct net_device *ndev)
 184{
 185	const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
 186	const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
 187	struct aq_nic_s *nic = netdev_priv(ndev);
 188	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
 189	u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
 190		      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
 191
 192#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 193	n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
 194		   tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
 195#endif
 196
 197#if IS_ENABLED(CONFIG_MACSEC)
 198	if (nic->macsec_cfg) {
 199		n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
 200			   ARRAY_SIZE(aq_macsec_txsc_stat_names) *
 201				   aq_macsec_tx_sc_cnt(nic) +
 202			   ARRAY_SIZE(aq_macsec_txsa_stat_names) *
 203				   aq_macsec_tx_sa_cnt(nic) +
 204			   ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
 205				   aq_macsec_rx_sa_cnt(nic);
 206	}
 207#endif
 208
 209	return n_stats;
 210}
 211
 212static void aq_ethtool_stats(struct net_device *ndev,
 213			     struct ethtool_stats *stats, u64 *data)
 214{
 215	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 216
 217	memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
 218	data = aq_nic_get_stats(aq_nic, data);
 219#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 220	data = aq_ptp_get_stats(aq_nic, data);
 221#endif
 222#if IS_ENABLED(CONFIG_MACSEC)
 223	data = aq_macsec_get_stats(aq_nic, data);
 224#endif
 225}
 226
 227static void aq_ethtool_get_drvinfo(struct net_device *ndev,
 228				   struct ethtool_drvinfo *drvinfo)
 229{
 230	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 231	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 232	u32 firmware_version;
 233	u32 regs_count;
 234
 235	firmware_version = aq_nic_get_fw_version(aq_nic);
 236	regs_count = aq_nic_get_regs_count(aq_nic);
 237
 238	strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
 239
 240	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 241		 "%u.%u.%u", firmware_version >> 24,
 242		 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
 243
 244	strscpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
 245		sizeof(drvinfo->bus_info));
 246	drvinfo->n_stats = aq_ethtool_n_stats(ndev);
 247	drvinfo->testinfo_len = 0;
 248	drvinfo->regdump_len = regs_count;
 249	drvinfo->eedump_len = 0;
 250}
 251
 252static void aq_ethtool_get_strings(struct net_device *ndev,
 253				   u32 stringset, u8 *data)
 254{
 255	struct aq_nic_s *nic = netdev_priv(ndev);
 256	struct aq_nic_cfg_s *cfg;
 257	u8 *p = data;
 258	int i, si;
 259#if IS_ENABLED(CONFIG_MACSEC)
 260	int sa;
 261#endif
 262
 263	cfg = aq_nic_get_cfg(nic);
 264
 265	switch (stringset) {
 266	case ETH_SS_STATS: {
 267		const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
 268		const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
 269		char tc_string[8];
 270		unsigned int tc;
 271
 272		memset(tc_string, 0, sizeof(tc_string));
 273		memcpy(p, aq_ethtool_stat_names,
 274		       sizeof(aq_ethtool_stat_names));
 275		p = p + sizeof(aq_ethtool_stat_names);
 276
 277		for (tc = 0; tc < cfg->tcs; tc++) {
 278			if (cfg->is_qos)
 279				snprintf(tc_string, 8, "TC%u ", tc);
 280
 281			for (i = 0; i < cfg->vecs; i++) {
 282				for (si = 0; si < rx_stat_cnt; si++) {
 283					ethtool_sprintf(&p,
 284					     aq_ethtool_queue_rx_stat_names[si],
 285					     tc_string,
 286					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
 287				}
 288				for (si = 0; si < tx_stat_cnt; si++) {
 289					ethtool_sprintf(&p,
 290					     aq_ethtool_queue_tx_stat_names[si],
 291					     tc_string,
 292					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
 293				}
 294			}
 295		}
 296#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 297		if (nic->aq_ptp) {
 298			const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
 299			const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
 300			unsigned int ptp_ring_idx =
 301				aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
 302
 303			snprintf(tc_string, 8, "PTP ");
 304
 305			for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
 306				for (si = 0; si < rx_stat_cnt; si++) {
 307					ethtool_sprintf(&p,
 308						 aq_ethtool_queue_rx_stat_names[si],
 309						 tc_string,
 310						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
 311				}
 312				if (i >= tx_ring_cnt)
 313					continue;
 314				for (si = 0; si < tx_stat_cnt; si++) {
 315					ethtool_sprintf(&p,
 316						 aq_ethtool_queue_tx_stat_names[si],
 317						 tc_string,
 318						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
 319				}
 320			}
 321		}
 322#endif
 323#if IS_ENABLED(CONFIG_MACSEC)
 324		if (!nic->macsec_cfg)
 325			break;
 326
 327		memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
 328		p = p + sizeof(aq_macsec_stat_names);
 329		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
 330			struct aq_macsec_txsc *aq_txsc;
 331
 332			if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
 333				continue;
 334
 335			for (si = 0;
 336				si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
 337				si++) {
 338				ethtool_sprintf(&p,
 339					 aq_macsec_txsc_stat_names[si], i);
 340			}
 341			aq_txsc = &nic->macsec_cfg->aq_txsc[i];
 342			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
 343				if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
 344					continue;
 345				for (si = 0;
 346				     si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
 347				     si++) {
 348					ethtool_sprintf(&p,
 349						 aq_macsec_txsa_stat_names[si],
 350						 i, sa);
 351				}
 352			}
 353		}
 354		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
 355			struct aq_macsec_rxsc *aq_rxsc;
 356
 357			if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
 358				continue;
 359
 360			aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
 361			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
 362				if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
 363					continue;
 364				for (si = 0;
 365				     si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
 366				     si++) {
 367					ethtool_sprintf(&p,
 368						 aq_macsec_rxsa_stat_names[si],
 369						 i, sa);
 370				}
 371			}
 372		}
 373#endif
 374		break;
 375	}
 376	case ETH_SS_PRIV_FLAGS:
 377		memcpy(p, aq_ethtool_priv_flag_names,
 378		       sizeof(aq_ethtool_priv_flag_names));
 379		break;
 380	}
 381}
 382
 383static int aq_ethtool_set_phys_id(struct net_device *ndev,
 384				  enum ethtool_phys_id_state state)
 385{
 386	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 387	struct aq_hw_s *hw = aq_nic->aq_hw;
 388	int ret = 0;
 389
 390	if (!aq_nic->aq_fw_ops->led_control)
 391		return -EOPNOTSUPP;
 392
 393	mutex_lock(&aq_nic->fwreq_mutex);
 394
 395	switch (state) {
 396	case ETHTOOL_ID_ACTIVE:
 397		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
 398				 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
 399		break;
 400	case ETHTOOL_ID_INACTIVE:
 401		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
 402		break;
 403	default:
 404		break;
 405	}
 406
 407	mutex_unlock(&aq_nic->fwreq_mutex);
 408
 409	return ret;
 410}
 411
 412static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
 413{
 414	int ret = 0;
 415
 416	switch (stringset) {
 417	case ETH_SS_STATS:
 418		ret = aq_ethtool_n_stats(ndev);
 419		break;
 420	case ETH_SS_PRIV_FLAGS:
 421		ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
 422		break;
 423	default:
 424		ret = -EOPNOTSUPP;
 425	}
 426
 427	return ret;
 428}
 429
 430static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
 431{
 432	return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
 433}
 434
 435static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
 436{
 437	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 438	struct aq_nic_cfg_s *cfg;
 439
 440	cfg = aq_nic_get_cfg(aq_nic);
 441
 442	return sizeof(cfg->aq_rss.hash_secret_key);
 443}
 444
 445static int aq_ethtool_get_rss(struct net_device *ndev,
 446			      struct ethtool_rxfh_param *rxfh)
 447{
 448	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 449	struct aq_nic_cfg_s *cfg;
 450	unsigned int i = 0U;
 451
 452	cfg = aq_nic_get_cfg(aq_nic);
 453
 454	rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
 455	if (rxfh->indir) {
 456		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
 457			rxfh->indir[i] = cfg->aq_rss.indirection_table[i];
 458	}
 459	if (rxfh->key)
 460		memcpy(rxfh->key, cfg->aq_rss.hash_secret_key,
 461		       sizeof(cfg->aq_rss.hash_secret_key));
 462
 463	return 0;
 464}
 465
 466static int aq_ethtool_set_rss(struct net_device *netdev,
 467			      struct ethtool_rxfh_param *rxfh,
 468			      struct netlink_ext_ack *extack)
 469{
 470	struct aq_nic_s *aq_nic = netdev_priv(netdev);
 471	struct aq_nic_cfg_s *cfg;
 472	unsigned int i = 0U;
 473	u32 rss_entries;
 474	int err = 0;
 475
 476	cfg = aq_nic_get_cfg(aq_nic);
 477	rss_entries = cfg->aq_rss.indirection_table_size;
 478
 479	/* We do not allow change in unsupported parameters */
 480	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
 481	    rxfh->hfunc != ETH_RSS_HASH_TOP)
 482		return -EOPNOTSUPP;
 483	/* Fill out the redirection table */
 484	if (rxfh->indir)
 485		for (i = 0; i < rss_entries; i++)
 486			cfg->aq_rss.indirection_table[i] = rxfh->indir[i];
 487
 488	/* Fill out the rss hash key */
 489	if (rxfh->key) {
 490		memcpy(cfg->aq_rss.hash_secret_key, rxfh->key,
 491		       sizeof(cfg->aq_rss.hash_secret_key));
 492		err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
 493			&cfg->aq_rss);
 494		if (err)
 495			return err;
 496	}
 497
 498	err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
 499
 500	return err;
 501}
 502
 503static int aq_ethtool_get_rxnfc(struct net_device *ndev,
 504				struct ethtool_rxnfc *cmd,
 505				u32 *rule_locs)
 506{
 507	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 508	struct aq_nic_cfg_s *cfg;
 509	int err = 0;
 510
 511	cfg = aq_nic_get_cfg(aq_nic);
 512
 513	switch (cmd->cmd) {
 514	case ETHTOOL_GRXRINGS:
 515		cmd->data = cfg->vecs;
 516		break;
 517	case ETHTOOL_GRXCLSRLCNT:
 518		cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
 519		break;
 520	case ETHTOOL_GRXCLSRULE:
 521		err = aq_get_rxnfc_rule(aq_nic, cmd);
 522		break;
 523	case ETHTOOL_GRXCLSRLALL:
 524		err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
 525		break;
 526	default:
 527		err = -EOPNOTSUPP;
 528		break;
 529	}
 530
 531	return err;
 532}
 533
 534static int aq_ethtool_set_rxnfc(struct net_device *ndev,
 535				struct ethtool_rxnfc *cmd)
 536{
 537	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 538	int err = 0;
 539
 540	switch (cmd->cmd) {
 541	case ETHTOOL_SRXCLSRLINS:
 542		err = aq_add_rxnfc_rule(aq_nic, cmd);
 543		break;
 544	case ETHTOOL_SRXCLSRLDEL:
 545		err = aq_del_rxnfc_rule(aq_nic, cmd);
 546		break;
 547	default:
 548		err = -EOPNOTSUPP;
 549		break;
 550	}
 551
 552	return err;
 553}
 554
 555static int aq_ethtool_get_coalesce(struct net_device *ndev,
 556				   struct ethtool_coalesce *coal,
 557				   struct kernel_ethtool_coalesce *kernel_coal,
 558				   struct netlink_ext_ack *extack)
 559{
 560	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 561	struct aq_nic_cfg_s *cfg;
 562
 563	cfg = aq_nic_get_cfg(aq_nic);
 564
 565	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
 566	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
 567		coal->rx_coalesce_usecs = cfg->rx_itr;
 568		coal->tx_coalesce_usecs = cfg->tx_itr;
 569		coal->rx_max_coalesced_frames = 0;
 570		coal->tx_max_coalesced_frames = 0;
 571	} else {
 572		coal->rx_coalesce_usecs = 0;
 573		coal->tx_coalesce_usecs = 0;
 574		coal->rx_max_coalesced_frames = 1;
 575		coal->tx_max_coalesced_frames = 1;
 576	}
 577
 578	return 0;
 579}
 580
 581static int aq_ethtool_set_coalesce(struct net_device *ndev,
 582				   struct ethtool_coalesce *coal,
 583				   struct kernel_ethtool_coalesce *kernel_coal,
 584				   struct netlink_ext_ack *extack)
 585{
 586	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 587	struct aq_nic_cfg_s *cfg;
 588
 589	cfg = aq_nic_get_cfg(aq_nic);
 590
 591	/* Atlantic only supports timing based coalescing
 592	 */
 593	if (coal->rx_max_coalesced_frames > 1 ||
 594	    coal->tx_max_coalesced_frames > 1)
 595		return -EOPNOTSUPP;
 596
 597	/* We do not support frame counting. Check this
 598	 */
 599	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
 600		return -EOPNOTSUPP;
 601	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
 602		return -EOPNOTSUPP;
 603
 604	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
 605	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
 606		return -EINVAL;
 607
 608	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
 609
 610	cfg->rx_itr = coal->rx_coalesce_usecs;
 611	cfg->tx_itr = coal->tx_coalesce_usecs;
 612
 613	return aq_nic_update_interrupt_moderation_settings(aq_nic);
 614}
 615
 616static void aq_ethtool_get_wol(struct net_device *ndev,
 617			       struct ethtool_wolinfo *wol)
 618{
 619	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 620	struct aq_nic_cfg_s *cfg;
 621
 622	cfg = aq_nic_get_cfg(aq_nic);
 623
 624	wol->supported = AQ_NIC_WOL_MODES;
 625	wol->wolopts = cfg->wol;
 626}
 627
 628static int aq_ethtool_set_wol(struct net_device *ndev,
 629			      struct ethtool_wolinfo *wol)
 630{
 631	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
 632	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 633	struct aq_nic_cfg_s *cfg;
 634	int err = 0;
 635
 636	cfg = aq_nic_get_cfg(aq_nic);
 637
 638	if (wol->wolopts & ~AQ_NIC_WOL_MODES)
 639		return -EOPNOTSUPP;
 640
 641	cfg->wol = wol->wolopts;
 642
 643	err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
 644
 645	return err;
 646}
 647
 648static int aq_ethtool_get_ts_info(struct net_device *ndev,
 649				  struct kernel_ethtool_ts_info *info)
 650{
 651	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 652
 653	ethtool_op_get_ts_info(ndev, info);
 654
 655	if (!aq_nic->aq_ptp)
 656		return 0;
 657
 658	info->so_timestamping |=
 659		SOF_TIMESTAMPING_TX_HARDWARE |
 660		SOF_TIMESTAMPING_RX_HARDWARE |
 661		SOF_TIMESTAMPING_RAW_HARDWARE;
 662
 663	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
 664			 BIT(HWTSTAMP_TX_ON);
 665
 666	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
 667
 668	info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
 669			    BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
 670			    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
 671
 672#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 673	info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
 674#endif
 675
 676	return 0;
 677}
 678
 679static void eee_mask_to_ethtool_mask(unsigned long *mode, u32 speed)
 680{
 681	if (speed & AQ_NIC_RATE_EEE_10G)
 682		linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, mode);
 683
 684	if (speed & AQ_NIC_RATE_EEE_1G)
 685		linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, mode);
 686
 687	if (speed & AQ_NIC_RATE_EEE_100M)
 688		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, mode);
 689}
 690
 691static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_keee *eee)
 692{
 693	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 694	u32 rate, supported_rates;
 695	int err = 0;
 696
 697	if (!aq_nic->aq_fw_ops->get_eee_rate)
 698		return -EOPNOTSUPP;
 699
 700	mutex_lock(&aq_nic->fwreq_mutex);
 701	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 702					      &supported_rates);
 703	mutex_unlock(&aq_nic->fwreq_mutex);
 704	if (err < 0)
 705		return err;
 706
 707	eee_mask_to_ethtool_mask(eee->supported, supported_rates);
 708
 709	if (aq_nic->aq_nic_cfg.eee_speeds)
 710		linkmode_copy(eee->advertised, eee->supported);
 711
 712	eee_mask_to_ethtool_mask(eee->lp_advertised, rate);
 713
 714	eee->eee_enabled = !linkmode_empty(eee->advertised);
 715
 716	eee->tx_lpi_enabled = eee->eee_enabled;
 717	if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
 718		eee->eee_active = true;
 719
 720	return 0;
 721}
 722
 723static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_keee *eee)
 724{
 725	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 726	u32 rate, supported_rates;
 727	struct aq_nic_cfg_s *cfg;
 728	int err = 0;
 729
 730	cfg = aq_nic_get_cfg(aq_nic);
 731
 732	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
 733		     !aq_nic->aq_fw_ops->set_eee_rate))
 734		return -EOPNOTSUPP;
 735
 736	mutex_lock(&aq_nic->fwreq_mutex);
 737	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
 738					      &supported_rates);
 739	mutex_unlock(&aq_nic->fwreq_mutex);
 740	if (err < 0)
 741		return err;
 742
 743	if (eee->eee_enabled) {
 744		rate = supported_rates;
 745		cfg->eee_speeds = rate;
 746	} else {
 747		rate = 0;
 748		cfg->eee_speeds = 0;
 749	}
 750
 751	mutex_lock(&aq_nic->fwreq_mutex);
 752	err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
 753	mutex_unlock(&aq_nic->fwreq_mutex);
 754
 755	return err;
 756}
 757
 758static int aq_ethtool_nway_reset(struct net_device *ndev)
 759{
 760	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 761	int err = 0;
 762
 763	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
 764		return -EOPNOTSUPP;
 765
 766	if (netif_running(ndev)) {
 767		mutex_lock(&aq_nic->fwreq_mutex);
 768		err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
 769		mutex_unlock(&aq_nic->fwreq_mutex);
 770	}
 771
 772	return err;
 773}
 774
 775static void aq_ethtool_get_pauseparam(struct net_device *ndev,
 776				      struct ethtool_pauseparam *pause)
 777{
 778	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 779	int fc = aq_nic->aq_nic_cfg.fc.req;
 780
 781	pause->autoneg = 0;
 782
 783	pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
 784	pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
 785}
 786
 787static int aq_ethtool_set_pauseparam(struct net_device *ndev,
 788				     struct ethtool_pauseparam *pause)
 789{
 790	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 791	int err = 0;
 792
 793	if (!aq_nic->aq_fw_ops->set_flow_control)
 794		return -EOPNOTSUPP;
 795
 796	if (pause->autoneg == AUTONEG_ENABLE)
 797		return -EOPNOTSUPP;
 798
 799	if (pause->rx_pause)
 800		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
 801	else
 802		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
 803
 804	if (pause->tx_pause)
 805		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
 806	else
 807		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
 808
 809	mutex_lock(&aq_nic->fwreq_mutex);
 810	err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
 811	mutex_unlock(&aq_nic->fwreq_mutex);
 812
 813	return err;
 814}
 815
 816static void aq_get_ringparam(struct net_device *ndev,
 817			     struct ethtool_ringparam *ring,
 818			     struct kernel_ethtool_ringparam *kernel_ring,
 819			     struct netlink_ext_ack *extack)
 820{
 821	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 822	struct aq_nic_cfg_s *cfg;
 823
 824	cfg = aq_nic_get_cfg(aq_nic);
 825
 826	ring->rx_pending = cfg->rxds;
 827	ring->tx_pending = cfg->txds;
 828
 829	ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
 830	ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
 831}
 832
 833static int aq_set_ringparam(struct net_device *ndev,
 834			    struct ethtool_ringparam *ring,
 835			    struct kernel_ethtool_ringparam *kernel_ring,
 836			    struct netlink_ext_ack *extack)
 837{
 838	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 839	const struct aq_hw_caps_s *hw_caps;
 840	bool ndev_running = false;
 841	struct aq_nic_cfg_s *cfg;
 842	int err = 0;
 843
 844	cfg = aq_nic_get_cfg(aq_nic);
 845	hw_caps = cfg->aq_hw_caps;
 846
 847	if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
 848		err = -EOPNOTSUPP;
 849		goto err_exit;
 850	}
 851
 852	if (netif_running(ndev)) {
 853		ndev_running = true;
 854		aq_ndev_close(ndev);
 855	}
 856
 857	cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
 858	cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
 859	cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
 860
 861	cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
 862	cfg->txds = min(cfg->txds, hw_caps->txds_max);
 863	cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
 864
 865	err = aq_nic_realloc_vectors(aq_nic);
 866	if (err)
 867		goto err_exit;
 868
 869	if (ndev_running)
 870		err = aq_ndev_open(ndev);
 871
 872err_exit:
 873	return err;
 874}
 875
 876static u32 aq_get_msg_level(struct net_device *ndev)
 877{
 878	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 879
 880	return aq_nic->msg_enable;
 881}
 882
 883static void aq_set_msg_level(struct net_device *ndev, u32 data)
 884{
 885	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 886
 887	aq_nic->msg_enable = data;
 888}
 889
 890static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
 891{
 892	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 893
 894	return aq_nic->aq_nic_cfg.priv_flags;
 895}
 896
 897static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
 898{
 899	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 900	struct aq_nic_cfg_s *cfg;
 901	u32 priv_flags;
 902	int ret = 0;
 903
 904	cfg = aq_nic_get_cfg(aq_nic);
 905	priv_flags = cfg->priv_flags;
 906
 907	if (flags & ~AQ_PRIV_FLAGS_MASK)
 908		return -EOPNOTSUPP;
 909
 910	if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
 911		netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
 912		return -EINVAL;
 913	}
 914
 915	cfg->priv_flags = flags;
 916
 917	if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
 918		if (netif_running(ndev)) {
 919			dev_close(ndev);
 920
 921			dev_open(ndev, NULL);
 922		}
 923	} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
 924		ret = aq_nic_set_loopback(aq_nic);
 925	}
 926
 927	return ret;
 928}
 929
 930static int aq_ethtool_get_phy_tunable(struct net_device *ndev,
 931				      const struct ethtool_tunable *tuna, void *data)
 932{
 933	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 934
 935	switch (tuna->id) {
 936	case ETHTOOL_PHY_EDPD: {
 937		u16 *val = data;
 938
 939		*val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0;
 940		break;
 941	}
 942	case ETHTOOL_PHY_DOWNSHIFT: {
 943		u8 *val = data;
 944
 945		*val = (u8)aq_nic->aq_nic_cfg.downshift_counter;
 946		break;
 947	}
 948	default:
 949		return -EOPNOTSUPP;
 950	}
 951
 952	return 0;
 953}
 954
 955static int aq_ethtool_set_phy_tunable(struct net_device *ndev,
 956				      const struct ethtool_tunable *tuna, const void *data)
 957{
 958	int err = -EOPNOTSUPP;
 959	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 960
 961	switch (tuna->id) {
 962	case ETHTOOL_PHY_EDPD: {
 963		const u16 *val = data;
 964
 965		err = aq_nic_set_media_detect(aq_nic, *val);
 966		break;
 967	}
 968	case ETHTOOL_PHY_DOWNSHIFT: {
 969		const u8 *val = data;
 970
 971		err = aq_nic_set_downshift(aq_nic, *val);
 972		break;
 973	}
 974	default:
 975		break;
 976	}
 977
 978	return err;
 979}
 980
 981static int aq_ethtool_get_module_info(struct net_device *ndev,
 982				      struct ethtool_modinfo *modinfo)
 983{
 984	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 985	u8 compliance_val, dom_type;
 986	int err;
 987
 988	/* Module EEPROM is only supported for controllers with external PHY */
 989	if (aq_nic->aq_nic_cfg.aq_hw_caps->media_type != AQ_HW_MEDIA_TYPE_FIBRE ||
 990	    !aq_nic->aq_hw_ops->hw_read_module_eeprom)
 991		return -EOPNOTSUPP;
 992
 993	err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
 994		SFF_8472_ID_ADDR, SFF_8472_COMP_ADDR, 1, &compliance_val);
 995	if (err)
 996		return err;
 997
 998	err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
 999		SFF_8472_ID_ADDR, SFF_8472_DOM_TYPE_ADDR, 1, &dom_type);
1000	if (err)
1001		return err;
1002
1003	if (dom_type & SFF_8472_ADDRESS_CHANGE_REQ_MASK || compliance_val == 0x00) {
1004		modinfo->type = ETH_MODULE_SFF_8079;
1005		modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
1006	} else {
1007		modinfo->type = ETH_MODULE_SFF_8472;
1008		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
1009	}
1010	return 0;
1011}
1012
1013static int aq_ethtool_get_module_eeprom(struct net_device *ndev,
1014					struct ethtool_eeprom *ee, unsigned char *data)
1015{
1016	struct aq_nic_s *aq_nic = netdev_priv(ndev);
1017	unsigned int first, last, len;
1018	int err;
1019
1020	if (!aq_nic->aq_hw_ops->hw_read_module_eeprom)
1021		return -EOPNOTSUPP;
1022
1023	first = ee->offset;
1024	last = ee->offset + ee->len;
1025
1026	if (first < ETH_MODULE_SFF_8079_LEN) {
1027		len = min(last, ETH_MODULE_SFF_8079_LEN);
1028		len -= first;
1029
1030		err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
1031			SFF_8472_ID_ADDR, first, len, data);
1032		if (err)
1033			return err;
1034
1035		first += len;
1036		data += len;
1037	}
1038	if (first < ETH_MODULE_SFF_8472_LEN && last > ETH_MODULE_SFF_8079_LEN) {
1039		len = min(last, ETH_MODULE_SFF_8472_LEN);
1040		len -= first;
1041		first -= ETH_MODULE_SFF_8079_LEN;
1042
1043		err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
1044			SFF_8472_DIAGNOSTICS_ADDR, first, len, data);
1045		if (err)
1046			return err;
1047	}
1048	return 0;
1049}
1050
1051const struct ethtool_ops aq_ethtool_ops = {
1052	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
1053				     ETHTOOL_COALESCE_MAX_FRAMES,
1054	.get_link            = aq_ethtool_get_link,
1055	.get_regs_len        = aq_ethtool_get_regs_len,
1056	.get_regs            = aq_ethtool_get_regs,
1057	.get_drvinfo         = aq_ethtool_get_drvinfo,
1058	.get_strings         = aq_ethtool_get_strings,
1059	.set_phys_id         = aq_ethtool_set_phys_id,
1060	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
1061	.get_wol             = aq_ethtool_get_wol,
1062	.set_wol             = aq_ethtool_set_wol,
1063	.nway_reset          = aq_ethtool_nway_reset,
1064	.get_ringparam       = aq_get_ringparam,
1065	.set_ringparam       = aq_set_ringparam,
1066	.get_eee             = aq_ethtool_get_eee,
1067	.set_eee             = aq_ethtool_set_eee,
1068	.get_pauseparam      = aq_ethtool_get_pauseparam,
1069	.set_pauseparam      = aq_ethtool_set_pauseparam,
1070	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
1071	.get_rxfh            = aq_ethtool_get_rss,
1072	.set_rxfh            = aq_ethtool_set_rss,
1073	.get_rxnfc           = aq_ethtool_get_rxnfc,
1074	.set_rxnfc           = aq_ethtool_set_rxnfc,
1075	.get_msglevel        = aq_get_msg_level,
1076	.set_msglevel        = aq_set_msg_level,
1077	.get_sset_count      = aq_ethtool_get_sset_count,
1078	.get_ethtool_stats   = aq_ethtool_stats,
1079	.get_priv_flags      = aq_ethtool_get_priv_flags,
1080	.set_priv_flags      = aq_ethtool_set_priv_flags,
1081	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
1082	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
1083	.get_coalesce	     = aq_ethtool_get_coalesce,
1084	.set_coalesce	     = aq_ethtool_set_coalesce,
1085	.get_ts_info         = aq_ethtool_get_ts_info,
1086	.get_phy_tunable     = aq_ethtool_get_phy_tunable,
1087	.set_phy_tunable     = aq_ethtool_set_phy_tunable,
1088	.get_module_info     = aq_ethtool_get_module_info,
1089	.get_module_eeprom   = aq_ethtool_get_module_eeprom,
1090};
~/ Read-only file preview.