18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* Atlantic Network Driver
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2014-2019 aQuantia Corporation
58c2ecf20Sopenharmony_ci * Copyright (C) 2019-2020 Marvell International Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/* File aq_ethtool.c: Definition of ethertool related functions. */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "aq_ethtool.h"
118c2ecf20Sopenharmony_ci#include "aq_nic.h"
128c2ecf20Sopenharmony_ci#include "aq_vec.h"
138c2ecf20Sopenharmony_ci#include "aq_ptp.h"
148c2ecf20Sopenharmony_ci#include "aq_filters.h"
158c2ecf20Sopenharmony_ci#include "aq_macsec.h"
168c2ecf20Sopenharmony_ci#include "aq_main.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/ptp_clock_kernel.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic void aq_ethtool_get_regs(struct net_device *ndev,
218c2ecf20Sopenharmony_ci				struct ethtool_regs *regs, void *p)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
248c2ecf20Sopenharmony_ci	u32 regs_count;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	regs_count = aq_nic_get_regs_count(aq_nic);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	memset(p, 0, regs_count * sizeof(u32));
298c2ecf20Sopenharmony_ci	aq_nic_get_regs(aq_nic, regs, p);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int aq_ethtool_get_regs_len(struct net_device *ndev)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
358c2ecf20Sopenharmony_ci	u32 regs_count;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	regs_count = aq_nic_get_regs_count(aq_nic);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	return regs_count * sizeof(u32);
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic u32 aq_ethtool_get_link(struct net_device *ndev)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	return ethtool_op_get_link(ndev);
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic int aq_ethtool_get_link_ksettings(struct net_device *ndev,
488c2ecf20Sopenharmony_ci					 struct ethtool_link_ksettings *cmd)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	aq_nic_get_link_ksettings(aq_nic, cmd);
538c2ecf20Sopenharmony_ci	cmd->base.speed = netif_carrier_ok(ndev) ?
548c2ecf20Sopenharmony_ci				aq_nic_get_link_speed(aq_nic) : 0U;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic int
608c2ecf20Sopenharmony_ciaq_ethtool_set_link_ksettings(struct net_device *ndev,
618c2ecf20Sopenharmony_ci			      const struct ethtool_link_ksettings *cmd)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	return aq_nic_set_link_ksettings(aq_nic, cmd);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
698c2ecf20Sopenharmony_ci	"InPackets",
708c2ecf20Sopenharmony_ci	"InUCast",
718c2ecf20Sopenharmony_ci	"InMCast",
728c2ecf20Sopenharmony_ci	"InBCast",
738c2ecf20Sopenharmony_ci	"InErrors",
748c2ecf20Sopenharmony_ci	"OutPackets",
758c2ecf20Sopenharmony_ci	"OutUCast",
768c2ecf20Sopenharmony_ci	"OutMCast",
778c2ecf20Sopenharmony_ci	"OutBCast",
788c2ecf20Sopenharmony_ci	"InUCastOctets",
798c2ecf20Sopenharmony_ci	"OutUCastOctets",
808c2ecf20Sopenharmony_ci	"InMCastOctets",
818c2ecf20Sopenharmony_ci	"OutMCastOctets",
828c2ecf20Sopenharmony_ci	"InBCastOctets",
838c2ecf20Sopenharmony_ci	"OutBCastOctets",
848c2ecf20Sopenharmony_ci	"InOctets",
858c2ecf20Sopenharmony_ci	"OutOctets",
868c2ecf20Sopenharmony_ci	"InPacketsDma",
878c2ecf20Sopenharmony_ci	"OutPacketsDma",
888c2ecf20Sopenharmony_ci	"InOctetsDma",
898c2ecf20Sopenharmony_ci	"OutOctetsDma",
908c2ecf20Sopenharmony_ci	"InDroppedDma",
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic const char * const aq_ethtool_queue_rx_stat_names[] = {
948c2ecf20Sopenharmony_ci	"%sQueue[%d] InPackets",
958c2ecf20Sopenharmony_ci	"%sQueue[%d] InJumboPackets",
968c2ecf20Sopenharmony_ci	"%sQueue[%d] InLroPackets",
978c2ecf20Sopenharmony_ci	"%sQueue[%d] InErrors",
988c2ecf20Sopenharmony_ci	"%sQueue[%d] AllocFails",
998c2ecf20Sopenharmony_ci	"%sQueue[%d] SkbAllocFails",
1008c2ecf20Sopenharmony_ci	"%sQueue[%d] Polls",
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic const char * const aq_ethtool_queue_tx_stat_names[] = {
1048c2ecf20Sopenharmony_ci	"%sQueue[%d] OutPackets",
1058c2ecf20Sopenharmony_ci	"%sQueue[%d] Restarts",
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MACSEC)
1098c2ecf20Sopenharmony_cistatic const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
1108c2ecf20Sopenharmony_ci	"MACSec InCtlPackets",
1118c2ecf20Sopenharmony_ci	"MACSec InTaggedMissPackets",
1128c2ecf20Sopenharmony_ci	"MACSec InUntaggedMissPackets",
1138c2ecf20Sopenharmony_ci	"MACSec InNotagPackets",
1148c2ecf20Sopenharmony_ci	"MACSec InUntaggedPackets",
1158c2ecf20Sopenharmony_ci	"MACSec InBadTagPackets",
1168c2ecf20Sopenharmony_ci	"MACSec InNoSciPackets",
1178c2ecf20Sopenharmony_ci	"MACSec InUnknownSciPackets",
1188c2ecf20Sopenharmony_ci	"MACSec InCtrlPortPassPackets",
1198c2ecf20Sopenharmony_ci	"MACSec InUnctrlPortPassPackets",
1208c2ecf20Sopenharmony_ci	"MACSec InCtrlPortFailPackets",
1218c2ecf20Sopenharmony_ci	"MACSec InUnctrlPortFailPackets",
1228c2ecf20Sopenharmony_ci	"MACSec InTooLongPackets",
1238c2ecf20Sopenharmony_ci	"MACSec InIgpocCtlPackets",
1248c2ecf20Sopenharmony_ci	"MACSec InEccErrorPackets",
1258c2ecf20Sopenharmony_ci	"MACSec InUnctrlHitDropRedir",
1268c2ecf20Sopenharmony_ci	"MACSec OutCtlPackets",
1278c2ecf20Sopenharmony_ci	"MACSec OutUnknownSaPackets",
1288c2ecf20Sopenharmony_ci	"MACSec OutUntaggedPackets",
1298c2ecf20Sopenharmony_ci	"MACSec OutTooLong",
1308c2ecf20Sopenharmony_ci	"MACSec OutEccErrorPackets",
1318c2ecf20Sopenharmony_ci	"MACSec OutUnctrlHitDropRedir",
1328c2ecf20Sopenharmony_ci};
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic const char * const aq_macsec_txsc_stat_names[] = {
1358c2ecf20Sopenharmony_ci	"MACSecTXSC%d ProtectedPkts",
1368c2ecf20Sopenharmony_ci	"MACSecTXSC%d EncryptedPkts",
1378c2ecf20Sopenharmony_ci	"MACSecTXSC%d ProtectedOctets",
1388c2ecf20Sopenharmony_ci	"MACSecTXSC%d EncryptedOctets",
1398c2ecf20Sopenharmony_ci};
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic const char * const aq_macsec_txsa_stat_names[] = {
1428c2ecf20Sopenharmony_ci	"MACSecTXSC%dSA%d HitDropRedirect",
1438c2ecf20Sopenharmony_ci	"MACSecTXSC%dSA%d Protected2Pkts",
1448c2ecf20Sopenharmony_ci	"MACSecTXSC%dSA%d ProtectedPkts",
1458c2ecf20Sopenharmony_ci	"MACSecTXSC%dSA%d EncryptedPkts",
1468c2ecf20Sopenharmony_ci};
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic const char * const aq_macsec_rxsa_stat_names[] = {
1498c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d UntaggedHitPkts",
1508c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d CtrlHitDrpRedir",
1518c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d NotUsingSa",
1528c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d UnusedSa",
1538c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d NotValidPkts",
1548c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d InvalidPkts",
1558c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d OkPkts",
1568c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d LatePkts",
1578c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d DelayedPkts",
1588c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d UncheckedPkts",
1598c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d ValidatedOctets",
1608c2ecf20Sopenharmony_ci	"MACSecRXSC%dSA%d DecryptedOctets",
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci#endif
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
1658c2ecf20Sopenharmony_ci	"DMASystemLoopback",
1668c2ecf20Sopenharmony_ci	"PKTSystemLoopback",
1678c2ecf20Sopenharmony_ci	"DMANetworkLoopback",
1688c2ecf20Sopenharmony_ci	"PHYInternalLoopback",
1698c2ecf20Sopenharmony_ci	"PHYExternalLoopback",
1708c2ecf20Sopenharmony_ci};
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic u32 aq_ethtool_n_stats(struct net_device *ndev)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
1758c2ecf20Sopenharmony_ci	const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
1768c2ecf20Sopenharmony_ci	struct aq_nic_s *nic = netdev_priv(ndev);
1778c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
1788c2ecf20Sopenharmony_ci	u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
1798c2ecf20Sopenharmony_ci		      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
1828c2ecf20Sopenharmony_ci	n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
1838c2ecf20Sopenharmony_ci		   tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
1848c2ecf20Sopenharmony_ci#endif
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MACSEC)
1878c2ecf20Sopenharmony_ci	if (nic->macsec_cfg) {
1888c2ecf20Sopenharmony_ci		n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
1898c2ecf20Sopenharmony_ci			   ARRAY_SIZE(aq_macsec_txsc_stat_names) *
1908c2ecf20Sopenharmony_ci				   aq_macsec_tx_sc_cnt(nic) +
1918c2ecf20Sopenharmony_ci			   ARRAY_SIZE(aq_macsec_txsa_stat_names) *
1928c2ecf20Sopenharmony_ci				   aq_macsec_tx_sa_cnt(nic) +
1938c2ecf20Sopenharmony_ci			   ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
1948c2ecf20Sopenharmony_ci				   aq_macsec_rx_sa_cnt(nic);
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci#endif
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	return n_stats;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic void aq_ethtool_stats(struct net_device *ndev,
2028c2ecf20Sopenharmony_ci			     struct ethtool_stats *stats, u64 *data)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
2078c2ecf20Sopenharmony_ci	data = aq_nic_get_stats(aq_nic, data);
2088c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
2098c2ecf20Sopenharmony_ci	data = aq_ptp_get_stats(aq_nic, data);
2108c2ecf20Sopenharmony_ci#endif
2118c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MACSEC)
2128c2ecf20Sopenharmony_ci	data = aq_macsec_get_stats(aq_nic, data);
2138c2ecf20Sopenharmony_ci#endif
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic void aq_ethtool_get_drvinfo(struct net_device *ndev,
2178c2ecf20Sopenharmony_ci				   struct ethtool_drvinfo *drvinfo)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
2208c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
2218c2ecf20Sopenharmony_ci	u32 firmware_version;
2228c2ecf20Sopenharmony_ci	u32 regs_count;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	firmware_version = aq_nic_get_fw_version(aq_nic);
2258c2ecf20Sopenharmony_ci	regs_count = aq_nic_get_regs_count(aq_nic);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
2308c2ecf20Sopenharmony_ci		 "%u.%u.%u", firmware_version >> 24,
2318c2ecf20Sopenharmony_ci		 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
2348c2ecf20Sopenharmony_ci		sizeof(drvinfo->bus_info));
2358c2ecf20Sopenharmony_ci	drvinfo->n_stats = aq_ethtool_n_stats(ndev);
2368c2ecf20Sopenharmony_ci	drvinfo->testinfo_len = 0;
2378c2ecf20Sopenharmony_ci	drvinfo->regdump_len = regs_count;
2388c2ecf20Sopenharmony_ci	drvinfo->eedump_len = 0;
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic void aq_ethtool_get_strings(struct net_device *ndev,
2428c2ecf20Sopenharmony_ci				   u32 stringset, u8 *data)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	struct aq_nic_s *nic = netdev_priv(ndev);
2458c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
2468c2ecf20Sopenharmony_ci	u8 *p = data;
2478c2ecf20Sopenharmony_ci	int i, si;
2488c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MACSEC)
2498c2ecf20Sopenharmony_ci	int sa;
2508c2ecf20Sopenharmony_ci#endif
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(nic);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	switch (stringset) {
2558c2ecf20Sopenharmony_ci	case ETH_SS_STATS: {
2568c2ecf20Sopenharmony_ci		const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
2578c2ecf20Sopenharmony_ci		const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
2588c2ecf20Sopenharmony_ci		char tc_string[8];
2598c2ecf20Sopenharmony_ci		int tc;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		memset(tc_string, 0, sizeof(tc_string));
2628c2ecf20Sopenharmony_ci		memcpy(p, aq_ethtool_stat_names,
2638c2ecf20Sopenharmony_ci		       sizeof(aq_ethtool_stat_names));
2648c2ecf20Sopenharmony_ci		p = p + sizeof(aq_ethtool_stat_names);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci		for (tc = 0; tc < cfg->tcs; tc++) {
2678c2ecf20Sopenharmony_ci			if (cfg->is_qos)
2688c2ecf20Sopenharmony_ci				snprintf(tc_string, 8, "TC%d ", tc);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci			for (i = 0; i < cfg->vecs; i++) {
2718c2ecf20Sopenharmony_ci				for (si = 0; si < rx_stat_cnt; si++) {
2728c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
2738c2ecf20Sopenharmony_ci					     aq_ethtool_queue_rx_stat_names[si],
2748c2ecf20Sopenharmony_ci					     tc_string,
2758c2ecf20Sopenharmony_ci					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
2768c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
2778c2ecf20Sopenharmony_ci				}
2788c2ecf20Sopenharmony_ci				for (si = 0; si < tx_stat_cnt; si++) {
2798c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
2808c2ecf20Sopenharmony_ci					     aq_ethtool_queue_tx_stat_names[si],
2818c2ecf20Sopenharmony_ci					     tc_string,
2828c2ecf20Sopenharmony_ci					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
2838c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
2848c2ecf20Sopenharmony_ci				}
2858c2ecf20Sopenharmony_ci			}
2868c2ecf20Sopenharmony_ci		}
2878c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
2888c2ecf20Sopenharmony_ci		if (nic->aq_ptp) {
2898c2ecf20Sopenharmony_ci			const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
2908c2ecf20Sopenharmony_ci			const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
2918c2ecf20Sopenharmony_ci			unsigned int ptp_ring_idx =
2928c2ecf20Sopenharmony_ci				aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci			snprintf(tc_string, 8, "PTP ");
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci			for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
2978c2ecf20Sopenharmony_ci				for (si = 0; si < rx_stat_cnt; si++) {
2988c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
2998c2ecf20Sopenharmony_ci						 aq_ethtool_queue_rx_stat_names[si],
3008c2ecf20Sopenharmony_ci						 tc_string,
3018c2ecf20Sopenharmony_ci						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
3028c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
3038c2ecf20Sopenharmony_ci				}
3048c2ecf20Sopenharmony_ci				if (i >= tx_ring_cnt)
3058c2ecf20Sopenharmony_ci					continue;
3068c2ecf20Sopenharmony_ci				for (si = 0; si < tx_stat_cnt; si++) {
3078c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
3088c2ecf20Sopenharmony_ci						 aq_ethtool_queue_tx_stat_names[si],
3098c2ecf20Sopenharmony_ci						 tc_string,
3108c2ecf20Sopenharmony_ci						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
3118c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
3128c2ecf20Sopenharmony_ci				}
3138c2ecf20Sopenharmony_ci			}
3148c2ecf20Sopenharmony_ci		}
3158c2ecf20Sopenharmony_ci#endif
3168c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MACSEC)
3178c2ecf20Sopenharmony_ci		if (!nic->macsec_cfg)
3188c2ecf20Sopenharmony_ci			break;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
3218c2ecf20Sopenharmony_ci		p = p + sizeof(aq_macsec_stat_names);
3228c2ecf20Sopenharmony_ci		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
3238c2ecf20Sopenharmony_ci			struct aq_macsec_txsc *aq_txsc;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci			if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
3268c2ecf20Sopenharmony_ci				continue;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci			for (si = 0;
3298c2ecf20Sopenharmony_ci				si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
3308c2ecf20Sopenharmony_ci				si++) {
3318c2ecf20Sopenharmony_ci				snprintf(p, ETH_GSTRING_LEN,
3328c2ecf20Sopenharmony_ci					 aq_macsec_txsc_stat_names[si], i);
3338c2ecf20Sopenharmony_ci				p += ETH_GSTRING_LEN;
3348c2ecf20Sopenharmony_ci			}
3358c2ecf20Sopenharmony_ci			aq_txsc = &nic->macsec_cfg->aq_txsc[i];
3368c2ecf20Sopenharmony_ci			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
3378c2ecf20Sopenharmony_ci				if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
3388c2ecf20Sopenharmony_ci					continue;
3398c2ecf20Sopenharmony_ci				for (si = 0;
3408c2ecf20Sopenharmony_ci				     si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
3418c2ecf20Sopenharmony_ci				     si++) {
3428c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
3438c2ecf20Sopenharmony_ci						 aq_macsec_txsa_stat_names[si],
3448c2ecf20Sopenharmony_ci						 i, sa);
3458c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
3468c2ecf20Sopenharmony_ci				}
3478c2ecf20Sopenharmony_ci			}
3488c2ecf20Sopenharmony_ci		}
3498c2ecf20Sopenharmony_ci		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
3508c2ecf20Sopenharmony_ci			struct aq_macsec_rxsc *aq_rxsc;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci			if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
3538c2ecf20Sopenharmony_ci				continue;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci			aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
3568c2ecf20Sopenharmony_ci			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
3578c2ecf20Sopenharmony_ci				if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
3588c2ecf20Sopenharmony_ci					continue;
3598c2ecf20Sopenharmony_ci				for (si = 0;
3608c2ecf20Sopenharmony_ci				     si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
3618c2ecf20Sopenharmony_ci				     si++) {
3628c2ecf20Sopenharmony_ci					snprintf(p, ETH_GSTRING_LEN,
3638c2ecf20Sopenharmony_ci						 aq_macsec_rxsa_stat_names[si],
3648c2ecf20Sopenharmony_ci						 i, sa);
3658c2ecf20Sopenharmony_ci					p += ETH_GSTRING_LEN;
3668c2ecf20Sopenharmony_ci				}
3678c2ecf20Sopenharmony_ci			}
3688c2ecf20Sopenharmony_ci		}
3698c2ecf20Sopenharmony_ci#endif
3708c2ecf20Sopenharmony_ci		break;
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
3738c2ecf20Sopenharmony_ci		memcpy(p, aq_ethtool_priv_flag_names,
3748c2ecf20Sopenharmony_ci		       sizeof(aq_ethtool_priv_flag_names));
3758c2ecf20Sopenharmony_ci		break;
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic int aq_ethtool_set_phys_id(struct net_device *ndev,
3808c2ecf20Sopenharmony_ci				  enum ethtool_phys_id_state state)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
3838c2ecf20Sopenharmony_ci	struct aq_hw_s *hw = aq_nic->aq_hw;
3848c2ecf20Sopenharmony_ci	int ret = 0;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (!aq_nic->aq_fw_ops->led_control)
3878c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	mutex_lock(&aq_nic->fwreq_mutex);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	switch (state) {
3928c2ecf20Sopenharmony_ci	case ETHTOOL_ID_ACTIVE:
3938c2ecf20Sopenharmony_ci		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
3948c2ecf20Sopenharmony_ci				 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
3958c2ecf20Sopenharmony_ci		break;
3968c2ecf20Sopenharmony_ci	case ETHTOOL_ID_INACTIVE:
3978c2ecf20Sopenharmony_ci		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
3988c2ecf20Sopenharmony_ci		break;
3998c2ecf20Sopenharmony_ci	default:
4008c2ecf20Sopenharmony_ci		break;
4018c2ecf20Sopenharmony_ci	}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	mutex_unlock(&aq_nic->fwreq_mutex);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	return ret;
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	int ret = 0;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	switch (stringset) {
4138c2ecf20Sopenharmony_ci	case ETH_SS_STATS:
4148c2ecf20Sopenharmony_ci		ret = aq_ethtool_n_stats(ndev);
4158c2ecf20Sopenharmony_ci		break;
4168c2ecf20Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
4178c2ecf20Sopenharmony_ci		ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
4188c2ecf20Sopenharmony_ci		break;
4198c2ecf20Sopenharmony_ci	default:
4208c2ecf20Sopenharmony_ci		ret = -EOPNOTSUPP;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	return ret;
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
4348c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	return sizeof(cfg->aq_rss.hash_secret_key);
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
4428c2ecf20Sopenharmony_ci			      u8 *hfunc)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
4458c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
4468c2ecf20Sopenharmony_ci	unsigned int i = 0U;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	if (hfunc)
4518c2ecf20Sopenharmony_ci		*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
4528c2ecf20Sopenharmony_ci	if (indir) {
4538c2ecf20Sopenharmony_ci		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
4548c2ecf20Sopenharmony_ci			indir[i] = cfg->aq_rss.indirection_table[i];
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci	if (key)
4578c2ecf20Sopenharmony_ci		memcpy(key, cfg->aq_rss.hash_secret_key,
4588c2ecf20Sopenharmony_ci		       sizeof(cfg->aq_rss.hash_secret_key));
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	return 0;
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cistatic int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
4648c2ecf20Sopenharmony_ci			      const u8 *key, const u8 hfunc)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(netdev);
4678c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
4688c2ecf20Sopenharmony_ci	unsigned int i = 0U;
4698c2ecf20Sopenharmony_ci	u32 rss_entries;
4708c2ecf20Sopenharmony_ci	int err = 0;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
4738c2ecf20Sopenharmony_ci	rss_entries = cfg->aq_rss.indirection_table_size;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* We do not allow change in unsupported parameters */
4768c2ecf20Sopenharmony_ci	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
4778c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
4788c2ecf20Sopenharmony_ci	/* Fill out the redirection table */
4798c2ecf20Sopenharmony_ci	if (indir)
4808c2ecf20Sopenharmony_ci		for (i = 0; i < rss_entries; i++)
4818c2ecf20Sopenharmony_ci			cfg->aq_rss.indirection_table[i] = indir[i];
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/* Fill out the rss hash key */
4848c2ecf20Sopenharmony_ci	if (key) {
4858c2ecf20Sopenharmony_ci		memcpy(cfg->aq_rss.hash_secret_key, key,
4868c2ecf20Sopenharmony_ci		       sizeof(cfg->aq_rss.hash_secret_key));
4878c2ecf20Sopenharmony_ci		err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
4888c2ecf20Sopenharmony_ci			&cfg->aq_rss);
4898c2ecf20Sopenharmony_ci		if (err)
4908c2ecf20Sopenharmony_ci			return err;
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	return err;
4968c2ecf20Sopenharmony_ci}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_cistatic int aq_ethtool_get_rxnfc(struct net_device *ndev,
4998c2ecf20Sopenharmony_ci				struct ethtool_rxnfc *cmd,
5008c2ecf20Sopenharmony_ci				u32 *rule_locs)
5018c2ecf20Sopenharmony_ci{
5028c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5038c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
5048c2ecf20Sopenharmony_ci	int err = 0;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	switch (cmd->cmd) {
5098c2ecf20Sopenharmony_ci	case ETHTOOL_GRXRINGS:
5108c2ecf20Sopenharmony_ci		cmd->data = cfg->vecs;
5118c2ecf20Sopenharmony_ci		break;
5128c2ecf20Sopenharmony_ci	case ETHTOOL_GRXCLSRLCNT:
5138c2ecf20Sopenharmony_ci		cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
5148c2ecf20Sopenharmony_ci		break;
5158c2ecf20Sopenharmony_ci	case ETHTOOL_GRXCLSRULE:
5168c2ecf20Sopenharmony_ci		err = aq_get_rxnfc_rule(aq_nic, cmd);
5178c2ecf20Sopenharmony_ci		break;
5188c2ecf20Sopenharmony_ci	case ETHTOOL_GRXCLSRLALL:
5198c2ecf20Sopenharmony_ci		err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
5208c2ecf20Sopenharmony_ci		break;
5218c2ecf20Sopenharmony_ci	default:
5228c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
5238c2ecf20Sopenharmony_ci		break;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	return err;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic int aq_ethtool_set_rxnfc(struct net_device *ndev,
5308c2ecf20Sopenharmony_ci				struct ethtool_rxnfc *cmd)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5338c2ecf20Sopenharmony_ci	int err = 0;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	switch (cmd->cmd) {
5368c2ecf20Sopenharmony_ci	case ETHTOOL_SRXCLSRLINS:
5378c2ecf20Sopenharmony_ci		err = aq_add_rxnfc_rule(aq_nic, cmd);
5388c2ecf20Sopenharmony_ci		break;
5398c2ecf20Sopenharmony_ci	case ETHTOOL_SRXCLSRLDEL:
5408c2ecf20Sopenharmony_ci		err = aq_del_rxnfc_rule(aq_nic, cmd);
5418c2ecf20Sopenharmony_ci		break;
5428c2ecf20Sopenharmony_ci	default:
5438c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
5448c2ecf20Sopenharmony_ci		break;
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	return err;
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_cistatic int aq_ethtool_get_coalesce(struct net_device *ndev,
5518c2ecf20Sopenharmony_ci				   struct ethtool_coalesce *coal)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5548c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
5598c2ecf20Sopenharmony_ci	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
5608c2ecf20Sopenharmony_ci		coal->rx_coalesce_usecs = cfg->rx_itr;
5618c2ecf20Sopenharmony_ci		coal->tx_coalesce_usecs = cfg->tx_itr;
5628c2ecf20Sopenharmony_ci		coal->rx_max_coalesced_frames = 0;
5638c2ecf20Sopenharmony_ci		coal->tx_max_coalesced_frames = 0;
5648c2ecf20Sopenharmony_ci	} else {
5658c2ecf20Sopenharmony_ci		coal->rx_coalesce_usecs = 0;
5668c2ecf20Sopenharmony_ci		coal->tx_coalesce_usecs = 0;
5678c2ecf20Sopenharmony_ci		coal->rx_max_coalesced_frames = 1;
5688c2ecf20Sopenharmony_ci		coal->tx_max_coalesced_frames = 1;
5698c2ecf20Sopenharmony_ci	}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	return 0;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int aq_ethtool_set_coalesce(struct net_device *ndev,
5758c2ecf20Sopenharmony_ci				   struct ethtool_coalesce *coal)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5788c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	/* Atlantic only supports timing based coalescing
5838c2ecf20Sopenharmony_ci	 */
5848c2ecf20Sopenharmony_ci	if (coal->rx_max_coalesced_frames > 1 ||
5858c2ecf20Sopenharmony_ci	    coal->tx_max_coalesced_frames > 1)
5868c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	/* We do not support frame counting. Check this
5898c2ecf20Sopenharmony_ci	 */
5908c2ecf20Sopenharmony_ci	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
5918c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
5928c2ecf20Sopenharmony_ci	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
5938c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
5968c2ecf20Sopenharmony_ci	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
5978c2ecf20Sopenharmony_ci		return -EINVAL;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	cfg->rx_itr = coal->rx_coalesce_usecs;
6028c2ecf20Sopenharmony_ci	cfg->tx_itr = coal->tx_coalesce_usecs;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	return aq_nic_update_interrupt_moderation_settings(aq_nic);
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_cistatic void aq_ethtool_get_wol(struct net_device *ndev,
6088c2ecf20Sopenharmony_ci			       struct ethtool_wolinfo *wol)
6098c2ecf20Sopenharmony_ci{
6108c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6118c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	wol->supported = AQ_NIC_WOL_MODES;
6168c2ecf20Sopenharmony_ci	wol->wolopts = cfg->wol;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic int aq_ethtool_set_wol(struct net_device *ndev,
6208c2ecf20Sopenharmony_ci			      struct ethtool_wolinfo *wol)
6218c2ecf20Sopenharmony_ci{
6228c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
6238c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6248c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
6258c2ecf20Sopenharmony_ci	int err = 0;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (wol->wolopts & ~AQ_NIC_WOL_MODES)
6308c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	cfg->wol = wol->wolopts;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return err;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic int aq_ethtool_get_ts_info(struct net_device *ndev,
6408c2ecf20Sopenharmony_ci				  struct ethtool_ts_info *info)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	ethtool_op_get_ts_info(ndev, info);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	if (!aq_nic->aq_ptp)
6478c2ecf20Sopenharmony_ci		return 0;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	info->so_timestamping |=
6508c2ecf20Sopenharmony_ci		SOF_TIMESTAMPING_TX_HARDWARE |
6518c2ecf20Sopenharmony_ci		SOF_TIMESTAMPING_RX_HARDWARE |
6528c2ecf20Sopenharmony_ci		SOF_TIMESTAMPING_RAW_HARDWARE;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
6558c2ecf20Sopenharmony_ci			 BIT(HWTSTAMP_TX_ON);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
6608c2ecf20Sopenharmony_ci			    BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
6618c2ecf20Sopenharmony_ci			    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
6648c2ecf20Sopenharmony_ci	info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
6658c2ecf20Sopenharmony_ci#endif
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	return 0;
6688c2ecf20Sopenharmony_ci}
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_cistatic u32 eee_mask_to_ethtool_mask(u32 speed)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci	u32 rate = 0;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (speed & AQ_NIC_RATE_EEE_10G)
6758c2ecf20Sopenharmony_ci		rate |= SUPPORTED_10000baseT_Full;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (speed & AQ_NIC_RATE_EEE_1G)
6788c2ecf20Sopenharmony_ci		rate |= SUPPORTED_1000baseT_Full;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	if (speed & AQ_NIC_RATE_EEE_100M)
6818c2ecf20Sopenharmony_ci		rate |= SUPPORTED_100baseT_Full;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	return rate;
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cistatic int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6898c2ecf20Sopenharmony_ci	u32 rate, supported_rates;
6908c2ecf20Sopenharmony_ci	int err = 0;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	if (!aq_nic->aq_fw_ops->get_eee_rate)
6938c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	mutex_lock(&aq_nic->fwreq_mutex);
6968c2ecf20Sopenharmony_ci	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
6978c2ecf20Sopenharmony_ci					      &supported_rates);
6988c2ecf20Sopenharmony_ci	mutex_unlock(&aq_nic->fwreq_mutex);
6998c2ecf20Sopenharmony_ci	if (err < 0)
7008c2ecf20Sopenharmony_ci		return err;
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	eee->supported = eee_mask_to_ethtool_mask(supported_rates);
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	if (aq_nic->aq_nic_cfg.eee_speeds)
7058c2ecf20Sopenharmony_ci		eee->advertised = eee->supported;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	eee->eee_enabled = !!eee->advertised;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	eee->tx_lpi_enabled = eee->eee_enabled;
7128c2ecf20Sopenharmony_ci	if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
7138c2ecf20Sopenharmony_ci		eee->eee_active = true;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	return 0;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_cistatic int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
7198c2ecf20Sopenharmony_ci{
7208c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
7218c2ecf20Sopenharmony_ci	u32 rate, supported_rates;
7228c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
7238c2ecf20Sopenharmony_ci	int err = 0;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
7288c2ecf20Sopenharmony_ci		     !aq_nic->aq_fw_ops->set_eee_rate))
7298c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	mutex_lock(&aq_nic->fwreq_mutex);
7328c2ecf20Sopenharmony_ci	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
7338c2ecf20Sopenharmony_ci					      &supported_rates);
7348c2ecf20Sopenharmony_ci	mutex_unlock(&aq_nic->fwreq_mutex);
7358c2ecf20Sopenharmony_ci	if (err < 0)
7368c2ecf20Sopenharmony_ci		return err;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	if (eee->eee_enabled) {
7398c2ecf20Sopenharmony_ci		rate = supported_rates;
7408c2ecf20Sopenharmony_ci		cfg->eee_speeds = rate;
7418c2ecf20Sopenharmony_ci	} else {
7428c2ecf20Sopenharmony_ci		rate = 0;
7438c2ecf20Sopenharmony_ci		cfg->eee_speeds = 0;
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	mutex_lock(&aq_nic->fwreq_mutex);
7478c2ecf20Sopenharmony_ci	err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
7488c2ecf20Sopenharmony_ci	mutex_unlock(&aq_nic->fwreq_mutex);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	return err;
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic int aq_ethtool_nway_reset(struct net_device *ndev)
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
7568c2ecf20Sopenharmony_ci	int err = 0;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
7598c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	if (netif_running(ndev)) {
7628c2ecf20Sopenharmony_ci		mutex_lock(&aq_nic->fwreq_mutex);
7638c2ecf20Sopenharmony_ci		err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
7648c2ecf20Sopenharmony_ci		mutex_unlock(&aq_nic->fwreq_mutex);
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	return err;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_cistatic void aq_ethtool_get_pauseparam(struct net_device *ndev,
7718c2ecf20Sopenharmony_ci				      struct ethtool_pauseparam *pause)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
7748c2ecf20Sopenharmony_ci	int fc = aq_nic->aq_nic_cfg.fc.req;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	pause->autoneg = 0;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
7798c2ecf20Sopenharmony_ci	pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic int aq_ethtool_set_pauseparam(struct net_device *ndev,
7838c2ecf20Sopenharmony_ci				     struct ethtool_pauseparam *pause)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
7868c2ecf20Sopenharmony_ci	int err = 0;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	if (!aq_nic->aq_fw_ops->set_flow_control)
7898c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	if (pause->autoneg == AUTONEG_ENABLE)
7928c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	if (pause->rx_pause)
7958c2ecf20Sopenharmony_ci		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
7968c2ecf20Sopenharmony_ci	else
7978c2ecf20Sopenharmony_ci		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	if (pause->tx_pause)
8008c2ecf20Sopenharmony_ci		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
8018c2ecf20Sopenharmony_ci	else
8028c2ecf20Sopenharmony_ci		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	mutex_lock(&aq_nic->fwreq_mutex);
8058c2ecf20Sopenharmony_ci	err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
8068c2ecf20Sopenharmony_ci	mutex_unlock(&aq_nic->fwreq_mutex);
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	return err;
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic void aq_get_ringparam(struct net_device *ndev,
8128c2ecf20Sopenharmony_ci			     struct ethtool_ringparam *ring)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8158c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	ring->rx_pending = cfg->rxds;
8208c2ecf20Sopenharmony_ci	ring->tx_pending = cfg->txds;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
8238c2ecf20Sopenharmony_ci	ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_cistatic int aq_set_ringparam(struct net_device *ndev,
8278c2ecf20Sopenharmony_ci			    struct ethtool_ringparam *ring)
8288c2ecf20Sopenharmony_ci{
8298c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8308c2ecf20Sopenharmony_ci	const struct aq_hw_caps_s *hw_caps;
8318c2ecf20Sopenharmony_ci	bool ndev_running = false;
8328c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
8338c2ecf20Sopenharmony_ci	int err = 0;
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
8368c2ecf20Sopenharmony_ci	hw_caps = cfg->aq_hw_caps;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
8398c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
8408c2ecf20Sopenharmony_ci		goto err_exit;
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	if (netif_running(ndev)) {
8448c2ecf20Sopenharmony_ci		ndev_running = true;
8458c2ecf20Sopenharmony_ci		aq_ndev_close(ndev);
8468c2ecf20Sopenharmony_ci	}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
8498c2ecf20Sopenharmony_ci	cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
8508c2ecf20Sopenharmony_ci	cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
8538c2ecf20Sopenharmony_ci	cfg->txds = min(cfg->txds, hw_caps->txds_max);
8548c2ecf20Sopenharmony_ci	cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	err = aq_nic_realloc_vectors(aq_nic);
8578c2ecf20Sopenharmony_ci	if (err)
8588c2ecf20Sopenharmony_ci		goto err_exit;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	if (ndev_running)
8618c2ecf20Sopenharmony_ci		err = aq_ndev_open(ndev);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_cierr_exit:
8648c2ecf20Sopenharmony_ci	return err;
8658c2ecf20Sopenharmony_ci}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_cistatic u32 aq_get_msg_level(struct net_device *ndev)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	return aq_nic->msg_enable;
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_cistatic void aq_set_msg_level(struct net_device *ndev, u32 data)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	aq_nic->msg_enable = data;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	return aq_nic->aq_nic_cfg.priv_flags;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8918c2ecf20Sopenharmony_ci	struct aq_nic_cfg_s *cfg;
8928c2ecf20Sopenharmony_ci	u32 priv_flags;
8938c2ecf20Sopenharmony_ci	int ret = 0;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	cfg = aq_nic_get_cfg(aq_nic);
8968c2ecf20Sopenharmony_ci	priv_flags = cfg->priv_flags;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	if (flags & ~AQ_PRIV_FLAGS_MASK)
8998c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
9028c2ecf20Sopenharmony_ci		netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
9038c2ecf20Sopenharmony_ci		return -EINVAL;
9048c2ecf20Sopenharmony_ci	}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	cfg->priv_flags = flags;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
9098c2ecf20Sopenharmony_ci		if (netif_running(ndev)) {
9108c2ecf20Sopenharmony_ci			dev_close(ndev);
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci			dev_open(ndev, NULL);
9138c2ecf20Sopenharmony_ci		}
9148c2ecf20Sopenharmony_ci	} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
9158c2ecf20Sopenharmony_ci		ret = aq_nic_set_loopback(aq_nic);
9168c2ecf20Sopenharmony_ci	}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	return ret;
9198c2ecf20Sopenharmony_ci}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic int aq_ethtool_get_phy_tunable(struct net_device *ndev,
9228c2ecf20Sopenharmony_ci				      const struct ethtool_tunable *tuna, void *data)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	switch (tuna->id) {
9278c2ecf20Sopenharmony_ci	case ETHTOOL_PHY_EDPD: {
9288c2ecf20Sopenharmony_ci		u16 *val = data;
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci		*val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0;
9318c2ecf20Sopenharmony_ci		break;
9328c2ecf20Sopenharmony_ci	}
9338c2ecf20Sopenharmony_ci	case ETHTOOL_PHY_DOWNSHIFT: {
9348c2ecf20Sopenharmony_ci		u8 *val = data;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci		*val = (u8)aq_nic->aq_nic_cfg.downshift_counter;
9378c2ecf20Sopenharmony_ci		break;
9388c2ecf20Sopenharmony_ci	}
9398c2ecf20Sopenharmony_ci	default:
9408c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	return 0;
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cistatic int aq_ethtool_set_phy_tunable(struct net_device *ndev,
9478c2ecf20Sopenharmony_ci				      const struct ethtool_tunable *tuna, const void *data)
9488c2ecf20Sopenharmony_ci{
9498c2ecf20Sopenharmony_ci	int err = -EOPNOTSUPP;
9508c2ecf20Sopenharmony_ci	struct aq_nic_s *aq_nic = netdev_priv(ndev);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	switch (tuna->id) {
9538c2ecf20Sopenharmony_ci	case ETHTOOL_PHY_EDPD: {
9548c2ecf20Sopenharmony_ci		const u16 *val = data;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci		err = aq_nic_set_media_detect(aq_nic, *val);
9578c2ecf20Sopenharmony_ci		break;
9588c2ecf20Sopenharmony_ci	}
9598c2ecf20Sopenharmony_ci	case ETHTOOL_PHY_DOWNSHIFT: {
9608c2ecf20Sopenharmony_ci		const u8 *val = data;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci		err = aq_nic_set_downshift(aq_nic, *val);
9638c2ecf20Sopenharmony_ci		break;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci	default:
9668c2ecf20Sopenharmony_ci		break;
9678c2ecf20Sopenharmony_ci	}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	return err;
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ciconst struct ethtool_ops aq_ethtool_ops = {
9738c2ecf20Sopenharmony_ci	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
9748c2ecf20Sopenharmony_ci				     ETHTOOL_COALESCE_MAX_FRAMES,
9758c2ecf20Sopenharmony_ci	.get_link            = aq_ethtool_get_link,
9768c2ecf20Sopenharmony_ci	.get_regs_len        = aq_ethtool_get_regs_len,
9778c2ecf20Sopenharmony_ci	.get_regs            = aq_ethtool_get_regs,
9788c2ecf20Sopenharmony_ci	.get_drvinfo         = aq_ethtool_get_drvinfo,
9798c2ecf20Sopenharmony_ci	.get_strings         = aq_ethtool_get_strings,
9808c2ecf20Sopenharmony_ci	.set_phys_id         = aq_ethtool_set_phys_id,
9818c2ecf20Sopenharmony_ci	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
9828c2ecf20Sopenharmony_ci	.get_wol             = aq_ethtool_get_wol,
9838c2ecf20Sopenharmony_ci	.set_wol             = aq_ethtool_set_wol,
9848c2ecf20Sopenharmony_ci	.nway_reset          = aq_ethtool_nway_reset,
9858c2ecf20Sopenharmony_ci	.get_ringparam       = aq_get_ringparam,
9868c2ecf20Sopenharmony_ci	.set_ringparam       = aq_set_ringparam,
9878c2ecf20Sopenharmony_ci	.get_eee             = aq_ethtool_get_eee,
9888c2ecf20Sopenharmony_ci	.set_eee             = aq_ethtool_set_eee,
9898c2ecf20Sopenharmony_ci	.get_pauseparam      = aq_ethtool_get_pauseparam,
9908c2ecf20Sopenharmony_ci	.set_pauseparam      = aq_ethtool_set_pauseparam,
9918c2ecf20Sopenharmony_ci	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
9928c2ecf20Sopenharmony_ci	.get_rxfh            = aq_ethtool_get_rss,
9938c2ecf20Sopenharmony_ci	.set_rxfh            = aq_ethtool_set_rss,
9948c2ecf20Sopenharmony_ci	.get_rxnfc           = aq_ethtool_get_rxnfc,
9958c2ecf20Sopenharmony_ci	.set_rxnfc           = aq_ethtool_set_rxnfc,
9968c2ecf20Sopenharmony_ci	.get_msglevel        = aq_get_msg_level,
9978c2ecf20Sopenharmony_ci	.set_msglevel        = aq_set_msg_level,
9988c2ecf20Sopenharmony_ci	.get_sset_count      = aq_ethtool_get_sset_count,
9998c2ecf20Sopenharmony_ci	.get_ethtool_stats   = aq_ethtool_stats,
10008c2ecf20Sopenharmony_ci	.get_priv_flags      = aq_ethtool_get_priv_flags,
10018c2ecf20Sopenharmony_ci	.set_priv_flags      = aq_ethtool_set_priv_flags,
10028c2ecf20Sopenharmony_ci	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
10038c2ecf20Sopenharmony_ci	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
10048c2ecf20Sopenharmony_ci	.get_coalesce	     = aq_ethtool_get_coalesce,
10058c2ecf20Sopenharmony_ci	.set_coalesce	     = aq_ethtool_set_coalesce,
10068c2ecf20Sopenharmony_ci	.get_ts_info         = aq_ethtool_get_ts_info,
10078c2ecf20Sopenharmony_ci	.get_phy_tunable     = aq_ethtool_get_phy_tunable,
10088c2ecf20Sopenharmony_ci	.set_phy_tunable     = aq_ethtool_set_phy_tunable,
10098c2ecf20Sopenharmony_ci};
1010