cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tsnep_ethtool.c (8504B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */
      3
      4#include "tsnep.h"
      5
      6static const char tsnep_stats_strings[][ETH_GSTRING_LEN] = {
      7	"rx_packets",
      8	"rx_bytes",
      9	"rx_dropped",
     10	"rx_multicast",
     11	"rx_phy_errors",
     12	"rx_forwarded_phy_errors",
     13	"rx_invalid_frame_errors",
     14	"tx_packets",
     15	"tx_bytes",
     16	"tx_dropped",
     17};
     18
     19struct tsnep_stats {
     20	u64 rx_packets;
     21	u64 rx_bytes;
     22	u64 rx_dropped;
     23	u64 rx_multicast;
     24	u64 rx_phy_errors;
     25	u64 rx_forwarded_phy_errors;
     26	u64 rx_invalid_frame_errors;
     27	u64 tx_packets;
     28	u64 tx_bytes;
     29	u64 tx_dropped;
     30};
     31
     32#define TSNEP_STATS_COUNT (sizeof(struct tsnep_stats) / sizeof(u64))
     33
     34static const char tsnep_rx_queue_stats_strings[][ETH_GSTRING_LEN] = {
     35	"rx_%d_packets",
     36	"rx_%d_bytes",
     37	"rx_%d_dropped",
     38	"rx_%d_multicast",
     39	"rx_%d_no_descriptor_errors",
     40	"rx_%d_buffer_too_small_errors",
     41	"rx_%d_fifo_overflow_errors",
     42	"rx_%d_invalid_frame_errors",
     43};
     44
     45struct tsnep_rx_queue_stats {
     46	u64 rx_packets;
     47	u64 rx_bytes;
     48	u64 rx_dropped;
     49	u64 rx_multicast;
     50	u64 rx_no_descriptor_errors;
     51	u64 rx_buffer_too_small_errors;
     52	u64 rx_fifo_overflow_errors;
     53	u64 rx_invalid_frame_errors;
     54};
     55
     56#define TSNEP_RX_QUEUE_STATS_COUNT (sizeof(struct tsnep_rx_queue_stats) / \
     57				    sizeof(u64))
     58
     59static const char tsnep_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
     60	"tx_%d_packets",
     61	"tx_%d_bytes",
     62	"tx_%d_dropped",
     63};
     64
     65struct tsnep_tx_queue_stats {
     66	u64 tx_packets;
     67	u64 tx_bytes;
     68	u64 tx_dropped;
     69};
     70
     71#define TSNEP_TX_QUEUE_STATS_COUNT (sizeof(struct tsnep_tx_queue_stats) / \
     72				    sizeof(u64))
     73
     74static void tsnep_ethtool_get_drvinfo(struct net_device *netdev,
     75				      struct ethtool_drvinfo *drvinfo)
     76{
     77	struct tsnep_adapter *adapter = netdev_priv(netdev);
     78
     79	strscpy(drvinfo->driver, TSNEP, sizeof(drvinfo->driver));
     80	strscpy(drvinfo->bus_info, dev_name(&adapter->pdev->dev),
     81		sizeof(drvinfo->bus_info));
     82}
     83
     84static int tsnep_ethtool_get_regs_len(struct net_device *netdev)
     85{
     86	struct tsnep_adapter *adapter = netdev_priv(netdev);
     87	int len;
     88	int num_additional_queues;
     89
     90	len = TSNEP_MAC_SIZE;
     91
     92	/* first queue pair is within TSNEP_MAC_SIZE, only queues additional to
     93	 * the first queue pair extend the register length by TSNEP_QUEUE_SIZE
     94	 */
     95	num_additional_queues =
     96		max(adapter->num_tx_queues, adapter->num_rx_queues) - 1;
     97	len += TSNEP_QUEUE_SIZE * num_additional_queues;
     98
     99	return len;
    100}
    101
    102static void tsnep_ethtool_get_regs(struct net_device *netdev,
    103				   struct ethtool_regs *regs,
    104				   void *p)
    105{
    106	struct tsnep_adapter *adapter = netdev_priv(netdev);
    107
    108	regs->version = 1;
    109
    110	memcpy_fromio(p, adapter->addr, regs->len);
    111}
    112
    113static u32 tsnep_ethtool_get_msglevel(struct net_device *netdev)
    114{
    115	struct tsnep_adapter *adapter = netdev_priv(netdev);
    116
    117	return adapter->msg_enable;
    118}
    119
    120static void tsnep_ethtool_set_msglevel(struct net_device *netdev, u32 data)
    121{
    122	struct tsnep_adapter *adapter = netdev_priv(netdev);
    123
    124	adapter->msg_enable = data;
    125}
    126
    127static void tsnep_ethtool_get_strings(struct net_device *netdev, u32 stringset,
    128				      u8 *data)
    129{
    130	struct tsnep_adapter *adapter = netdev_priv(netdev);
    131	int rx_count = adapter->num_rx_queues;
    132	int tx_count = adapter->num_tx_queues;
    133	int i, j;
    134
    135	switch (stringset) {
    136	case ETH_SS_STATS:
    137		memcpy(data, tsnep_stats_strings, sizeof(tsnep_stats_strings));
    138		data += sizeof(tsnep_stats_strings);
    139
    140		for (i = 0; i < rx_count; i++) {
    141			for (j = 0; j < TSNEP_RX_QUEUE_STATS_COUNT; j++) {
    142				snprintf(data, ETH_GSTRING_LEN,
    143					 tsnep_rx_queue_stats_strings[j], i);
    144				data += ETH_GSTRING_LEN;
    145			}
    146		}
    147
    148		for (i = 0; i < tx_count; i++) {
    149			for (j = 0; j < TSNEP_TX_QUEUE_STATS_COUNT; j++) {
    150				snprintf(data, ETH_GSTRING_LEN,
    151					 tsnep_tx_queue_stats_strings[j], i);
    152				data += ETH_GSTRING_LEN;
    153			}
    154		}
    155		break;
    156	case ETH_SS_TEST:
    157		tsnep_ethtool_get_test_strings(data);
    158		break;
    159	}
    160}
    161
    162static void tsnep_ethtool_get_ethtool_stats(struct net_device *netdev,
    163					    struct ethtool_stats *stats,
    164					    u64 *data)
    165{
    166	struct tsnep_adapter *adapter = netdev_priv(netdev);
    167	int rx_count = adapter->num_rx_queues;
    168	int tx_count = adapter->num_tx_queues;
    169	struct tsnep_stats tsnep_stats;
    170	struct tsnep_rx_queue_stats tsnep_rx_queue_stats;
    171	struct tsnep_tx_queue_stats tsnep_tx_queue_stats;
    172	u32 reg;
    173	int i;
    174
    175	memset(&tsnep_stats, 0, sizeof(tsnep_stats));
    176	for (i = 0; i < adapter->num_rx_queues; i++) {
    177		tsnep_stats.rx_packets += adapter->rx[i].packets;
    178		tsnep_stats.rx_bytes += adapter->rx[i].bytes;
    179		tsnep_stats.rx_dropped += adapter->rx[i].dropped;
    180		tsnep_stats.rx_multicast += adapter->rx[i].multicast;
    181	}
    182	reg = ioread32(adapter->addr + ECM_STAT);
    183	tsnep_stats.rx_phy_errors =
    184		(reg & ECM_STAT_RX_ERR_MASK) >> ECM_STAT_RX_ERR_SHIFT;
    185	tsnep_stats.rx_forwarded_phy_errors =
    186		(reg & ECM_STAT_FWD_RX_ERR_MASK) >> ECM_STAT_FWD_RX_ERR_SHIFT;
    187	tsnep_stats.rx_invalid_frame_errors =
    188		(reg & ECM_STAT_INV_FRM_MASK) >> ECM_STAT_INV_FRM_SHIFT;
    189	for (i = 0; i < adapter->num_tx_queues; i++) {
    190		tsnep_stats.tx_packets += adapter->tx[i].packets;
    191		tsnep_stats.tx_bytes += adapter->tx[i].bytes;
    192		tsnep_stats.tx_dropped += adapter->tx[i].dropped;
    193	}
    194	memcpy(data, &tsnep_stats, sizeof(tsnep_stats));
    195	data += TSNEP_STATS_COUNT;
    196
    197	for (i = 0; i < rx_count; i++) {
    198		memset(&tsnep_rx_queue_stats, 0, sizeof(tsnep_rx_queue_stats));
    199		tsnep_rx_queue_stats.rx_packets = adapter->rx[i].packets;
    200		tsnep_rx_queue_stats.rx_bytes = adapter->rx[i].bytes;
    201		tsnep_rx_queue_stats.rx_dropped = adapter->rx[i].dropped;
    202		tsnep_rx_queue_stats.rx_multicast = adapter->rx[i].multicast;
    203		reg = ioread32(adapter->addr + TSNEP_QUEUE(i) +
    204			       TSNEP_RX_STATISTIC);
    205		tsnep_rx_queue_stats.rx_no_descriptor_errors =
    206			(reg & TSNEP_RX_STATISTIC_NO_DESC_MASK) >>
    207			TSNEP_RX_STATISTIC_NO_DESC_SHIFT;
    208		tsnep_rx_queue_stats.rx_buffer_too_small_errors =
    209			(reg & TSNEP_RX_STATISTIC_BUFFER_TOO_SMALL_MASK) >>
    210			TSNEP_RX_STATISTIC_BUFFER_TOO_SMALL_SHIFT;
    211		tsnep_rx_queue_stats.rx_fifo_overflow_errors =
    212			(reg & TSNEP_RX_STATISTIC_FIFO_OVERFLOW_MASK) >>
    213			TSNEP_RX_STATISTIC_FIFO_OVERFLOW_SHIFT;
    214		tsnep_rx_queue_stats.rx_invalid_frame_errors =
    215			(reg & TSNEP_RX_STATISTIC_INVALID_FRAME_MASK) >>
    216			TSNEP_RX_STATISTIC_INVALID_FRAME_SHIFT;
    217		memcpy(data, &tsnep_rx_queue_stats,
    218		       sizeof(tsnep_rx_queue_stats));
    219		data += TSNEP_RX_QUEUE_STATS_COUNT;
    220	}
    221
    222	for (i = 0; i < tx_count; i++) {
    223		memset(&tsnep_tx_queue_stats, 0, sizeof(tsnep_tx_queue_stats));
    224		tsnep_tx_queue_stats.tx_packets += adapter->tx[i].packets;
    225		tsnep_tx_queue_stats.tx_bytes += adapter->tx[i].bytes;
    226		tsnep_tx_queue_stats.tx_dropped += adapter->tx[i].dropped;
    227		memcpy(data, &tsnep_tx_queue_stats,
    228		       sizeof(tsnep_tx_queue_stats));
    229		data += TSNEP_TX_QUEUE_STATS_COUNT;
    230	}
    231}
    232
    233static int tsnep_ethtool_get_sset_count(struct net_device *netdev, int sset)
    234{
    235	struct tsnep_adapter *adapter = netdev_priv(netdev);
    236	int rx_count;
    237	int tx_count;
    238
    239	switch (sset) {
    240	case ETH_SS_STATS:
    241		rx_count = adapter->num_rx_queues;
    242		tx_count = adapter->num_tx_queues;
    243		return TSNEP_STATS_COUNT +
    244		       TSNEP_RX_QUEUE_STATS_COUNT * rx_count +
    245		       TSNEP_TX_QUEUE_STATS_COUNT * tx_count;
    246	case ETH_SS_TEST:
    247		return tsnep_ethtool_get_test_count();
    248	default:
    249		return -EOPNOTSUPP;
    250	}
    251}
    252
    253static int tsnep_ethtool_get_ts_info(struct net_device *dev,
    254				     struct ethtool_ts_info *info)
    255{
    256	struct tsnep_adapter *adapter = netdev_priv(dev);
    257
    258	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
    259				SOF_TIMESTAMPING_RX_SOFTWARE |
    260				SOF_TIMESTAMPING_SOFTWARE |
    261				SOF_TIMESTAMPING_TX_HARDWARE |
    262				SOF_TIMESTAMPING_RX_HARDWARE |
    263				SOF_TIMESTAMPING_RAW_HARDWARE;
    264
    265	if (adapter->ptp_clock)
    266		info->phc_index = ptp_clock_index(adapter->ptp_clock);
    267	else
    268		info->phc_index = -1;
    269
    270	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
    271			 BIT(HWTSTAMP_TX_ON);
    272	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
    273			   BIT(HWTSTAMP_FILTER_ALL);
    274
    275	return 0;
    276}
    277
    278const struct ethtool_ops tsnep_ethtool_ops = {
    279	.get_drvinfo = tsnep_ethtool_get_drvinfo,
    280	.get_regs_len = tsnep_ethtool_get_regs_len,
    281	.get_regs = tsnep_ethtool_get_regs,
    282	.get_msglevel = tsnep_ethtool_get_msglevel,
    283	.set_msglevel = tsnep_ethtool_set_msglevel,
    284	.nway_reset = phy_ethtool_nway_reset,
    285	.get_link = ethtool_op_get_link,
    286	.self_test = tsnep_ethtool_self_test,
    287	.get_strings = tsnep_ethtool_get_strings,
    288	.get_ethtool_stats = tsnep_ethtool_get_ethtool_stats,
    289	.get_sset_count = tsnep_ethtool_get_sset_count,
    290	.get_ts_info = tsnep_ethtool_get_ts_info,
    291	.get_link_ksettings = phy_ethtool_get_link_ksettings,
    292	.set_link_ksettings = phy_ethtool_set_link_ksettings,
    293};