Commit 6fff9261 authored by David S. Miller's avatar David S. Miller

Merge branch 'felix-dsa-ethtool-stats'

Vladimir Oltean says:

====================
Standardized ethtool counters for Felix DSA driver

The main purpose of this change set is to add reporting of structured
ethtool statistics counters to the felix DSA driver (see patch 11/14 for
details), as a prerequisite for extending these counters to the
eMAC/pMAC defined by the IEEE MAC Merge layer.

Along the way, the main purpose has diverged into multiple sub-purposes
which are also tackled:

- A bug fix patch submitted to "net" has made ocelot->stats_lock a spin
  lock, which is not an issue currently (all Ocelot switches are MMIO),
  but will be an issue for Colin Foster who is working on a SPI
  controlled Ocelot switch. We restore the hardware access to port stats
  to be sleepable.

- PSFP (tc-gate, tc-police) tc-flower stats on Felix use a non-converged
  procedure to access the hardware counters, although the interface is
  very similar to what is used for the port counters. Benefit from the
  logic used for the port counters, which gains us 64-bit tc-flower
  stats that are resistant to overflows.

- Also export the ndo_get_stats64 method used by the ocelot switchdev
  driver to Felix, so that ifconfig sees something hardware-based as
  well (but not 100% up to date).

- Create a new ocelot_stats.c file which groups everything stats-related
  together. Along with this, also move some other topic-specific code,
  like FDB and PTP, out of the main ocelot.c.

- Minimize the lines of code for the stats layout definitions. These
  changes alone cause the patch set to have an overall reduction of
  lines of code in the driver, even though we are adding new
  functionality as well.

Tested the port counters with lockdep and friends, with some
garden-variety traffic (ping, iperf3) and the PSFP counters with
tools/testing/selftests/drivers/net/ocelot/psfp.sh.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 34df6a8a 4d1d157f
......@@ -1034,6 +1034,55 @@ static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
}
}
static void felix_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *stats)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_stats64(ocelot, port, stats);
}
static void felix_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_pause_stats(ocelot, port, pause_stats);
}
static void felix_get_rmon_stats(struct dsa_switch *ds, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_rmon_stats(ocelot, port, rmon_stats, ranges);
}
static void felix_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_eth_ctrl_stats(ocelot, port, ctrl_stats);
}
static void felix_get_eth_mac_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_mac_stats *mac_stats)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_eth_mac_stats(ocelot, port, mac_stats);
}
static void felix_get_eth_phy_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_phy_stats *phy_stats)
{
struct ocelot *ocelot = ds->priv;
ocelot_port_get_eth_phy_stats(ocelot, port, phy_stats);
}
static void felix_get_strings(struct dsa_switch *ds, int port,
u32 stringset, u8 *data)
{
......@@ -1848,6 +1897,12 @@ const struct dsa_switch_ops felix_switch_ops = {
.setup = felix_setup,
.teardown = felix_teardown,
.set_ageing_time = felix_set_ageing_time,
.get_stats64 = felix_get_stats64,
.get_pause_stats = felix_get_pause_stats,
.get_rmon_stats = felix_get_rmon_stats,
.get_eth_ctrl_stats = felix_get_eth_ctrl_stats,
.get_eth_mac_stats = felix_get_eth_mac_stats,
.get_eth_phy_stats = felix_get_eth_phy_stats,
.get_strings = felix_get_strings,
.get_ethtool_stats = felix_get_ethtool_stats,
.get_sset_count = felix_get_sset_count,
......
This diff is collapsed.
This diff is collapsed.
......@@ -2,16 +2,17 @@
obj-$(CONFIG_MSCC_OCELOT_SWITCH_LIB) += mscc_ocelot_switch_lib.o
mscc_ocelot_switch_lib-y := \
ocelot.o \
ocelot_devlink.o \
ocelot_flower.o \
ocelot_io.o \
ocelot_police.o \
ocelot_vcap.o \
ocelot_flower.o \
ocelot_ptp.o \
ocelot_devlink.o \
ocelot_stats.o \
ocelot_vcap.o \
vsc7514_regs.o
mscc_ocelot_switch_lib-$(CONFIG_BRIDGE_MRP) += ocelot_mrp.o
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot.o
mscc_ocelot-y := \
ocelot_fdma.o \
ocelot_vsc7514.o \
ocelot_net.o
ocelot_net.o \
ocelot_vsc7514.o
This diff is collapsed.
......@@ -51,13 +51,6 @@ struct ocelot_port_private {
struct ocelot_port_tc tc;
};
struct ocelot_dump_ctx {
struct net_device *dev;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
};
/* A (PGID) port mask structure, encoding the 2^ocelot->num_phys_ports
* possibilities of egress port masks for L2 multicast traffic.
* For a switch with 9 user ports, there are 512 possible port masks, but the
......@@ -84,8 +77,6 @@ struct ocelot_multicast {
int ocelot_bridge_num_find(struct ocelot *ocelot,
const struct net_device *bridge);
int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
bool is_static, void *data);
int ocelot_mact_learn(struct ocelot *ocelot, int port,
const unsigned char mac[ETH_ALEN],
unsigned int vid, enum macaccess_entry_type type);
......@@ -115,6 +106,9 @@ struct ocelot_mirror *ocelot_mirror_get(struct ocelot *ocelot, int to,
struct netlink_ext_ack *extack);
void ocelot_mirror_put(struct ocelot *ocelot);
int ocelot_stats_init(struct ocelot *ocelot);
void ocelot_stats_deinit(struct ocelot *ocelot);
extern struct notifier_block ocelot_netdevice_nb;
extern struct notifier_block ocelot_switchdev_nb;
extern struct notifier_block ocelot_switchdev_blocking_nb;
......
......@@ -20,6 +20,13 @@
#define OCELOT_MAC_QUIRKS OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP
struct ocelot_dump_ctx {
struct net_device *dev;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
};
static bool ocelot_netdevice_dev_check(const struct net_device *dev);
static struct ocelot *devlink_port_to_ocelot(struct devlink_port *dlp)
......@@ -725,42 +732,8 @@ static void ocelot_get_stats64(struct net_device *dev,
struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot *ocelot = priv->port.ocelot;
int port = priv->port.index;
u64 *s;
spin_lock(&ocelot->stats_lock);
s = &ocelot->stats[port * OCELOT_NUM_STATS];
/* Get Rx stats */
stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS];
stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] +
s[OCELOT_STAT_RX_FRAGMENTS] +
s[OCELOT_STAT_RX_JABBERS] +
s[OCELOT_STAT_RX_LONGS] +
s[OCELOT_STAT_RX_64] +
s[OCELOT_STAT_RX_65_127] +
s[OCELOT_STAT_RX_128_255] +
s[OCELOT_STAT_RX_256_511] +
s[OCELOT_STAT_RX_512_1023] +
s[OCELOT_STAT_RX_1024_1526] +
s[OCELOT_STAT_RX_1527_MAX];
stats->multicast = s[OCELOT_STAT_RX_MULTICAST];
stats->rx_dropped = dev->stats.rx_dropped;
/* Get Tx stats */
stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS];
stats->tx_packets = s[OCELOT_STAT_TX_64] +
s[OCELOT_STAT_TX_65_127] +
s[OCELOT_STAT_TX_128_255] +
s[OCELOT_STAT_TX_256_511] +
s[OCELOT_STAT_TX_512_1023] +
s[OCELOT_STAT_TX_1024_1526] +
s[OCELOT_STAT_TX_1527_MAX];
stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] +
s[OCELOT_STAT_TX_AGED];
stats->collisions = s[OCELOT_STAT_TX_COLLISION];
spin_unlock(&ocelot->stats_lock);
return ocelot_port_get_stats64(ocelot, port, stats);
}
static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
......@@ -790,6 +763,49 @@ static int ocelot_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
return ocelot_fdb_del(ocelot, port, addr, vid, ocelot_port->bridge);
}
static int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
bool is_static, void *data)
{
struct ocelot_dump_ctx *dump = data;
u32 portid = NETLINK_CB(dump->cb->skb).portid;
u32 seq = dump->cb->nlh->nlmsg_seq;
struct nlmsghdr *nlh;
struct ndmsg *ndm;
if (dump->idx < dump->cb->args[2])
goto skip;
nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
sizeof(*ndm), NLM_F_MULTI);
if (!nlh)
return -EMSGSIZE;
ndm = nlmsg_data(nlh);
ndm->ndm_family = AF_BRIDGE;
ndm->ndm_pad1 = 0;
ndm->ndm_pad2 = 0;
ndm->ndm_flags = NTF_SELF;
ndm->ndm_type = 0;
ndm->ndm_ifindex = dump->dev->ifindex;
ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
goto nla_put_failure;
if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
goto nla_put_failure;
nlmsg_end(dump->skb, nlh);
skip:
dump->idx++;
return 0;
nla_put_failure:
nlmsg_cancel(dump->skb, nlh);
return -EMSGSIZE;
}
static int ocelot_port_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
......
This diff is collapsed.
This diff is collapsed.
......@@ -97,378 +97,7 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = {
};
static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
[OCELOT_STAT_RX_OCTETS] = {
.name = "rx_octets",
.reg = SYS_COUNT_RX_OCTETS,
},
[OCELOT_STAT_RX_UNICAST] = {
.name = "rx_unicast",
.reg = SYS_COUNT_RX_UNICAST,
},
[OCELOT_STAT_RX_MULTICAST] = {
.name = "rx_multicast",
.reg = SYS_COUNT_RX_MULTICAST,
},
[OCELOT_STAT_RX_BROADCAST] = {
.name = "rx_broadcast",
.reg = SYS_COUNT_RX_BROADCAST,
},
[OCELOT_STAT_RX_SHORTS] = {
.name = "rx_shorts",
.reg = SYS_COUNT_RX_SHORTS,
},
[OCELOT_STAT_RX_FRAGMENTS] = {
.name = "rx_fragments",
.reg = SYS_COUNT_RX_FRAGMENTS,
},
[OCELOT_STAT_RX_JABBERS] = {
.name = "rx_jabbers",
.reg = SYS_COUNT_RX_JABBERS,
},
[OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
.name = "rx_crc_align_errs",
.reg = SYS_COUNT_RX_CRC_ALIGN_ERRS,
},
[OCELOT_STAT_RX_SYM_ERRS] = {
.name = "rx_sym_errs",
.reg = SYS_COUNT_RX_SYM_ERRS,
},
[OCELOT_STAT_RX_64] = {
.name = "rx_frames_below_65_octets",
.reg = SYS_COUNT_RX_64,
},
[OCELOT_STAT_RX_65_127] = {
.name = "rx_frames_65_to_127_octets",
.reg = SYS_COUNT_RX_65_127,
},
[OCELOT_STAT_RX_128_255] = {
.name = "rx_frames_128_to_255_octets",
.reg = SYS_COUNT_RX_128_255,
},
[OCELOT_STAT_RX_256_511] = {
.name = "rx_frames_256_to_511_octets",
.reg = SYS_COUNT_RX_256_511,
},
[OCELOT_STAT_RX_512_1023] = {
.name = "rx_frames_512_to_1023_octets",
.reg = SYS_COUNT_RX_512_1023,
},
[OCELOT_STAT_RX_1024_1526] = {
.name = "rx_frames_1024_to_1526_octets",
.reg = SYS_COUNT_RX_1024_1526,
},
[OCELOT_STAT_RX_1527_MAX] = {
.name = "rx_frames_over_1526_octets",
.reg = SYS_COUNT_RX_1527_MAX,
},
[OCELOT_STAT_RX_PAUSE] = {
.name = "rx_pause",
.reg = SYS_COUNT_RX_PAUSE,
},
[OCELOT_STAT_RX_CONTROL] = {
.name = "rx_control",
.reg = SYS_COUNT_RX_CONTROL,
},
[OCELOT_STAT_RX_LONGS] = {
.name = "rx_longs",
.reg = SYS_COUNT_RX_LONGS,
},
[OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
.name = "rx_classified_drops",
.reg = SYS_COUNT_RX_CLASSIFIED_DROPS,
},
[OCELOT_STAT_RX_RED_PRIO_0] = {
.name = "rx_red_prio_0",
.reg = SYS_COUNT_RX_RED_PRIO_0,
},
[OCELOT_STAT_RX_RED_PRIO_1] = {
.name = "rx_red_prio_1",
.reg = SYS_COUNT_RX_RED_PRIO_1,
},
[OCELOT_STAT_RX_RED_PRIO_2] = {
.name = "rx_red_prio_2",
.reg = SYS_COUNT_RX_RED_PRIO_2,
},
[OCELOT_STAT_RX_RED_PRIO_3] = {
.name = "rx_red_prio_3",
.reg = SYS_COUNT_RX_RED_PRIO_3,
},
[OCELOT_STAT_RX_RED_PRIO_4] = {
.name = "rx_red_prio_4",
.reg = SYS_COUNT_RX_RED_PRIO_4,
},
[OCELOT_STAT_RX_RED_PRIO_5] = {
.name = "rx_red_prio_5",
.reg = SYS_COUNT_RX_RED_PRIO_5,
},
[OCELOT_STAT_RX_RED_PRIO_6] = {
.name = "rx_red_prio_6",
.reg = SYS_COUNT_RX_RED_PRIO_6,
},
[OCELOT_STAT_RX_RED_PRIO_7] = {
.name = "rx_red_prio_7",
.reg = SYS_COUNT_RX_RED_PRIO_7,
},
[OCELOT_STAT_RX_YELLOW_PRIO_0] = {
.name = "rx_yellow_prio_0",
.reg = SYS_COUNT_RX_YELLOW_PRIO_0,
},
[OCELOT_STAT_RX_YELLOW_PRIO_1] = {
.name = "rx_yellow_prio_1",
.reg = SYS_COUNT_RX_YELLOW_PRIO_1,
},
[OCELOT_STAT_RX_YELLOW_PRIO_2] = {
.name = "rx_yellow_prio_2",
.reg = SYS_COUNT_RX_YELLOW_PRIO_2,
},
[OCELOT_STAT_RX_YELLOW_PRIO_3] = {
.name = "rx_yellow_prio_3",
.reg = SYS_COUNT_RX_YELLOW_PRIO_3,
},
[OCELOT_STAT_RX_YELLOW_PRIO_4] = {
.name = "rx_yellow_prio_4",
.reg = SYS_COUNT_RX_YELLOW_PRIO_4,
},
[OCELOT_STAT_RX_YELLOW_PRIO_5] = {
.name = "rx_yellow_prio_5",
.reg = SYS_COUNT_RX_YELLOW_PRIO_5,
},
[OCELOT_STAT_RX_YELLOW_PRIO_6] = {
.name = "rx_yellow_prio_6",
.reg = SYS_COUNT_RX_YELLOW_PRIO_6,
},
[OCELOT_STAT_RX_YELLOW_PRIO_7] = {
.name = "rx_yellow_prio_7",
.reg = SYS_COUNT_RX_YELLOW_PRIO_7,
},
[OCELOT_STAT_RX_GREEN_PRIO_0] = {
.name = "rx_green_prio_0",
.reg = SYS_COUNT_RX_GREEN_PRIO_0,
},
[OCELOT_STAT_RX_GREEN_PRIO_1] = {
.name = "rx_green_prio_1",
.reg = SYS_COUNT_RX_GREEN_PRIO_1,
},
[OCELOT_STAT_RX_GREEN_PRIO_2] = {
.name = "rx_green_prio_2",
.reg = SYS_COUNT_RX_GREEN_PRIO_2,
},
[OCELOT_STAT_RX_GREEN_PRIO_3] = {
.name = "rx_green_prio_3",
.reg = SYS_COUNT_RX_GREEN_PRIO_3,
},
[OCELOT_STAT_RX_GREEN_PRIO_4] = {
.name = "rx_green_prio_4",
.reg = SYS_COUNT_RX_GREEN_PRIO_4,
},
[OCELOT_STAT_RX_GREEN_PRIO_5] = {
.name = "rx_green_prio_5",
.reg = SYS_COUNT_RX_GREEN_PRIO_5,
},
[OCELOT_STAT_RX_GREEN_PRIO_6] = {
.name = "rx_green_prio_6",
.reg = SYS_COUNT_RX_GREEN_PRIO_6,
},
[OCELOT_STAT_RX_GREEN_PRIO_7] = {
.name = "rx_green_prio_7",
.reg = SYS_COUNT_RX_GREEN_PRIO_7,
},
[OCELOT_STAT_TX_OCTETS] = {
.name = "tx_octets",
.reg = SYS_COUNT_TX_OCTETS,
},
[OCELOT_STAT_TX_UNICAST] = {
.name = "tx_unicast",
.reg = SYS_COUNT_TX_UNICAST,
},
[OCELOT_STAT_TX_MULTICAST] = {
.name = "tx_multicast",
.reg = SYS_COUNT_TX_MULTICAST,
},
[OCELOT_STAT_TX_BROADCAST] = {
.name = "tx_broadcast",
.reg = SYS_COUNT_TX_BROADCAST,
},
[OCELOT_STAT_TX_COLLISION] = {
.name = "tx_collision",
.reg = SYS_COUNT_TX_COLLISION,
},
[OCELOT_STAT_TX_DROPS] = {
.name = "tx_drops",
.reg = SYS_COUNT_TX_DROPS,
},
[OCELOT_STAT_TX_PAUSE] = {
.name = "tx_pause",
.reg = SYS_COUNT_TX_PAUSE,
},
[OCELOT_STAT_TX_64] = {
.name = "tx_frames_below_65_octets",
.reg = SYS_COUNT_TX_64,
},
[OCELOT_STAT_TX_65_127] = {
.name = "tx_frames_65_to_127_octets",
.reg = SYS_COUNT_TX_65_127,
},
[OCELOT_STAT_TX_128_255] = {
.name = "tx_frames_128_255_octets",
.reg = SYS_COUNT_TX_128_255,
},
[OCELOT_STAT_TX_256_511] = {
.name = "tx_frames_256_511_octets",
.reg = SYS_COUNT_TX_256_511,
},
[OCELOT_STAT_TX_512_1023] = {
.name = "tx_frames_512_1023_octets",
.reg = SYS_COUNT_TX_512_1023,
},
[OCELOT_STAT_TX_1024_1526] = {
.name = "tx_frames_1024_1526_octets",
.reg = SYS_COUNT_TX_1024_1526,
},
[OCELOT_STAT_TX_1527_MAX] = {
.name = "tx_frames_over_1526_octets",
.reg = SYS_COUNT_TX_1527_MAX,
},
[OCELOT_STAT_TX_YELLOW_PRIO_0] = {
.name = "tx_yellow_prio_0",
.reg = SYS_COUNT_TX_YELLOW_PRIO_0,
},
[OCELOT_STAT_TX_YELLOW_PRIO_1] = {
.name = "tx_yellow_prio_1",
.reg = SYS_COUNT_TX_YELLOW_PRIO_1,
},
[OCELOT_STAT_TX_YELLOW_PRIO_2] = {
.name = "tx_yellow_prio_2",
.reg = SYS_COUNT_TX_YELLOW_PRIO_2,
},
[OCELOT_STAT_TX_YELLOW_PRIO_3] = {
.name = "tx_yellow_prio_3",
.reg = SYS_COUNT_TX_YELLOW_PRIO_3,
},
[OCELOT_STAT_TX_YELLOW_PRIO_4] = {
.name = "tx_yellow_prio_4",
.reg = SYS_COUNT_TX_YELLOW_PRIO_4,
},
[OCELOT_STAT_TX_YELLOW_PRIO_5] = {
.name = "tx_yellow_prio_5",
.reg = SYS_COUNT_TX_YELLOW_PRIO_5,
},
[OCELOT_STAT_TX_YELLOW_PRIO_6] = {
.name = "tx_yellow_prio_6",
.reg = SYS_COUNT_TX_YELLOW_PRIO_6,
},
[OCELOT_STAT_TX_YELLOW_PRIO_7] = {
.name = "tx_yellow_prio_7",
.reg = SYS_COUNT_TX_YELLOW_PRIO_7,
},
[OCELOT_STAT_TX_GREEN_PRIO_0] = {
.name = "tx_green_prio_0",
.reg = SYS_COUNT_TX_GREEN_PRIO_0,
},
[OCELOT_STAT_TX_GREEN_PRIO_1] = {
.name = "tx_green_prio_1",
.reg = SYS_COUNT_TX_GREEN_PRIO_1,
},
[OCELOT_STAT_TX_GREEN_PRIO_2] = {
.name = "tx_green_prio_2",
.reg = SYS_COUNT_TX_GREEN_PRIO_2,
},
[OCELOT_STAT_TX_GREEN_PRIO_3] = {
.name = "tx_green_prio_3",
.reg = SYS_COUNT_TX_GREEN_PRIO_3,
},
[OCELOT_STAT_TX_GREEN_PRIO_4] = {
.name = "tx_green_prio_4",
.reg = SYS_COUNT_TX_GREEN_PRIO_4,
},
[OCELOT_STAT_TX_GREEN_PRIO_5] = {
.name = "tx_green_prio_5",
.reg = SYS_COUNT_TX_GREEN_PRIO_5,
},
[OCELOT_STAT_TX_GREEN_PRIO_6] = {
.name = "tx_green_prio_6",
.reg = SYS_COUNT_TX_GREEN_PRIO_6,
},
[OCELOT_STAT_TX_GREEN_PRIO_7] = {
.name = "tx_green_prio_7",
.reg = SYS_COUNT_TX_GREEN_PRIO_7,
},
[OCELOT_STAT_TX_AGED] = {
.name = "tx_aged",
.reg = SYS_COUNT_TX_AGING,
},
[OCELOT_STAT_DROP_LOCAL] = {
.name = "drop_local",
.reg = SYS_COUNT_DROP_LOCAL,
},
[OCELOT_STAT_DROP_TAIL] = {
.name = "drop_tail",
.reg = SYS_COUNT_DROP_TAIL,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
.name = "drop_yellow_prio_0",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_0,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
.name = "drop_yellow_prio_1",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_1,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
.name = "drop_yellow_prio_2",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_2,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
.name = "drop_yellow_prio_3",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_3,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
.name = "drop_yellow_prio_4",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_4,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
.name = "drop_yellow_prio_5",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_5,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
.name = "drop_yellow_prio_6",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_6,
},
[OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
.name = "drop_yellow_prio_7",
.reg = SYS_COUNT_DROP_YELLOW_PRIO_7,
},
[OCELOT_STAT_DROP_GREEN_PRIO_0] = {
.name = "drop_green_prio_0",
.reg = SYS_COUNT_DROP_GREEN_PRIO_0,
},
[OCELOT_STAT_DROP_GREEN_PRIO_1] = {
.name = "drop_green_prio_1",
.reg = SYS_COUNT_DROP_GREEN_PRIO_1,
},
[OCELOT_STAT_DROP_GREEN_PRIO_2] = {
.name = "drop_green_prio_2",
.reg = SYS_COUNT_DROP_GREEN_PRIO_2,
},
[OCELOT_STAT_DROP_GREEN_PRIO_3] = {
.name = "drop_green_prio_3",
.reg = SYS_COUNT_DROP_GREEN_PRIO_3,
},
[OCELOT_STAT_DROP_GREEN_PRIO_4] = {
.name = "drop_green_prio_4",
.reg = SYS_COUNT_DROP_GREEN_PRIO_4,
},
[OCELOT_STAT_DROP_GREEN_PRIO_5] = {
.name = "drop_green_prio_5",
.reg = SYS_COUNT_DROP_GREEN_PRIO_5,
},
[OCELOT_STAT_DROP_GREEN_PRIO_6] = {
.name = "drop_green_prio_6",
.reg = SYS_COUNT_DROP_GREEN_PRIO_6,
},
[OCELOT_STAT_DROP_GREEN_PRIO_7] = {
.name = "drop_green_prio_7",
.reg = SYS_COUNT_DROP_GREEN_PRIO_7,
},
OCELOT_COMMON_STATS,
};
static void ocelot_pll5_init(struct ocelot *ocelot)
......
......@@ -242,7 +242,7 @@ const u32 vsc7514_sys_regmap[] = {
REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00016c),
REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000170),
REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000174),
REG(SYS_COUNT_TX_AGING, 0x000178),
REG(SYS_COUNT_TX_AGED, 0x000178),
REG(SYS_COUNT_DROP_LOCAL, 0x000200),
REG(SYS_COUNT_DROP_TAIL, 0x000204),
REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000208),
......@@ -283,7 +283,6 @@ const u32 vsc7514_sys_regmap[] = {
REG(SYS_MMGT_FAST, 0x0006a0),
REG(SYS_EVENTS_DIF, 0x0006a4),
REG(SYS_EVENTS_CORE, 0x0006b4),
REG(SYS_CNT, 0x000000),
REG(SYS_PTP_STATUS, 0x0006b8),
REG(SYS_PTP_TXSTAMP, 0x0006bc),
REG(SYS_PTP_NXT, 0x0006c0),
......
......@@ -392,7 +392,7 @@ enum ocelot_reg {
SYS_COUNT_TX_GREEN_PRIO_5,
SYS_COUNT_TX_GREEN_PRIO_6,
SYS_COUNT_TX_GREEN_PRIO_7,
SYS_COUNT_TX_AGING,
SYS_COUNT_TX_AGED,
SYS_COUNT_DROP_LOCAL,
SYS_COUNT_DROP_TAIL,
SYS_COUNT_DROP_YELLOW_PRIO_0,
......@@ -411,6 +411,10 @@ enum ocelot_reg {
SYS_COUNT_DROP_GREEN_PRIO_5,
SYS_COUNT_DROP_GREEN_PRIO_6,
SYS_COUNT_DROP_GREEN_PRIO_7,
SYS_COUNT_SF_MATCHING_FRAMES,
SYS_COUNT_SF_NOT_PASSING_FRAMES,
SYS_COUNT_SF_NOT_PASSING_SDU,
SYS_COUNT_SF_RED_FRAMES,
SYS_RESET_CFG,
SYS_SR_ETYPE_CFG,
SYS_VLAN_ETYPE_CFG,
......@@ -433,7 +437,6 @@ enum ocelot_reg {
SYS_MMGT_FAST,
SYS_EVENTS_DIF,
SYS_EVENTS_CORE,
SYS_CNT,
SYS_PTP_STATUS,
SYS_PTP_TXSTAMP,
SYS_PTP_NXT,
......@@ -695,6 +698,112 @@ struct ocelot_stat_layout {
char name[ETH_GSTRING_LEN];
};
/* 32-bit counter checked for wraparound by ocelot_port_update_stats()
* and copied to ocelot->stats.
*/
#define OCELOT_STAT(kind) \
[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind }
/* Same as above, except also exported to ethtool -S. Standard counters should
* only be exposed to more specific interfaces rather than by their string name.
*/
#define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \
[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name }
#define OCELOT_COMMON_STATS \
OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \
OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \
OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \
OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \
OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \
OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \
OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \
OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \
OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \
OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \
OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \
OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \
OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \
OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \
OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \
OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \
OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \
OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \
OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \
OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \
OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \
OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \
OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \
OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \
OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \
OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \
OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \
OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \
OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \
OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \
OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \
OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \
OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \
OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \
OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \
OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \
OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \
OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \
OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \
OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \
OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \
OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \
OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \
OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7")
struct ocelot_stats_region {
struct list_head node;
u32 base;
......@@ -726,6 +835,7 @@ struct ocelot_ops {
struct flow_stats *stats);
void (*cut_through_fwd)(struct ocelot *ocelot);
void (*tas_clock_adjust)(struct ocelot *ocelot);
void (*update_stats)(struct ocelot *ocelot);
};
struct ocelot_vcap_policer {
......@@ -763,6 +873,8 @@ struct ocelot_psfp_list {
struct list_head stream_list;
struct list_head sfi_list;
struct list_head sgi_list;
/* Serialize access to the lists */
struct mutex lock;
};
enum ocelot_sb {
......@@ -898,12 +1010,15 @@ struct ocelot {
struct ocelot_psfp_list psfp;
/* Workqueue to check statistics for overflow with its lock */
spinlock_t stats_lock;
u64 *stats;
/* Workqueue to check statistics for overflow */
struct delayed_work stats_work;
struct workqueue_struct *stats_queue;
/* Lock for serializing access to the statistics array */
spinlock_t stats_lock;
u64 *stats;
/* Lock for serializing indirect access to STAT_VIEW registers */
struct mutex stat_view_lock;
/* Lock for serializing access to the MAC table */
struct mutex mact_lock;
/* Lock for serializing forwarding domain changes */
......@@ -1034,6 +1149,19 @@ u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port);
void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data);
void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data);
int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset);
void ocelot_port_get_stats64(struct ocelot *ocelot, int port,
struct rtnl_link_stats64 *stats);
void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,
struct ethtool_pause_stats *pause_stats);
void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port,
struct ethtool_eth_mac_stats *mac_stats);
void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port,
struct ethtool_eth_phy_stats *phy_stats);
int ocelot_get_ts_info(struct ocelot *ocelot, int port,
struct ethtool_ts_info *info);
void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment