cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aq_ethtool.c (25748B)


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