brintos

brintos / linux-shallow public Read only

0
0
Text · 15.7 KiB · 7d0124b Raw
468 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell Octeon EP (EndPoint) Ethernet Driver3 *4 * Copyright (C) 2020 Marvell.5 *6 */7 8#include <linux/pci.h>9#include <linux/netdevice.h>10#include <linux/ethtool.h>11 12#include "octep_config.h"13#include "octep_main.h"14#include "octep_ctrl_net.h"15 16static const char octep_gstrings_global_stats[][ETH_GSTRING_LEN] = {17	"rx_packets",18	"tx_packets",19	"rx_bytes",20	"tx_bytes",21	"rx_alloc_errors",22	"tx_busy_errors",23	"rx_dropped",24	"tx_dropped",25	"tx_hw_pkts",26	"tx_hw_octs",27	"tx_hw_bcast",28	"tx_hw_mcast",29	"tx_hw_underflow",30	"tx_hw_control",31	"tx_less_than_64",32	"tx_equal_64",33	"tx_equal_65_to_127",34	"tx_equal_128_to_255",35	"tx_equal_256_to_511",36	"tx_equal_512_to_1023",37	"tx_equal_1024_to_1518",38	"tx_greater_than_1518",39	"rx_hw_pkts",40	"rx_hw_bytes",41	"rx_hw_bcast",42	"rx_hw_mcast",43	"rx_pause_pkts",44	"rx_pause_bytes",45	"rx_dropped_pkts_fifo_full",46	"rx_dropped_bytes_fifo_full",47	"rx_err_pkts",48};49 50#define OCTEP_GLOBAL_STATS_CNT (sizeof(octep_gstrings_global_stats) / ETH_GSTRING_LEN)51 52static const char octep_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {53	"tx_packets_posted[Q-%u]",54	"tx_packets_completed[Q-%u]",55	"tx_bytes[Q-%u]",56	"tx_busy[Q-%u]",57};58 59#define OCTEP_TX_Q_STATS_CNT (sizeof(octep_gstrings_tx_q_stats) / ETH_GSTRING_LEN)60 61static const char octep_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {62	"rx_packets[Q-%u]",63	"rx_bytes[Q-%u]",64	"rx_alloc_errors[Q-%u]",65};66 67#define OCTEP_RX_Q_STATS_CNT (sizeof(octep_gstrings_rx_q_stats) / ETH_GSTRING_LEN)68 69static void octep_get_drvinfo(struct net_device *netdev,70			      struct ethtool_drvinfo *info)71{72	struct octep_device *oct = netdev_priv(netdev);73 74	strscpy(info->driver, OCTEP_DRV_NAME, sizeof(info->driver));75	strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));76}77 78static void octep_get_strings(struct net_device *netdev,79			      u32 stringset, u8 *data)80{81	struct octep_device *oct = netdev_priv(netdev);82	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);83	char *strings = (char *)data;84	int i, j;85 86	switch (stringset) {87	case ETH_SS_STATS:88		for (i = 0; i < OCTEP_GLOBAL_STATS_CNT; i++) {89			snprintf(strings, ETH_GSTRING_LEN,90				 octep_gstrings_global_stats[i]);91			strings += ETH_GSTRING_LEN;92		}93 94		for (i = 0; i < num_queues; i++) {95			for (j = 0; j < OCTEP_TX_Q_STATS_CNT; j++) {96				snprintf(strings, ETH_GSTRING_LEN,97					 octep_gstrings_tx_q_stats[j], i);98				strings += ETH_GSTRING_LEN;99			}100		}101 102		for (i = 0; i < num_queues; i++) {103			for (j = 0; j < OCTEP_RX_Q_STATS_CNT; j++) {104				snprintf(strings, ETH_GSTRING_LEN,105					 octep_gstrings_rx_q_stats[j], i);106				strings += ETH_GSTRING_LEN;107			}108		}109		break;110	default:111		break;112	}113}114 115static int octep_get_sset_count(struct net_device *netdev, int sset)116{117	struct octep_device *oct = netdev_priv(netdev);118	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);119 120	switch (sset) {121	case ETH_SS_STATS:122		return OCTEP_GLOBAL_STATS_CNT + (num_queues *123		       (OCTEP_TX_Q_STATS_CNT + OCTEP_RX_Q_STATS_CNT));124		break;125	default:126		return -EOPNOTSUPP;127	}128}129 130static void131octep_get_ethtool_stats(struct net_device *netdev,132			struct ethtool_stats *stats, u64 *data)133{134	struct octep_device *oct = netdev_priv(netdev);135	struct octep_iface_tx_stats *iface_tx_stats;136	struct octep_iface_rx_stats *iface_rx_stats;137	u64 rx_packets, rx_bytes;138	u64 tx_packets, tx_bytes;139	u64 rx_alloc_errors, tx_busy_errors;140	int q, i;141 142	rx_packets = 0;143	rx_bytes = 0;144	tx_packets = 0;145	tx_bytes = 0;146	rx_alloc_errors = 0;147	tx_busy_errors = 0;148	tx_packets = 0;149	tx_bytes = 0;150	rx_packets = 0;151	rx_bytes = 0;152 153	iface_tx_stats = &oct->iface_tx_stats;154	iface_rx_stats = &oct->iface_rx_stats;155	octep_ctrl_net_get_if_stats(oct,156				    OCTEP_CTRL_NET_INVALID_VFID,157				    iface_rx_stats,158				    iface_tx_stats);159 160	for (q = 0; q < oct->num_oqs; q++) {161		struct octep_iq *iq = oct->iq[q];162		struct octep_oq *oq = oct->oq[q];163 164		tx_packets += iq->stats.instr_completed;165		tx_bytes += iq->stats.bytes_sent;166		tx_busy_errors += iq->stats.tx_busy;167 168		rx_packets += oq->stats.packets;169		rx_bytes += oq->stats.bytes;170		rx_alloc_errors += oq->stats.alloc_failures;171	}172	i = 0;173	data[i++] = rx_packets;174	data[i++] = tx_packets;175	data[i++] = rx_bytes;176	data[i++] = tx_bytes;177	data[i++] = rx_alloc_errors;178	data[i++] = tx_busy_errors;179	data[i++] = iface_rx_stats->dropped_pkts_fifo_full +180		    iface_rx_stats->err_pkts;181	data[i++] = iface_tx_stats->xscol +182		    iface_tx_stats->xsdef;183	data[i++] = iface_tx_stats->pkts;184	data[i++] = iface_tx_stats->octs;185	data[i++] = iface_tx_stats->bcst;186	data[i++] = iface_tx_stats->mcst;187	data[i++] = iface_tx_stats->undflw;188	data[i++] = iface_tx_stats->ctl;189	data[i++] = iface_tx_stats->hist_lt64;190	data[i++] = iface_tx_stats->hist_eq64;191	data[i++] = iface_tx_stats->hist_65to127;192	data[i++] = iface_tx_stats->hist_128to255;193	data[i++] = iface_tx_stats->hist_256to511;194	data[i++] = iface_tx_stats->hist_512to1023;195	data[i++] = iface_tx_stats->hist_1024to1518;196	data[i++] = iface_tx_stats->hist_gt1518;197	data[i++] = iface_rx_stats->pkts;198	data[i++] = iface_rx_stats->octets;199	data[i++] = iface_rx_stats->mcast_pkts;200	data[i++] = iface_rx_stats->bcast_pkts;201	data[i++] = iface_rx_stats->pause_pkts;202	data[i++] = iface_rx_stats->pause_octets;203	data[i++] = iface_rx_stats->dropped_pkts_fifo_full;204	data[i++] = iface_rx_stats->dropped_octets_fifo_full;205	data[i++] = iface_rx_stats->err_pkts;206 207	/* Per Tx Queue stats */208	for (q = 0; q < oct->num_iqs; q++) {209		struct octep_iq *iq = oct->iq[q];210 211		data[i++] = iq->stats.instr_posted;212		data[i++] = iq->stats.instr_completed;213		data[i++] = iq->stats.bytes_sent;214		data[i++] = iq->stats.tx_busy;215	}216 217	/* Per Rx Queue stats */218	for (q = 0; q < oct->num_oqs; q++) {219		struct octep_oq *oq = oct->oq[q];220 221		data[i++] = oq->stats.packets;222		data[i++] = oq->stats.bytes;223		data[i++] = oq->stats.alloc_failures;224	}225}226 227#define OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(octep_speeds, ksettings, name) \228{ \229	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_T)) \230		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \231	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_R)) \232		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \233	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_CR)) \234		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \235	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_KR)) \236		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \237	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_LR)) \238		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \239	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_10GBASE_SR)) \240		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \241	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_CR)) \242		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \243	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_KR)) \244		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \245	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_25GBASE_SR)) \246		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \247	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_CR4)) \248		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \249	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_KR4)) \250		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \251	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_LR4)) \252		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \253	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_40GBASE_SR4)) \254		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \255	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR2)) \256		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \257	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR2)) \258		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \259	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR2)) \260		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \261	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_CR)) \262		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \263	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_KR)) \264		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \265	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_LR)) \266		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \267	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_50GBASE_SR)) \268		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \269	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_CR4)) \270		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \271	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_KR4)) \272		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \273	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_LR4)) \274		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \275	if ((octep_speeds) & BIT(OCTEP_LINK_MODE_100GBASE_SR4)) \276		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \277}278 279static int octep_get_link_ksettings(struct net_device *netdev,280				    struct ethtool_link_ksettings *cmd)281{282	struct octep_device *oct = netdev_priv(netdev);283	struct octep_iface_link_info *link_info;284	u32 advertised_modes, supported_modes;285 286	ethtool_link_ksettings_zero_link_mode(cmd, supported);287	ethtool_link_ksettings_zero_link_mode(cmd, advertising);288 289	link_info = &oct->link_info;290	octep_ctrl_net_get_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID, link_info);291 292	advertised_modes = oct->link_info.advertised_modes;293	supported_modes = oct->link_info.supported_modes;294 295	OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);296	OCTEP_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);297 298	if (link_info->autoneg) {299		if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED)300			ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);301		if (link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_ADVERTISED) {302			ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);303			cmd->base.autoneg = AUTONEG_ENABLE;304		} else {305			cmd->base.autoneg = AUTONEG_DISABLE;306		}307	} else {308		cmd->base.autoneg = AUTONEG_DISABLE;309	}310 311	if (link_info->pause) {312		if (link_info->pause & OCTEP_LINK_MODE_PAUSE_SUPPORTED)313			ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);314		if (link_info->pause & OCTEP_LINK_MODE_PAUSE_ADVERTISED)315			ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);316	}317 318	cmd->base.port = PORT_FIBRE;319	ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);320	ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);321 322	if (netif_carrier_ok(netdev)) {323		cmd->base.speed = link_info->speed;324		cmd->base.duplex = DUPLEX_FULL;325	} else {326		cmd->base.speed = SPEED_UNKNOWN;327		cmd->base.duplex = DUPLEX_UNKNOWN;328	}329	return 0;330}331 332static int octep_set_link_ksettings(struct net_device *netdev,333				    const struct ethtool_link_ksettings *cmd)334{335	struct octep_device *oct = netdev_priv(netdev);336	struct octep_iface_link_info link_info_new;337	struct octep_iface_link_info *link_info;338	u64 advertised = 0;339	u8 autoneg = 0;340	int err;341 342	link_info = &oct->link_info;343	memcpy(&link_info_new, link_info, sizeof(struct octep_iface_link_info));344 345	/* Only Full duplex is supported;346	 * Assume full duplex when duplex is unknown.347	 */348	if (cmd->base.duplex != DUPLEX_FULL &&349	    cmd->base.duplex != DUPLEX_UNKNOWN)350		return -EOPNOTSUPP;351 352	if (cmd->base.autoneg == AUTONEG_ENABLE) {353		if (!(link_info->autoneg & OCTEP_LINK_MODE_AUTONEG_SUPPORTED))354			return -EOPNOTSUPP;355		autoneg = 1;356	}357 358	if (!bitmap_subset(cmd->link_modes.advertising,359			   cmd->link_modes.supported,360			   __ETHTOOL_LINK_MODE_MASK_NBITS))361		return -EINVAL;362 363	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,364						  10000baseT_Full))365		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_T);366	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,367						  10000baseR_FEC))368		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_R);369	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,370						  10000baseCR_Full))371		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_CR);372	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,373						  10000baseKR_Full))374		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_KR);375	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,376						  10000baseLR_Full))377		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_LR);378	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,379						  10000baseSR_Full))380		advertised |= BIT(OCTEP_LINK_MODE_10GBASE_SR);381	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,382						  25000baseCR_Full))383		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_CR);384	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,385						  25000baseKR_Full))386		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_KR);387	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,388						  25000baseSR_Full))389		advertised |= BIT(OCTEP_LINK_MODE_25GBASE_SR);390	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,391						  40000baseCR4_Full))392		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_CR4);393	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,394						  40000baseKR4_Full))395		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_KR4);396	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,397						  40000baseLR4_Full))398		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_LR4);399	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,400						  40000baseSR4_Full))401		advertised |= BIT(OCTEP_LINK_MODE_40GBASE_SR4);402	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,403						  50000baseCR2_Full))404		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR2);405	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,406						  50000baseKR2_Full))407		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR2);408	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,409						  50000baseSR2_Full))410		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR2);411	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,412						  50000baseCR_Full))413		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_CR);414	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,415						  50000baseKR_Full))416		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_KR);417	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,418						  50000baseLR_ER_FR_Full))419		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_LR);420	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,421						  50000baseSR_Full))422		advertised |= BIT(OCTEP_LINK_MODE_50GBASE_SR);423	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,424						  100000baseCR4_Full))425		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_CR4);426	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,427						  100000baseKR4_Full))428		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_KR4);429	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,430						  100000baseLR4_ER4_Full))431		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_LR4);432	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,433						  100000baseSR4_Full))434		advertised |= BIT(OCTEP_LINK_MODE_100GBASE_SR4);435 436	if (advertised == link_info->advertised_modes &&437	    cmd->base.speed == link_info->speed &&438	    cmd->base.autoneg == link_info->autoneg)439		return 0;440 441	link_info_new.advertised_modes = advertised;442	link_info_new.speed = cmd->base.speed;443	link_info_new.autoneg = autoneg;444 445	err = octep_ctrl_net_set_link_info(oct, OCTEP_CTRL_NET_INVALID_VFID,446					   &link_info_new, true);447	if (err)448		return err;449 450	memcpy(link_info, &link_info_new, sizeof(struct octep_iface_link_info));451	return 0;452}453 454static const struct ethtool_ops octep_ethtool_ops = {455	.get_drvinfo = octep_get_drvinfo,456	.get_link = ethtool_op_get_link,457	.get_strings = octep_get_strings,458	.get_sset_count = octep_get_sset_count,459	.get_ethtool_stats = octep_get_ethtool_stats,460	.get_link_ksettings = octep_get_link_ksettings,461	.set_link_ksettings = octep_set_link_ksettings,462};463 464void octep_set_ethtool_ops(struct net_device *netdev)465{466	netdev->ethtool_ops = &octep_ethtool_ops;467}468