brintos

brintos / linux-shallow public Read only

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