brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · f502db9 Raw
288 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2016, The Linux Foundation. All rights reserved.3 */4 5#include <linux/ethtool.h>6#include <linux/phy.h>7 8#include "emac.h"9 10static const char * const emac_ethtool_stat_strings[] = {11	"rx_ok",12	"rx_bcast",13	"rx_mcast",14	"rx_pause",15	"rx_ctrl",16	"rx_fcs_err",17	"rx_len_err",18	"rx_byte_cnt",19	"rx_runt",20	"rx_frag",21	"rx_sz_64",22	"rx_sz_65_127",23	"rx_sz_128_255",24	"rx_sz_256_511",25	"rx_sz_512_1023",26	"rx_sz_1024_1518",27	"rx_sz_1519_max",28	"rx_sz_ov",29	"rx_rxf_ov",30	"rx_align_err",31	"rx_bcast_byte_cnt",32	"rx_mcast_byte_cnt",33	"rx_err_addr",34	"rx_crc_align",35	"rx_jabbers",36	"tx_ok",37	"tx_bcast",38	"tx_mcast",39	"tx_pause",40	"tx_exc_defer",41	"tx_ctrl",42	"tx_defer",43	"tx_byte_cnt",44	"tx_sz_64",45	"tx_sz_65_127",46	"tx_sz_128_255",47	"tx_sz_256_511",48	"tx_sz_512_1023",49	"tx_sz_1024_1518",50	"tx_sz_1519_max",51	"tx_1_col",52	"tx_2_col",53	"tx_late_col",54	"tx_abort_col",55	"tx_underrun",56	"tx_rd_eop",57	"tx_len_err",58	"tx_trunc",59	"tx_bcast_byte",60	"tx_mcast_byte",61	"tx_col",62};63 64#define EMAC_STATS_LEN	ARRAY_SIZE(emac_ethtool_stat_strings)65 66static u32 emac_get_msglevel(struct net_device *netdev)67{68	struct emac_adapter *adpt = netdev_priv(netdev);69 70	return adpt->msg_enable;71}72 73static void emac_set_msglevel(struct net_device *netdev, u32 data)74{75	struct emac_adapter *adpt = netdev_priv(netdev);76 77	adpt->msg_enable = data;78}79 80static int emac_get_sset_count(struct net_device *netdev, int sset)81{82	switch (sset) {83	case ETH_SS_PRIV_FLAGS:84		return 1;85	case ETH_SS_STATS:86		return EMAC_STATS_LEN;87	default:88		return -EOPNOTSUPP;89	}90}91 92static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)93{94	unsigned int i;95 96	switch (stringset) {97	case ETH_SS_PRIV_FLAGS:98		strcpy(data, "single-pause-mode");99		break;100 101	case ETH_SS_STATS:102		for (i = 0; i < EMAC_STATS_LEN; i++) {103			strscpy(data, emac_ethtool_stat_strings[i],104				ETH_GSTRING_LEN);105			data += ETH_GSTRING_LEN;106		}107		break;108	}109}110 111static void emac_get_ethtool_stats(struct net_device *netdev,112				   struct ethtool_stats *stats,113				   u64 *data)114{115	struct emac_adapter *adpt = netdev_priv(netdev);116 117	spin_lock(&adpt->stats.lock);118 119	emac_update_hw_stats(adpt);120	memcpy(data, &adpt->stats, EMAC_STATS_LEN * sizeof(u64));121 122	spin_unlock(&adpt->stats.lock);123}124 125static int emac_nway_reset(struct net_device *netdev)126{127	struct phy_device *phydev = netdev->phydev;128 129	if (!phydev)130		return -ENODEV;131 132	return genphy_restart_aneg(phydev);133}134 135static void emac_get_ringparam(struct net_device *netdev,136			       struct ethtool_ringparam *ring,137			       struct kernel_ethtool_ringparam *kernel_ring,138			       struct netlink_ext_ack *extack)139{140	struct emac_adapter *adpt = netdev_priv(netdev);141 142	ring->rx_max_pending = EMAC_MAX_RX_DESCS;143	ring->tx_max_pending = EMAC_MAX_TX_DESCS;144	ring->rx_pending = adpt->rx_desc_cnt;145	ring->tx_pending = adpt->tx_desc_cnt;146}147 148static int emac_set_ringparam(struct net_device *netdev,149			      struct ethtool_ringparam *ring,150			      struct kernel_ethtool_ringparam *kernel_ring,151			      struct netlink_ext_ack *extack)152{153	struct emac_adapter *adpt = netdev_priv(netdev);154 155	/* We don't have separate queues/rings for small/large frames, so156	 * reject any attempt to specify those values separately.157	 */158	if (ring->rx_mini_pending || ring->rx_jumbo_pending)159		return -EINVAL;160 161	adpt->tx_desc_cnt =162		clamp_val(ring->tx_pending, EMAC_MIN_TX_DESCS, EMAC_MAX_TX_DESCS);163 164	adpt->rx_desc_cnt =165		clamp_val(ring->rx_pending, EMAC_MIN_RX_DESCS, EMAC_MAX_RX_DESCS);166 167	if (netif_running(netdev))168		return emac_reinit_locked(adpt);169 170	return 0;171}172 173static void emac_get_pauseparam(struct net_device *netdev,174				struct ethtool_pauseparam *pause)175{176	struct emac_adapter *adpt = netdev_priv(netdev);177 178	pause->autoneg = adpt->automatic ? AUTONEG_ENABLE : AUTONEG_DISABLE;179	pause->rx_pause = adpt->rx_flow_control ? 1 : 0;180	pause->tx_pause = adpt->tx_flow_control ? 1 : 0;181}182 183static int emac_set_pauseparam(struct net_device *netdev,184			       struct ethtool_pauseparam *pause)185{186	struct emac_adapter *adpt = netdev_priv(netdev);187 188	adpt->automatic = pause->autoneg == AUTONEG_ENABLE;189	adpt->rx_flow_control = pause->rx_pause != 0;190	adpt->tx_flow_control = pause->tx_pause != 0;191 192	if (netif_running(netdev))193		return emac_reinit_locked(adpt);194 195	return 0;196}197 198/* Selected registers that might want to track during runtime. */199static const u16 emac_regs[] = {200	EMAC_DMA_MAS_CTRL,201	EMAC_MAC_CTRL,202	EMAC_TXQ_CTRL_0,203	EMAC_RXQ_CTRL_0,204	EMAC_DMA_CTRL,205	EMAC_INT_MASK,206	EMAC_AXI_MAST_CTRL,207	EMAC_CORE_HW_VERSION,208	EMAC_MISC_CTRL,209};210 211/* Every time emac_regs[] above is changed, increase this version number. */212#define EMAC_REGS_VERSION	0213 214#define EMAC_MAX_REG_SIZE	ARRAY_SIZE(emac_regs)215 216static void emac_get_regs(struct net_device *netdev,217			  struct ethtool_regs *regs, void *buff)218{219	struct emac_adapter *adpt = netdev_priv(netdev);220	u32 *val = buff;221	unsigned int i;222 223	regs->version = EMAC_REGS_VERSION;224	regs->len = EMAC_MAX_REG_SIZE * sizeof(u32);225 226	for (i = 0; i < EMAC_MAX_REG_SIZE; i++)227		val[i] = readl(adpt->base + emac_regs[i]);228}229 230static int emac_get_regs_len(struct net_device *netdev)231{232	return EMAC_MAX_REG_SIZE * sizeof(u32);233}234 235#define EMAC_PRIV_ENABLE_SINGLE_PAUSE	BIT(0)236 237static int emac_set_priv_flags(struct net_device *netdev, u32 flags)238{239	struct emac_adapter *adpt = netdev_priv(netdev);240 241	adpt->single_pause_mode = !!(flags & EMAC_PRIV_ENABLE_SINGLE_PAUSE);242 243	if (netif_running(netdev))244		return emac_reinit_locked(adpt);245 246	return 0;247}248 249static u32 emac_get_priv_flags(struct net_device *netdev)250{251	struct emac_adapter *adpt = netdev_priv(netdev);252 253	return adpt->single_pause_mode ? EMAC_PRIV_ENABLE_SINGLE_PAUSE : 0;254}255 256static const struct ethtool_ops emac_ethtool_ops = {257	.get_link_ksettings = phy_ethtool_get_link_ksettings,258	.set_link_ksettings = phy_ethtool_set_link_ksettings,259 260	.get_msglevel    = emac_get_msglevel,261	.set_msglevel    = emac_set_msglevel,262 263	.get_sset_count  = emac_get_sset_count,264	.get_strings = emac_get_strings,265	.get_ethtool_stats = emac_get_ethtool_stats,266 267	.get_ringparam = emac_get_ringparam,268	.set_ringparam = emac_set_ringparam,269 270	.get_pauseparam = emac_get_pauseparam,271	.set_pauseparam = emac_set_pauseparam,272 273	.nway_reset = emac_nway_reset,274 275	.get_link = ethtool_op_get_link,276 277	.get_regs_len    = emac_get_regs_len,278	.get_regs        = emac_get_regs,279 280	.set_priv_flags = emac_set_priv_flags,281	.get_priv_flags = emac_get_priv_flags,282};283 284void emac_set_ethtool_ops(struct net_device *netdev)285{286	netdev->ethtool_ops = &emac_ethtool_ops;287}288