brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · b715af2 Raw
322 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Texas Instruments ICSSG Ethernet driver3 *4 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/5 *6 */7 8#include "icssg_prueth.h"9#include "icssg_stats.h"10 11static void emac_get_drvinfo(struct net_device *ndev,12			     struct ethtool_drvinfo *info)13{14	struct prueth_emac *emac = netdev_priv(ndev);15	struct prueth *prueth = emac->prueth;16 17	strscpy(info->driver, dev_driver_string(prueth->dev),18		sizeof(info->driver));19	strscpy(info->bus_info, dev_name(prueth->dev), sizeof(info->bus_info));20}21 22static u32 emac_get_msglevel(struct net_device *ndev)23{24	struct prueth_emac *emac = netdev_priv(ndev);25 26	return emac->msg_enable;27}28 29static void emac_set_msglevel(struct net_device *ndev, u32 value)30{31	struct prueth_emac *emac = netdev_priv(ndev);32 33	emac->msg_enable = value;34}35 36static int emac_get_link_ksettings(struct net_device *ndev,37				   struct ethtool_link_ksettings *ecmd)38{39	return phy_ethtool_get_link_ksettings(ndev, ecmd);40}41 42static int emac_set_link_ksettings(struct net_device *ndev,43				   const struct ethtool_link_ksettings *ecmd)44{45	return phy_ethtool_set_link_ksettings(ndev, ecmd);46}47 48static int emac_get_eee(struct net_device *ndev, struct ethtool_keee *edata)49{50	if (!ndev->phydev)51		return -EOPNOTSUPP;52 53	return phy_ethtool_get_eee(ndev->phydev, edata);54}55 56static int emac_set_eee(struct net_device *ndev, struct ethtool_keee *edata)57{58	if (!ndev->phydev)59		return -EOPNOTSUPP;60 61	return phy_ethtool_set_eee(ndev->phydev, edata);62}63 64static int emac_nway_reset(struct net_device *ndev)65{66	return phy_ethtool_nway_reset(ndev);67}68 69static int emac_get_sset_count(struct net_device *ndev, int stringset)70{71	struct prueth_emac *emac = netdev_priv(ndev);72	switch (stringset) {73	case ETH_SS_STATS:74		if (emac->prueth->pa_stats)75			return ICSSG_NUM_ETHTOOL_STATS;76		else77			return ICSSG_NUM_ETHTOOL_STATS - ICSSG_NUM_PA_STATS;78	default:79		return -EOPNOTSUPP;80	}81}82 83static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data)84{85	struct prueth_emac *emac = netdev_priv(ndev);86	u8 *p = data;87	int i;88 89	switch (stringset) {90	case ETH_SS_STATS:91		for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++)92			if (!icssg_all_miig_stats[i].standard_stats)93				ethtool_puts(&p, icssg_all_miig_stats[i].name);94		if (emac->prueth->pa_stats)95			for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++)96				ethtool_puts(&p, icssg_all_pa_stats[i].name);97		break;98	default:99		break;100	}101}102 103static void emac_get_ethtool_stats(struct net_device *ndev,104				   struct ethtool_stats *stats, u64 *data)105{106	struct prueth_emac *emac = netdev_priv(ndev);107	int i;108 109	emac_update_hardware_stats(emac);110 111	for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++)112		if (!icssg_all_miig_stats[i].standard_stats)113			*(data++) = emac->stats[i];114 115	if (emac->prueth->pa_stats)116		for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++)117			*(data++) = emac->pa_stats[i];118}119 120static int emac_get_ts_info(struct net_device *ndev,121			    struct kernel_ethtool_ts_info *info)122{123	struct prueth_emac *emac = netdev_priv(ndev);124 125	info->so_timestamping =126		SOF_TIMESTAMPING_TX_HARDWARE |127		SOF_TIMESTAMPING_TX_SOFTWARE |128		SOF_TIMESTAMPING_RX_HARDWARE |129		SOF_TIMESTAMPING_RAW_HARDWARE;130 131	info->phc_index = icss_iep_get_ptp_clock_idx(emac->iep);132	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);133	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);134 135	return 0;136}137 138static int emac_set_channels(struct net_device *ndev,139			     struct ethtool_channels *ch)140{141	struct prueth_emac *emac = netdev_priv(ndev);142 143	/* Check if interface is up. Can change the num queues when144	 * the interface is down.145	 */146	if (netif_running(emac->ndev))147		return -EBUSY;148 149	emac->tx_ch_num = ch->tx_count;150 151	if (emac->is_sr1)152		emac->tx_ch_num++;153 154	return 0;155}156 157static void emac_get_channels(struct net_device *ndev,158			      struct ethtool_channels *ch)159{160	struct prueth_emac *emac = netdev_priv(ndev);161 162	ch->max_rx = 1;163	ch->max_tx = PRUETH_MAX_TX_QUEUES;164 165	/* Disable multiple TX channels due to timeouts166	 * when using more than one queue */167	if (emac->is_sr1)168		ch->max_tx = 1;169 170	ch->rx_count = 1;171	ch->tx_count = emac->tx_ch_num;172 173	if (emac->is_sr1)174		ch->tx_count--;175}176 177static const struct ethtool_rmon_hist_range emac_rmon_ranges[] = {178	{    0,   64},179	{   65,  128},180	{  129,  256},181	{  257,  512},182	{  513, PRUETH_MAX_PKT_SIZE},183	{}184};185 186static void emac_get_rmon_stats(struct net_device *ndev,187				struct ethtool_rmon_stats *rmon_stats,188				const struct ethtool_rmon_hist_range **ranges)189{190	struct prueth_emac *emac = netdev_priv(ndev);191 192	*ranges = emac_rmon_ranges;193 194	rmon_stats->undersize_pkts = emac_get_stat_by_name(emac, "rx_bucket1_frames") -195				     emac_get_stat_by_name(emac, "rx_64B_frames");196 197	rmon_stats->hist[0] = emac_get_stat_by_name(emac, "rx_bucket1_frames");198	rmon_stats->hist[1] = emac_get_stat_by_name(emac, "rx_bucket2_frames");199	rmon_stats->hist[2] = emac_get_stat_by_name(emac, "rx_bucket3_frames");200	rmon_stats->hist[3] = emac_get_stat_by_name(emac, "rx_bucket4_frames");201	rmon_stats->hist[4] = emac_get_stat_by_name(emac, "rx_bucket5_frames");202 203	rmon_stats->hist_tx[0] = emac_get_stat_by_name(emac, "tx_bucket1_frames");204	rmon_stats->hist_tx[1] = emac_get_stat_by_name(emac, "tx_bucket2_frames");205	rmon_stats->hist_tx[2] = emac_get_stat_by_name(emac, "tx_bucket3_frames");206	rmon_stats->hist_tx[3] = emac_get_stat_by_name(emac, "tx_bucket4_frames");207	rmon_stats->hist_tx[4] = emac_get_stat_by_name(emac, "tx_bucket5_frames");208}209 210static int emac_get_coalesce(struct net_device *ndev,211			     struct ethtool_coalesce *coal,212			     struct kernel_ethtool_coalesce *kernel_coal,213			     struct netlink_ext_ack *extack)214{215	struct prueth_emac *emac = netdev_priv(ndev);216	struct prueth_tx_chn *tx_chn;217 218	tx_chn = &emac->tx_chns[0];219 220	coal->rx_coalesce_usecs = emac->rx_pace_timeout_ns / 1000;221	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout_ns / 1000;222 223	return 0;224}225 226static int emac_get_per_queue_coalesce(struct net_device *ndev, u32 queue,227				       struct ethtool_coalesce *coal)228{229	struct prueth_emac *emac = netdev_priv(ndev);230	struct prueth_tx_chn *tx_chn;231 232	if (queue >= PRUETH_MAX_TX_QUEUES)233		return -EINVAL;234 235	tx_chn = &emac->tx_chns[queue];236 237	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout_ns / 1000;238 239	return 0;240}241 242static int emac_set_coalesce(struct net_device *ndev,243			     struct ethtool_coalesce *coal,244			     struct kernel_ethtool_coalesce *kernel_coal,245			     struct netlink_ext_ack *extack)246{247	struct prueth_emac *emac = netdev_priv(ndev);248	struct prueth *prueth = emac->prueth;249	struct prueth_tx_chn *tx_chn;250 251	tx_chn = &emac->tx_chns[0];252 253	if (coal->rx_coalesce_usecs &&254	    coal->rx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {255		dev_info(prueth->dev, "defaulting to min value of %dus for rx-usecs\n",256			 ICSSG_MIN_COALESCE_USECS);257		coal->rx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;258	}259 260	if (coal->tx_coalesce_usecs &&261	    coal->tx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {262		dev_info(prueth->dev, "defaulting to min value of %dus for tx-usecs\n",263			 ICSSG_MIN_COALESCE_USECS);264		coal->tx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;265	}266 267	emac->rx_pace_timeout_ns = coal->rx_coalesce_usecs * 1000;268	tx_chn->tx_pace_timeout_ns = coal->tx_coalesce_usecs * 1000;269 270	return 0;271}272 273static int emac_set_per_queue_coalesce(struct net_device *ndev, u32 queue,274				       struct ethtool_coalesce *coal)275{276	struct prueth_emac *emac = netdev_priv(ndev);277	struct prueth *prueth = emac->prueth;278	struct prueth_tx_chn *tx_chn;279 280	if (queue >= PRUETH_MAX_TX_QUEUES)281		return -EINVAL;282 283	tx_chn = &emac->tx_chns[queue];284 285	if (coal->tx_coalesce_usecs &&286	    coal->tx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {287		dev_info(prueth->dev, "defaulting to min value of %dus for tx-usecs for tx-%u\n",288			 ICSSG_MIN_COALESCE_USECS, queue);289		coal->tx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;290	}291 292	tx_chn->tx_pace_timeout_ns = coal->tx_coalesce_usecs * 1000;293 294	return 0;295}296 297const struct ethtool_ops icssg_ethtool_ops = {298	.get_drvinfo = emac_get_drvinfo,299	.get_msglevel = emac_get_msglevel,300	.set_msglevel = emac_set_msglevel,301	.get_sset_count = emac_get_sset_count,302	.get_ethtool_stats = emac_get_ethtool_stats,303	.get_strings = emac_get_strings,304	.get_ts_info = emac_get_ts_info,305	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |306				     ETHTOOL_COALESCE_TX_USECS,307	.get_coalesce = emac_get_coalesce,308	.set_coalesce = emac_set_coalesce,309	.get_per_queue_coalesce = emac_get_per_queue_coalesce,310	.set_per_queue_coalesce = emac_set_per_queue_coalesce,311	.get_channels = emac_get_channels,312	.set_channels = emac_set_channels,313	.get_link_ksettings = emac_get_link_ksettings,314	.set_link_ksettings = emac_set_link_ksettings,315	.get_link = ethtool_op_get_link,316	.get_eee = emac_get_eee,317	.set_eee = emac_set_eee,318	.nway_reset = emac_nway_reset,319	.get_rmon_stats = emac_get_rmon_stats,320};321EXPORT_SYMBOL_GPL(icssg_ethtool_ops);322