brintos

brintos / linux-shallow public Read only

0
0
Text · 9.4 KiB · a1979b4 Raw
274 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell Octeon EP (EndPoint) VF 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_vf_config.h"13#include "octep_vf_main.h"14 15static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = {16	"rx_alloc_errors",17	"tx_busy_errors",18	"tx_hw_pkts",19	"tx_hw_octs",20	"tx_hw_bcast",21	"tx_hw_mcast",22	"rx_hw_pkts",23	"rx_hw_bytes",24	"rx_hw_bcast",25	"rx_dropped_bytes_fifo_full",26};27 28#define OCTEP_VF_GLOBAL_STATS_CNT (sizeof(octep_vf_gstrings_global_stats) / ETH_GSTRING_LEN)29 30static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {31	"tx_packets_posted[Q-%u]",32	"tx_packets_completed[Q-%u]",33	"tx_bytes[Q-%u]",34	"tx_busy[Q-%u]",35};36 37#define OCTEP_VF_TX_Q_STATS_CNT (sizeof(octep_vf_gstrings_tx_q_stats) / ETH_GSTRING_LEN)38 39static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {40	"rx_packets[Q-%u]",41	"rx_bytes[Q-%u]",42	"rx_alloc_errors[Q-%u]",43};44 45#define OCTEP_VF_RX_Q_STATS_CNT (sizeof(octep_vf_gstrings_rx_q_stats) / ETH_GSTRING_LEN)46 47static void octep_vf_get_drvinfo(struct net_device *netdev,48				 struct ethtool_drvinfo *info)49{50	struct octep_vf_device *oct = netdev_priv(netdev);51 52	strscpy(info->driver, OCTEP_VF_DRV_NAME, sizeof(info->driver));53	strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info));54}55 56static void octep_vf_get_strings(struct net_device *netdev,57				 u32 stringset, u8 *data)58{59	struct octep_vf_device *oct = netdev_priv(netdev);60	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);61	char *strings = (char *)data;62	int i, j;63 64	switch (stringset) {65	case ETH_SS_STATS:66		for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++) {67			snprintf(strings, ETH_GSTRING_LEN,68				 octep_vf_gstrings_global_stats[i]);69			strings += ETH_GSTRING_LEN;70		}71 72		for (i = 0; i < num_queues; i++) {73			for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) {74				snprintf(strings, ETH_GSTRING_LEN,75					 octep_vf_gstrings_tx_q_stats[j], i);76				strings += ETH_GSTRING_LEN;77			}78		}79 80		for (i = 0; i < num_queues; i++) {81			for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) {82				snprintf(strings, ETH_GSTRING_LEN,83					 octep_vf_gstrings_rx_q_stats[j], i);84				strings += ETH_GSTRING_LEN;85			}86		}87		break;88	default:89		break;90	}91}92 93static int octep_vf_get_sset_count(struct net_device *netdev, int sset)94{95	struct octep_vf_device *oct = netdev_priv(netdev);96	u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);97 98	switch (sset) {99	case ETH_SS_STATS:100		return OCTEP_VF_GLOBAL_STATS_CNT + (num_queues *101		       (OCTEP_VF_TX_Q_STATS_CNT + OCTEP_VF_RX_Q_STATS_CNT));102		break;103	default:104		return -EOPNOTSUPP;105	}106}107 108static void octep_vf_get_ethtool_stats(struct net_device *netdev,109				       struct ethtool_stats *stats, u64 *data)110{111	struct octep_vf_device *oct = netdev_priv(netdev);112	struct octep_vf_iface_tx_stats *iface_tx_stats;113	struct octep_vf_iface_rx_stats *iface_rx_stats;114	u64 rx_alloc_errors, tx_busy_errors;115	int q, i;116 117	rx_alloc_errors = 0;118	tx_busy_errors = 0;119 120	octep_vf_get_if_stats(oct);121	iface_tx_stats = &oct->iface_tx_stats;122	iface_rx_stats = &oct->iface_rx_stats;123 124	for (q = 0; q < oct->num_oqs; q++) {125		struct octep_vf_iq *iq = oct->iq[q];126		struct octep_vf_oq *oq = oct->oq[q];127 128		tx_busy_errors += iq->stats.tx_busy;129		rx_alloc_errors += oq->stats.alloc_failures;130	}131	i = 0;132	data[i++] = rx_alloc_errors;133	data[i++] = tx_busy_errors;134	data[i++] = iface_tx_stats->pkts;135	data[i++] = iface_tx_stats->octs;136	data[i++] = iface_tx_stats->bcst;137	data[i++] = iface_tx_stats->mcst;138	data[i++] = iface_rx_stats->pkts;139	data[i++] = iface_rx_stats->octets;140	data[i++] = iface_rx_stats->bcast_pkts;141	data[i++] = iface_rx_stats->dropped_octets_fifo_full;142 143	/* Per Tx Queue stats */144	for (q = 0; q < oct->num_iqs; q++) {145		struct octep_vf_iq *iq = oct->iq[q];146 147		data[i++] = iq->stats.instr_posted;148		data[i++] = iq->stats.instr_completed;149		data[i++] = iq->stats.bytes_sent;150		data[i++] = iq->stats.tx_busy;151	}152 153	/* Per Rx Queue stats */154	for (q = 0; q < oct->num_oqs; q++) {155		struct octep_vf_oq *oq = oct->oq[q];156 157		data[i++] = oq->stats.packets;158		data[i++] = oq->stats.bytes;159		data[i++] = oq->stats.alloc_failures;160	}161}162 163#define OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(octep_vf_speeds, ksettings, name) \164{ \165	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_T)) \166		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \167	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_R)) \168		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \169	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_CR)) \170		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \171	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_KR)) \172		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \173	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_LR)) \174		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \175	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_SR)) \176		ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \177	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_CR)) \178		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \179	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_KR)) \180		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \181	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_SR)) \182		ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \183	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_CR4)) \184		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \185	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_KR4)) \186		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \187	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_LR4)) \188		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \189	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_SR4)) \190		ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \191	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR2)) \192		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \193	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR2)) \194		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \195	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR2)) \196		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \197	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR)) \198		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \199	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR)) \200		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \201	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_LR)) \202		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \203	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR)) \204		ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \205	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_CR4)) \206		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \207	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_KR4)) \208		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \209	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_LR4)) \210		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \211	if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_SR4)) \212		ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \213}214 215static int octep_vf_get_link_ksettings(struct net_device *netdev,216				       struct ethtool_link_ksettings *cmd)217{218	struct octep_vf_device *oct = netdev_priv(netdev);219	struct octep_vf_iface_link_info *link_info;220	u32 advertised_modes, supported_modes;221 222	ethtool_link_ksettings_zero_link_mode(cmd, supported);223	ethtool_link_ksettings_zero_link_mode(cmd, advertising);224 225	octep_vf_get_link_info(oct);226 227	advertised_modes = oct->link_info.advertised_modes;228	supported_modes = oct->link_info.supported_modes;229	link_info = &oct->link_info;230 231	OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported);232	OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising);233 234	if (link_info->autoneg) {235		if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED)236			ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);237		if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED) {238			ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);239			cmd->base.autoneg = AUTONEG_ENABLE;240		} else {241			cmd->base.autoneg = AUTONEG_DISABLE;242		}243	} else {244		cmd->base.autoneg = AUTONEG_DISABLE;245	}246 247	cmd->base.port = PORT_FIBRE;248	ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);249	ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);250 251	if (netif_carrier_ok(netdev)) {252		cmd->base.speed = link_info->speed;253		cmd->base.duplex = DUPLEX_FULL;254	} else {255		cmd->base.speed = SPEED_UNKNOWN;256		cmd->base.duplex = DUPLEX_UNKNOWN;257	}258	return 0;259}260 261static const struct ethtool_ops octep_vf_ethtool_ops = {262	.get_drvinfo = octep_vf_get_drvinfo,263	.get_link = ethtool_op_get_link,264	.get_strings = octep_vf_get_strings,265	.get_sset_count = octep_vf_get_sset_count,266	.get_ethtool_stats = octep_vf_get_ethtool_stats,267	.get_link_ksettings = octep_vf_get_link_ksettings,268};269 270void octep_vf_set_ethtool_ops(struct net_device *netdev)271{272	netdev->ethtool_ops = &octep_vf_ethtool_ops;273}274