mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
net: lan966x: add ethtool configuration and statistics
This patch adds support for statistics counters for the network interfaces. Also adds support for configuring the network interface via ethtool like: speed, duplex etc. Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e18aba8941
commit
12c2d0a5b8
@ -6,4 +6,4 @@
|
||||
obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
|
||||
|
||||
lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
|
||||
lan966x_mac.o
|
||||
lan966x_mac.o lan966x_ethtool.o
|
||||
|
682
drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c
Normal file
682
drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c
Normal file
@ -0,0 +1,682 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "lan966x_main.h"
|
||||
|
||||
/* Number of traffic classes */
|
||||
#define LAN966X_NUM_TC 8
|
||||
#define LAN966X_STATS_CHECK_DELAY (2 * HZ)
|
||||
|
||||
static const struct lan966x_stat_layout lan966x_stats_layout[] = {
|
||||
{ .name = "rx_octets", .offset = 0x00, },
|
||||
{ .name = "rx_unicast", .offset = 0x01, },
|
||||
{ .name = "rx_multicast", .offset = 0x02 },
|
||||
{ .name = "rx_broadcast", .offset = 0x03 },
|
||||
{ .name = "rx_short", .offset = 0x04 },
|
||||
{ .name = "rx_frag", .offset = 0x05 },
|
||||
{ .name = "rx_jabber", .offset = 0x06 },
|
||||
{ .name = "rx_crc", .offset = 0x07 },
|
||||
{ .name = "rx_symbol_err", .offset = 0x08 },
|
||||
{ .name = "rx_sz_64", .offset = 0x09 },
|
||||
{ .name = "rx_sz_65_127", .offset = 0x0a},
|
||||
{ .name = "rx_sz_128_255", .offset = 0x0b},
|
||||
{ .name = "rx_sz_256_511", .offset = 0x0c },
|
||||
{ .name = "rx_sz_512_1023", .offset = 0x0d },
|
||||
{ .name = "rx_sz_1024_1526", .offset = 0x0e },
|
||||
{ .name = "rx_sz_jumbo", .offset = 0x0f },
|
||||
{ .name = "rx_pause", .offset = 0x10 },
|
||||
{ .name = "rx_control", .offset = 0x11 },
|
||||
{ .name = "rx_long", .offset = 0x12 },
|
||||
{ .name = "rx_cat_drop", .offset = 0x13 },
|
||||
{ .name = "rx_red_prio_0", .offset = 0x14 },
|
||||
{ .name = "rx_red_prio_1", .offset = 0x15 },
|
||||
{ .name = "rx_red_prio_2", .offset = 0x16 },
|
||||
{ .name = "rx_red_prio_3", .offset = 0x17 },
|
||||
{ .name = "rx_red_prio_4", .offset = 0x18 },
|
||||
{ .name = "rx_red_prio_5", .offset = 0x19 },
|
||||
{ .name = "rx_red_prio_6", .offset = 0x1a },
|
||||
{ .name = "rx_red_prio_7", .offset = 0x1b },
|
||||
{ .name = "rx_yellow_prio_0", .offset = 0x1c },
|
||||
{ .name = "rx_yellow_prio_1", .offset = 0x1d },
|
||||
{ .name = "rx_yellow_prio_2", .offset = 0x1e },
|
||||
{ .name = "rx_yellow_prio_3", .offset = 0x1f },
|
||||
{ .name = "rx_yellow_prio_4", .offset = 0x20 },
|
||||
{ .name = "rx_yellow_prio_5", .offset = 0x21 },
|
||||
{ .name = "rx_yellow_prio_6", .offset = 0x22 },
|
||||
{ .name = "rx_yellow_prio_7", .offset = 0x23 },
|
||||
{ .name = "rx_green_prio_0", .offset = 0x24 },
|
||||
{ .name = "rx_green_prio_1", .offset = 0x25 },
|
||||
{ .name = "rx_green_prio_2", .offset = 0x26 },
|
||||
{ .name = "rx_green_prio_3", .offset = 0x27 },
|
||||
{ .name = "rx_green_prio_4", .offset = 0x28 },
|
||||
{ .name = "rx_green_prio_5", .offset = 0x29 },
|
||||
{ .name = "rx_green_prio_6", .offset = 0x2a },
|
||||
{ .name = "rx_green_prio_7", .offset = 0x2b },
|
||||
{ .name = "rx_assembly_err", .offset = 0x2c },
|
||||
{ .name = "rx_smd_err", .offset = 0x2d },
|
||||
{ .name = "rx_assembly_ok", .offset = 0x2e },
|
||||
{ .name = "rx_merge_frag", .offset = 0x2f },
|
||||
{ .name = "rx_pmac_octets", .offset = 0x30, },
|
||||
{ .name = "rx_pmac_unicast", .offset = 0x31, },
|
||||
{ .name = "rx_pmac_multicast", .offset = 0x32 },
|
||||
{ .name = "rx_pmac_broadcast", .offset = 0x33 },
|
||||
{ .name = "rx_pmac_short", .offset = 0x34 },
|
||||
{ .name = "rx_pmac_frag", .offset = 0x35 },
|
||||
{ .name = "rx_pmac_jabber", .offset = 0x36 },
|
||||
{ .name = "rx_pmac_crc", .offset = 0x37 },
|
||||
{ .name = "rx_pmac_symbol_err", .offset = 0x38 },
|
||||
{ .name = "rx_pmac_sz_64", .offset = 0x39 },
|
||||
{ .name = "rx_pmac_sz_65_127", .offset = 0x3a },
|
||||
{ .name = "rx_pmac_sz_128_255", .offset = 0x3b },
|
||||
{ .name = "rx_pmac_sz_256_511", .offset = 0x3c },
|
||||
{ .name = "rx_pmac_sz_512_1023", .offset = 0x3d },
|
||||
{ .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },
|
||||
{ .name = "rx_pmac_sz_jumbo", .offset = 0x3f },
|
||||
{ .name = "rx_pmac_pause", .offset = 0x40 },
|
||||
{ .name = "rx_pmac_control", .offset = 0x41 },
|
||||
{ .name = "rx_pmac_long", .offset = 0x42 },
|
||||
|
||||
{ .name = "tx_octets", .offset = 0x80, },
|
||||
{ .name = "tx_unicast", .offset = 0x81, },
|
||||
{ .name = "tx_multicast", .offset = 0x82 },
|
||||
{ .name = "tx_broadcast", .offset = 0x83 },
|
||||
{ .name = "tx_col", .offset = 0x84 },
|
||||
{ .name = "tx_drop", .offset = 0x85 },
|
||||
{ .name = "tx_pause", .offset = 0x86 },
|
||||
{ .name = "tx_sz_64", .offset = 0x87 },
|
||||
{ .name = "tx_sz_65_127", .offset = 0x88 },
|
||||
{ .name = "tx_sz_128_255", .offset = 0x89 },
|
||||
{ .name = "tx_sz_256_511", .offset = 0x8a },
|
||||
{ .name = "tx_sz_512_1023", .offset = 0x8b },
|
||||
{ .name = "tx_sz_1024_1526", .offset = 0x8c },
|
||||
{ .name = "tx_sz_jumbo", .offset = 0x8d },
|
||||
{ .name = "tx_yellow_prio_0", .offset = 0x8e },
|
||||
{ .name = "tx_yellow_prio_1", .offset = 0x8f },
|
||||
{ .name = "tx_yellow_prio_2", .offset = 0x90 },
|
||||
{ .name = "tx_yellow_prio_3", .offset = 0x91 },
|
||||
{ .name = "tx_yellow_prio_4", .offset = 0x92 },
|
||||
{ .name = "tx_yellow_prio_5", .offset = 0x93 },
|
||||
{ .name = "tx_yellow_prio_6", .offset = 0x94 },
|
||||
{ .name = "tx_yellow_prio_7", .offset = 0x95 },
|
||||
{ .name = "tx_green_prio_0", .offset = 0x96 },
|
||||
{ .name = "tx_green_prio_1", .offset = 0x97 },
|
||||
{ .name = "tx_green_prio_2", .offset = 0x98 },
|
||||
{ .name = "tx_green_prio_3", .offset = 0x99 },
|
||||
{ .name = "tx_green_prio_4", .offset = 0x9a },
|
||||
{ .name = "tx_green_prio_5", .offset = 0x9b },
|
||||
{ .name = "tx_green_prio_6", .offset = 0x9c },
|
||||
{ .name = "tx_green_prio_7", .offset = 0x9d },
|
||||
{ .name = "tx_aged", .offset = 0x9e },
|
||||
{ .name = "tx_llct", .offset = 0x9f },
|
||||
{ .name = "tx_ct", .offset = 0xa0 },
|
||||
{ .name = "tx_mm_hold", .offset = 0xa1 },
|
||||
{ .name = "tx_merge_frag", .offset = 0xa2 },
|
||||
{ .name = "tx_pmac_octets", .offset = 0xa3, },
|
||||
{ .name = "tx_pmac_unicast", .offset = 0xa4, },
|
||||
{ .name = "tx_pmac_multicast", .offset = 0xa5 },
|
||||
{ .name = "tx_pmac_broadcast", .offset = 0xa6 },
|
||||
{ .name = "tx_pmac_pause", .offset = 0xa7 },
|
||||
{ .name = "tx_pmac_sz_64", .offset = 0xa8 },
|
||||
{ .name = "tx_pmac_sz_65_127", .offset = 0xa9 },
|
||||
{ .name = "tx_pmac_sz_128_255", .offset = 0xaa },
|
||||
{ .name = "tx_pmac_sz_256_511", .offset = 0xab },
|
||||
{ .name = "tx_pmac_sz_512_1023", .offset = 0xac },
|
||||
{ .name = "tx_pmac_sz_1024_1526", .offset = 0xad },
|
||||
{ .name = "tx_pmac_sz_jumbo", .offset = 0xae },
|
||||
|
||||
{ .name = "dr_local", .offset = 0x100 },
|
||||
{ .name = "dr_tail", .offset = 0x101 },
|
||||
{ .name = "dr_yellow_prio_0", .offset = 0x102 },
|
||||
{ .name = "dr_yellow_prio_1", .offset = 0x103 },
|
||||
{ .name = "dr_yellow_prio_2", .offset = 0x104 },
|
||||
{ .name = "dr_yellow_prio_3", .offset = 0x105 },
|
||||
{ .name = "dr_yellow_prio_4", .offset = 0x106 },
|
||||
{ .name = "dr_yellow_prio_5", .offset = 0x107 },
|
||||
{ .name = "dr_yellow_prio_6", .offset = 0x108 },
|
||||
{ .name = "dr_yellow_prio_7", .offset = 0x109 },
|
||||
{ .name = "dr_green_prio_0", .offset = 0x10a },
|
||||
{ .name = "dr_green_prio_1", .offset = 0x10b },
|
||||
{ .name = "dr_green_prio_2", .offset = 0x10c },
|
||||
{ .name = "dr_green_prio_3", .offset = 0x10d },
|
||||
{ .name = "dr_green_prio_4", .offset = 0x10e },
|
||||
{ .name = "dr_green_prio_5", .offset = 0x10f },
|
||||
{ .name = "dr_green_prio_6", .offset = 0x110 },
|
||||
{ .name = "dr_green_prio_7", .offset = 0x111 },
|
||||
};
|
||||
|
||||
/* The following numbers are indexes into lan966x_stats_layout[] */
|
||||
#define SYS_COUNT_RX_OCT 0
|
||||
#define SYS_COUNT_RX_UC 1
|
||||
#define SYS_COUNT_RX_MC 2
|
||||
#define SYS_COUNT_RX_BC 3
|
||||
#define SYS_COUNT_RX_SHORT 4
|
||||
#define SYS_COUNT_RX_FRAG 5
|
||||
#define SYS_COUNT_RX_JABBER 6
|
||||
#define SYS_COUNT_RX_CRC 7
|
||||
#define SYS_COUNT_RX_SYMBOL_ERR 8
|
||||
#define SYS_COUNT_RX_SZ_64 9
|
||||
#define SYS_COUNT_RX_SZ_65_127 10
|
||||
#define SYS_COUNT_RX_SZ_128_255 11
|
||||
#define SYS_COUNT_RX_SZ_256_511 12
|
||||
#define SYS_COUNT_RX_SZ_512_1023 13
|
||||
#define SYS_COUNT_RX_SZ_1024_1526 14
|
||||
#define SYS_COUNT_RX_SZ_JUMBO 15
|
||||
#define SYS_COUNT_RX_PAUSE 16
|
||||
#define SYS_COUNT_RX_CONTROL 17
|
||||
#define SYS_COUNT_RX_LONG 18
|
||||
#define SYS_COUNT_RX_CAT_DROP 19
|
||||
#define SYS_COUNT_RX_RED_PRIO_0 20
|
||||
#define SYS_COUNT_RX_RED_PRIO_1 21
|
||||
#define SYS_COUNT_RX_RED_PRIO_2 22
|
||||
#define SYS_COUNT_RX_RED_PRIO_3 23
|
||||
#define SYS_COUNT_RX_RED_PRIO_4 24
|
||||
#define SYS_COUNT_RX_RED_PRIO_5 25
|
||||
#define SYS_COUNT_RX_RED_PRIO_6 26
|
||||
#define SYS_COUNT_RX_RED_PRIO_7 27
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_0 28
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_1 29
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_2 30
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_3 31
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_4 32
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_5 33
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_6 34
|
||||
#define SYS_COUNT_RX_YELLOW_PRIO_7 35
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_0 36
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_1 37
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_2 38
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_3 39
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_4 40
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_5 41
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_6 42
|
||||
#define SYS_COUNT_RX_GREEN_PRIO_7 43
|
||||
#define SYS_COUNT_RX_ASSEMBLY_ERR 44
|
||||
#define SYS_COUNT_RX_SMD_ERR 45
|
||||
#define SYS_COUNT_RX_ASSEMBLY_OK 46
|
||||
#define SYS_COUNT_RX_MERGE_FRAG 47
|
||||
#define SYS_COUNT_RX_PMAC_OCT 48
|
||||
#define SYS_COUNT_RX_PMAC_UC 49
|
||||
#define SYS_COUNT_RX_PMAC_MC 50
|
||||
#define SYS_COUNT_RX_PMAC_BC 51
|
||||
#define SYS_COUNT_RX_PMAC_SHORT 52
|
||||
#define SYS_COUNT_RX_PMAC_FRAG 53
|
||||
#define SYS_COUNT_RX_PMAC_JABBER 54
|
||||
#define SYS_COUNT_RX_PMAC_CRC 55
|
||||
#define SYS_COUNT_RX_PMAC_SYMBOL_ERR 56
|
||||
#define SYS_COUNT_RX_PMAC_SZ_64 57
|
||||
#define SYS_COUNT_RX_PMAC_SZ_65_127 58
|
||||
#define SYS_COUNT_RX_PMAC_SZ_128_255 59
|
||||
#define SYS_COUNT_RX_PMAC_SZ_256_511 60
|
||||
#define SYS_COUNT_RX_PMAC_SZ_512_1023 61
|
||||
#define SYS_COUNT_RX_PMAC_SZ_1024_1526 62
|
||||
#define SYS_COUNT_RX_PMAC_SZ_JUMBO 63
|
||||
#define SYS_COUNT_RX_PMAC_PAUSE 64
|
||||
#define SYS_COUNT_RX_PMAC_CONTROL 65
|
||||
#define SYS_COUNT_RX_PMAC_LONG 66
|
||||
|
||||
#define SYS_COUNT_TX_OCT 67
|
||||
#define SYS_COUNT_TX_UC 68
|
||||
#define SYS_COUNT_TX_MC 69
|
||||
#define SYS_COUNT_TX_BC 70
|
||||
#define SYS_COUNT_TX_COL 71
|
||||
#define SYS_COUNT_TX_DROP 72
|
||||
#define SYS_COUNT_TX_PAUSE 73
|
||||
#define SYS_COUNT_TX_SZ_64 74
|
||||
#define SYS_COUNT_TX_SZ_65_127 75
|
||||
#define SYS_COUNT_TX_SZ_128_255 76
|
||||
#define SYS_COUNT_TX_SZ_256_511 77
|
||||
#define SYS_COUNT_TX_SZ_512_1023 78
|
||||
#define SYS_COUNT_TX_SZ_1024_1526 79
|
||||
#define SYS_COUNT_TX_SZ_JUMBO 80
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_0 81
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_1 82
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_2 83
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_3 84
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_4 85
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_5 86
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_6 87
|
||||
#define SYS_COUNT_TX_YELLOW_PRIO_7 88
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_0 89
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_1 90
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_2 91
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_3 92
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_4 93
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_5 94
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_6 95
|
||||
#define SYS_COUNT_TX_GREEN_PRIO_7 96
|
||||
#define SYS_COUNT_TX_AGED 97
|
||||
#define SYS_COUNT_TX_LLCT 98
|
||||
#define SYS_COUNT_TX_CT 99
|
||||
#define SYS_COUNT_TX_MM_HOLD 100
|
||||
#define SYS_COUNT_TX_MERGE_FRAG 101
|
||||
#define SYS_COUNT_TX_PMAC_OCT 102
|
||||
#define SYS_COUNT_TX_PMAC_UC 103
|
||||
#define SYS_COUNT_TX_PMAC_MC 104
|
||||
#define SYS_COUNT_TX_PMAC_BC 105
|
||||
#define SYS_COUNT_TX_PMAC_PAUSE 106
|
||||
#define SYS_COUNT_TX_PMAC_SZ_64 107
|
||||
#define SYS_COUNT_TX_PMAC_SZ_65_127 108
|
||||
#define SYS_COUNT_TX_PMAC_SZ_128_255 109
|
||||
#define SYS_COUNT_TX_PMAC_SZ_256_511 110
|
||||
#define SYS_COUNT_TX_PMAC_SZ_512_1023 111
|
||||
#define SYS_COUNT_TX_PMAC_SZ_1024_1526 112
|
||||
#define SYS_COUNT_TX_PMAC_SZ_JUMBO 113
|
||||
|
||||
#define SYS_COUNT_DR_LOCAL 114
|
||||
#define SYS_COUNT_DR_TAIL 115
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_0 116
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_1 117
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_2 118
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_3 119
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_4 120
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_5 121
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_6 122
|
||||
#define SYS_COUNT_DR_YELLOW_PRIO_7 123
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_0 124
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_1 125
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_2 126
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_3 127
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_4 128
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_5 129
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_6 130
|
||||
#define SYS_COUNT_DR_GREEN_PRIO_7 131
|
||||
|
||||
/* Add a possibly wrapping 32 bit value to a 64 bit counter */
|
||||
static void lan966x_add_cnt(u64 *cnt, u32 val)
|
||||
{
|
||||
if (val < (*cnt & U32_MAX))
|
||||
*cnt += (u64)1 << 32; /* value has wrapped */
|
||||
|
||||
*cnt = (*cnt & ~(u64)U32_MAX) + val;
|
||||
}
|
||||
|
||||
static void lan966x_stats_update(struct lan966x *lan966x)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
mutex_lock(&lan966x->stats_lock);
|
||||
|
||||
for (i = 0; i < lan966x->num_phys_ports; i++) {
|
||||
uint idx = i * lan966x->num_stats;
|
||||
|
||||
lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),
|
||||
lan966x, SYS_STAT_CFG);
|
||||
|
||||
for (j = 0; j < lan966x->num_stats; j++) {
|
||||
u32 offset = lan966x->stats_layout[j].offset;
|
||||
|
||||
lan966x_add_cnt(&lan966x->stats[idx++],
|
||||
lan_rd(lan966x, SYS_CNT(offset)));
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&lan966x->stats_lock);
|
||||
}
|
||||
|
||||
static int lan966x_get_sset_count(struct net_device *dev, int sset)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return lan966x->num_stats;
|
||||
}
|
||||
|
||||
static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(netdev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
int i;
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < lan966x->num_stats; i++)
|
||||
memcpy(data + i * ETH_GSTRING_LEN,
|
||||
lan966x->stats_layout[i].name, ETH_GSTRING_LEN);
|
||||
}
|
||||
|
||||
static void lan966x_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
int i;
|
||||
|
||||
/* check and update now */
|
||||
lan966x_stats_update(lan966x);
|
||||
|
||||
/* Copy all counters */
|
||||
for (i = 0; i < lan966x->num_stats; i++)
|
||||
*data++ = lan966x->stats[port->chip_port *
|
||||
lan966x->num_stats + i];
|
||||
}
|
||||
|
||||
static void lan966x_get_eth_mac_stats(struct net_device *dev,
|
||||
struct ethtool_eth_mac_stats *mac_stats)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
u32 idx;
|
||||
|
||||
lan966x_stats_update(lan966x);
|
||||
|
||||
idx = port->chip_port * lan966x->num_stats;
|
||||
|
||||
mutex_lock(&lan966x->stats_lock);
|
||||
|
||||
mac_stats->FramesTransmittedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_UC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_MC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_BC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
|
||||
mac_stats->SingleCollisionFrames =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_COL];
|
||||
mac_stats->MultipleCollisionFrames = 0;
|
||||
mac_stats->FramesReceivedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_UC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_MC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_BC];
|
||||
mac_stats->FrameCheckSequenceErrors =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_CRC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_CRC];
|
||||
mac_stats->AlignmentErrors = 0;
|
||||
mac_stats->OctetsTransmittedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_OCT] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
|
||||
mac_stats->FramesWithDeferredXmissions =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
|
||||
mac_stats->LateCollisions = 0;
|
||||
mac_stats->FramesAbortedDueToXSColls = 0;
|
||||
mac_stats->FramesLostDueToIntMACXmitError = 0;
|
||||
mac_stats->CarrierSenseErrors = 0;
|
||||
mac_stats->OctetsReceivedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_OCT];
|
||||
mac_stats->FramesLostDueToIntMACRcvError = 0;
|
||||
mac_stats->MulticastFramesXmittedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_MC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
|
||||
mac_stats->BroadcastFramesXmittedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_BC] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
|
||||
mac_stats->FramesWithExcessiveDeferral = 0;
|
||||
mac_stats->MulticastFramesReceivedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_MC];
|
||||
mac_stats->BroadcastFramesReceivedOK =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_BC];
|
||||
mac_stats->InRangeLengthErrors =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_CRC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
|
||||
mac_stats->OutOfRangeLengthField =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
|
||||
mac_stats->FrameTooLongErrors =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
|
||||
|
||||
mutex_unlock(&lan966x->stats_lock);
|
||||
}
|
||||
|
||||
static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
|
||||
{ 0, 64 },
|
||||
{ 65, 127 },
|
||||
{ 128, 255 },
|
||||
{ 256, 511 },
|
||||
{ 512, 1023 },
|
||||
{ 1024, 1518 },
|
||||
{ 1519, 10239 },
|
||||
{}
|
||||
};
|
||||
|
||||
static void lan966x_get_eth_rmon_stats(struct net_device *dev,
|
||||
struct ethtool_rmon_stats *rmon_stats,
|
||||
const struct ethtool_rmon_hist_range **ranges)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
u32 idx;
|
||||
|
||||
lan966x_stats_update(lan966x);
|
||||
|
||||
idx = port->chip_port * lan966x->num_stats;
|
||||
|
||||
mutex_lock(&lan966x->stats_lock);
|
||||
|
||||
rmon_stats->undersize_pkts =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
|
||||
rmon_stats->oversize_pkts =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
|
||||
rmon_stats->fragments =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
|
||||
rmon_stats->jabbers =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
|
||||
rmon_stats->hist[0] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
|
||||
rmon_stats->hist[1] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
|
||||
rmon_stats->hist[2] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
|
||||
rmon_stats->hist[3] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
|
||||
rmon_stats->hist[4] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
|
||||
rmon_stats->hist[5] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
|
||||
rmon_stats->hist[6] =
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
|
||||
|
||||
rmon_stats->hist_tx[0] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
|
||||
rmon_stats->hist_tx[1] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
|
||||
rmon_stats->hist_tx[2] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
|
||||
rmon_stats->hist_tx[3] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
|
||||
rmon_stats->hist_tx[4] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
|
||||
rmon_stats->hist_tx[5] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
|
||||
rmon_stats->hist_tx[6] =
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
|
||||
|
||||
mutex_unlock(&lan966x->stats_lock);
|
||||
|
||||
*ranges = lan966x_rmon_ranges;
|
||||
}
|
||||
|
||||
static int lan966x_get_link_ksettings(struct net_device *ndev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(ndev);
|
||||
|
||||
return phylink_ethtool_ksettings_get(port->phylink, cmd);
|
||||
}
|
||||
|
||||
static int lan966x_set_link_ksettings(struct net_device *ndev,
|
||||
const struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(ndev);
|
||||
|
||||
return phylink_ethtool_ksettings_set(port->phylink, cmd);
|
||||
}
|
||||
|
||||
static void lan966x_get_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
|
||||
phylink_ethtool_get_pauseparam(port->phylink, pause);
|
||||
}
|
||||
|
||||
static int lan966x_set_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
|
||||
return phylink_ethtool_set_pauseparam(port->phylink, pause);
|
||||
}
|
||||
|
||||
const struct ethtool_ops lan966x_ethtool_ops = {
|
||||
.get_link_ksettings = lan966x_get_link_ksettings,
|
||||
.set_link_ksettings = lan966x_set_link_ksettings,
|
||||
.get_pauseparam = lan966x_get_pauseparam,
|
||||
.set_pauseparam = lan966x_set_pauseparam,
|
||||
.get_sset_count = lan966x_get_sset_count,
|
||||
.get_strings = lan966x_get_strings,
|
||||
.get_ethtool_stats = lan966x_get_ethtool_stats,
|
||||
.get_eth_mac_stats = lan966x_get_eth_mac_stats,
|
||||
.get_rmon_stats = lan966x_get_eth_rmon_stats,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static void lan966x_check_stats_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *del_work = to_delayed_work(work);
|
||||
struct lan966x *lan966x = container_of(del_work, struct lan966x,
|
||||
stats_work);
|
||||
|
||||
lan966x_stats_update(lan966x);
|
||||
|
||||
queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
|
||||
LAN966X_STATS_CHECK_DELAY);
|
||||
}
|
||||
|
||||
void lan966x_stats_get(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct lan966x_port *port = netdev_priv(dev);
|
||||
struct lan966x *lan966x = port->lan966x;
|
||||
u32 idx;
|
||||
int i;
|
||||
|
||||
idx = port->chip_port * lan966x->num_stats;
|
||||
|
||||
mutex_lock(&lan966x->stats_lock);
|
||||
|
||||
stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
|
||||
|
||||
stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_CRC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
|
||||
|
||||
stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
|
||||
|
||||
stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_CRC] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG];
|
||||
|
||||
stats->rx_dropped = dev->stats.rx_dropped +
|
||||
lan966x->stats[idx + SYS_COUNT_RX_LONG] +
|
||||
lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
|
||||
lan966x->stats[idx + SYS_COUNT_DR_TAIL];
|
||||
|
||||
for (i = 0; i < LAN966X_NUM_TC; i++) {
|
||||
stats->rx_dropped +=
|
||||
(lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
|
||||
lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
|
||||
}
|
||||
|
||||
/* Get Tx stats */
|
||||
stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
|
||||
|
||||
stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
|
||||
|
||||
stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
|
||||
lan966x->stats[idx + SYS_COUNT_TX_AGED];
|
||||
|
||||
stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
|
||||
|
||||
mutex_unlock(&lan966x->stats_lock);
|
||||
}
|
||||
|
||||
int lan966x_stats_init(struct lan966x *lan966x)
|
||||
{
|
||||
char queue_name[32];
|
||||
|
||||
lan966x->stats_layout = lan966x_stats_layout;
|
||||
lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
|
||||
lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
|
||||
lan966x->num_stats,
|
||||
sizeof(u64), GFP_KERNEL);
|
||||
if (!lan966x->stats)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Init stats worker */
|
||||
mutex_init(&lan966x->stats_lock);
|
||||
snprintf(queue_name, sizeof(queue_name), "%s-stats",
|
||||
dev_name(lan966x->dev));
|
||||
lan966x->stats_queue = create_singlethread_workqueue(queue_name);
|
||||
INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);
|
||||
queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
|
||||
LAN966X_STATS_CHECK_DELAY);
|
||||
|
||||
return 0;
|
||||
}
|
@ -373,6 +373,7 @@ static const struct net_device_ops lan966x_port_netdev_ops = {
|
||||
.ndo_change_mtu = lan966x_port_change_mtu,
|
||||
.ndo_set_rx_mode = lan966x_port_set_rx_mode,
|
||||
.ndo_get_phys_port_name = lan966x_port_get_phys_port_name,
|
||||
.ndo_get_stats64 = lan966x_stats_get,
|
||||
.ndo_set_mac_address = lan966x_port_set_mac_address,
|
||||
.ndo_get_port_parent_id = lan966x_port_get_parent_id,
|
||||
};
|
||||
@ -588,6 +589,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
|
||||
dev->max_mtu = ETH_MAX_MTU;
|
||||
|
||||
dev->netdev_ops = &lan966x_port_netdev_ops;
|
||||
dev->ethtool_ops = &lan966x_ethtool_ops;
|
||||
dev->needed_headroom = IFH_LEN * sizeof(u32);
|
||||
|
||||
eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
|
||||
@ -875,6 +877,7 @@ static int lan966x_probe(struct platform_device *pdev)
|
||||
|
||||
/* init switch */
|
||||
lan966x_init(lan966x);
|
||||
lan966x_stats_init(lan966x);
|
||||
|
||||
/* go over the child nodes */
|
||||
fwnode_for_each_available_child_node(ports, portnp) {
|
||||
@ -908,6 +911,10 @@ cleanup_ports:
|
||||
|
||||
lan966x_cleanup_ports(lan966x);
|
||||
|
||||
cancel_delayed_work_sync(&lan966x->stats_work);
|
||||
destroy_workqueue(lan966x->stats_queue);
|
||||
mutex_destroy(&lan966x->stats_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -917,6 +924,10 @@ static int lan966x_remove(struct platform_device *pdev)
|
||||
|
||||
lan966x_cleanup_ports(lan966x);
|
||||
|
||||
cancel_delayed_work_sync(&lan966x->stats_work);
|
||||
destroy_workqueue(lan966x->stats_queue);
|
||||
mutex_destroy(&lan966x->stats_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,11 @@ enum macaccess_entry_type {
|
||||
|
||||
struct lan966x_port;
|
||||
|
||||
struct lan966x_stat_layout {
|
||||
u32 offset;
|
||||
char name[ETH_GSTRING_LEN];
|
||||
};
|
||||
|
||||
struct lan966x {
|
||||
struct device *dev;
|
||||
|
||||
@ -70,6 +75,16 @@ struct lan966x {
|
||||
|
||||
u8 base_mac[ETH_ALEN];
|
||||
|
||||
/* stats */
|
||||
const struct lan966x_stat_layout *stats_layout;
|
||||
u32 num_stats;
|
||||
|
||||
/* workqueue for reading stats */
|
||||
struct mutex stats_lock;
|
||||
u64 *stats;
|
||||
struct delayed_work stats_work;
|
||||
struct workqueue_struct *stats_queue;
|
||||
|
||||
/* interrupts */
|
||||
int xtr_irq;
|
||||
};
|
||||
@ -101,6 +116,11 @@ struct lan966x_port {
|
||||
|
||||
extern const struct phylink_mac_ops lan966x_phylink_mac_ops;
|
||||
extern const struct phylink_pcs_ops lan966x_phylink_pcs_ops;
|
||||
extern const struct ethtool_ops lan966x_ethtool_ops;
|
||||
|
||||
void lan966x_stats_get(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats);
|
||||
int lan966x_stats_init(struct lan966x *lan966x);
|
||||
|
||||
void lan966x_port_config_down(struct lan966x_port *port);
|
||||
void lan966x_port_config_up(struct lan966x_port *port);
|
||||
|
Loading…
Reference in New Issue
Block a user