Commit 5b6a0729 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'fixes-for-ocelot-driver-statistics'

Vladimir Oltean says:

====================
Fixes for Ocelot driver statistics

This series contains bug fixes for the ocelot drivers (both switchdev
and DSA). Some concern the counters exposed to ethtool -S, and others to
the counters exposed to ifconfig. I'm aware that the changes are fairly
large, but I wanted to prioritize on a proper approach to addressing the
issues rather than a quick hack.

Some of the noticed problems:
- bad register offsets for some counters
- unhandled concurrency leading to corrupted counters
- unhandled 32-bit wraparound of ifconfig counters

The issues on the ocelot switchdev driver were noticed through code
inspection, I do not have the hardware to test.

This patch set necessarily converts ocelot->stats_lock from a mutex to a
spinlock. I know this affects Colin Foster's development with the SPI
controlled VSC7512. I have other changes prepared for net-next that
convert this back into a mutex (along with other changes in this area).
====================

Link: https://lore.kernel.org/r/20220816135352.1431497-1-vladimir.oltean@nxp.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 211987f3 e780e319
This diff is collapsed.
This diff is collapsed.
...@@ -1860,16 +1860,20 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) ...@@ -1860,16 +1860,20 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
if (sset != ETH_SS_STATS) if (sset != ETH_SS_STATS)
return; return;
for (i = 0; i < ocelot->num_stats; i++) for (i = 0; i < OCELOT_NUM_STATS; i++) {
if (ocelot->stats_layout[i].name[0] == '\0')
continue;
memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name, memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
}
} }
EXPORT_SYMBOL(ocelot_get_strings); EXPORT_SYMBOL(ocelot_get_strings);
/* Caller must hold &ocelot->stats_lock */ /* Caller must hold &ocelot->stats_lock */
static int ocelot_port_update_stats(struct ocelot *ocelot, int port) static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
{ {
unsigned int idx = port * ocelot->num_stats; unsigned int idx = port * OCELOT_NUM_STATS;
struct ocelot_stats_region *region; struct ocelot_stats_region *region;
int err, j; int err, j;
...@@ -1877,9 +1881,8 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port) ...@@ -1877,9 +1881,8 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG);
list_for_each_entry(region, &ocelot->stats_regions, node) { list_for_each_entry(region, &ocelot->stats_regions, node) {
err = ocelot_bulk_read_rix(ocelot, SYS_COUNT_RX_OCTETS, err = ocelot_bulk_read(ocelot, region->base, region->buf,
region->offset, region->buf, region->count);
region->count);
if (err) if (err)
return err; return err;
...@@ -1906,13 +1909,13 @@ static void ocelot_check_stats_work(struct work_struct *work) ...@@ -1906,13 +1909,13 @@ static void ocelot_check_stats_work(struct work_struct *work)
stats_work); stats_work);
int i, err; int i, err;
mutex_lock(&ocelot->stats_lock); spin_lock(&ocelot->stats_lock);
for (i = 0; i < ocelot->num_phys_ports; i++) { for (i = 0; i < ocelot->num_phys_ports; i++) {
err = ocelot_port_update_stats(ocelot, i); err = ocelot_port_update_stats(ocelot, i);
if (err) if (err)
break; break;
} }
mutex_unlock(&ocelot->stats_lock); spin_unlock(&ocelot->stats_lock);
if (err) if (err)
dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err);
...@@ -1925,16 +1928,22 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) ...@@ -1925,16 +1928,22 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
{ {
int i, err; int i, err;
mutex_lock(&ocelot->stats_lock); spin_lock(&ocelot->stats_lock);
/* check and update now */ /* check and update now */
err = ocelot_port_update_stats(ocelot, port); err = ocelot_port_update_stats(ocelot, port);
/* Copy all counters */ /* Copy all supported counters */
for (i = 0; i < ocelot->num_stats; i++) for (i = 0; i < OCELOT_NUM_STATS; i++) {
*data++ = ocelot->stats[port * ocelot->num_stats + i]; int index = port * OCELOT_NUM_STATS + i;
if (ocelot->stats_layout[i].name[0] == '\0')
continue;
*data++ = ocelot->stats[index];
}
mutex_unlock(&ocelot->stats_lock); spin_unlock(&ocelot->stats_lock);
if (err) if (err)
dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err);
...@@ -1943,10 +1952,16 @@ EXPORT_SYMBOL(ocelot_get_ethtool_stats); ...@@ -1943,10 +1952,16 @@ EXPORT_SYMBOL(ocelot_get_ethtool_stats);
int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset) int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
{ {
int i, num_stats = 0;
if (sset != ETH_SS_STATS) if (sset != ETH_SS_STATS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return ocelot->num_stats; for (i = 0; i < OCELOT_NUM_STATS; i++)
if (ocelot->stats_layout[i].name[0] != '\0')
num_stats++;
return num_stats;
} }
EXPORT_SYMBOL(ocelot_get_sset_count); EXPORT_SYMBOL(ocelot_get_sset_count);
...@@ -1958,8 +1973,11 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) ...@@ -1958,8 +1973,11 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
INIT_LIST_HEAD(&ocelot->stats_regions); INIT_LIST_HEAD(&ocelot->stats_regions);
for (i = 0; i < ocelot->num_stats; i++) { for (i = 0; i < OCELOT_NUM_STATS; i++) {
if (region && ocelot->stats_layout[i].offset == last + 1) { if (ocelot->stats_layout[i].name[0] == '\0')
continue;
if (region && ocelot->stats_layout[i].reg == last + 4) {
region->count++; region->count++;
} else { } else {
region = devm_kzalloc(ocelot->dev, sizeof(*region), region = devm_kzalloc(ocelot->dev, sizeof(*region),
...@@ -1967,12 +1985,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) ...@@ -1967,12 +1985,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
if (!region) if (!region)
return -ENOMEM; return -ENOMEM;
region->offset = ocelot->stats_layout[i].offset; region->base = ocelot->stats_layout[i].reg;
region->count = 1; region->count = 1;
list_add_tail(&region->node, &ocelot->stats_regions); list_add_tail(&region->node, &ocelot->stats_regions);
} }
last = ocelot->stats_layout[i].offset; last = ocelot->stats_layout[i].reg;
} }
list_for_each_entry(region, &ocelot->stats_regions, node) { list_for_each_entry(region, &ocelot->stats_regions, node) {
...@@ -3340,7 +3358,6 @@ static void ocelot_detect_features(struct ocelot *ocelot) ...@@ -3340,7 +3358,6 @@ static void ocelot_detect_features(struct ocelot *ocelot)
int ocelot_init(struct ocelot *ocelot) int ocelot_init(struct ocelot *ocelot)
{ {
const struct ocelot_stat_layout *stat;
char queue_name[32]; char queue_name[32];
int i, ret; int i, ret;
u32 port; u32 port;
...@@ -3353,17 +3370,13 @@ int ocelot_init(struct ocelot *ocelot) ...@@ -3353,17 +3370,13 @@ int ocelot_init(struct ocelot *ocelot)
} }
} }
ocelot->num_stats = 0;
for_each_stat(ocelot, stat)
ocelot->num_stats++;
ocelot->stats = devm_kcalloc(ocelot->dev, ocelot->stats = devm_kcalloc(ocelot->dev,
ocelot->num_phys_ports * ocelot->num_stats, ocelot->num_phys_ports * OCELOT_NUM_STATS,
sizeof(u64), GFP_KERNEL); sizeof(u64), GFP_KERNEL);
if (!ocelot->stats) if (!ocelot->stats)
return -ENOMEM; return -ENOMEM;
mutex_init(&ocelot->stats_lock); spin_lock_init(&ocelot->stats_lock);
mutex_init(&ocelot->ptp_lock); mutex_init(&ocelot->ptp_lock);
mutex_init(&ocelot->mact_lock); mutex_init(&ocelot->mact_lock);
mutex_init(&ocelot->fwd_domain_lock); mutex_init(&ocelot->fwd_domain_lock);
...@@ -3511,7 +3524,6 @@ void ocelot_deinit(struct ocelot *ocelot) ...@@ -3511,7 +3524,6 @@ void ocelot_deinit(struct ocelot *ocelot)
cancel_delayed_work(&ocelot->stats_work); cancel_delayed_work(&ocelot->stats_work);
destroy_workqueue(ocelot->stats_queue); destroy_workqueue(ocelot->stats_queue);
destroy_workqueue(ocelot->owq); destroy_workqueue(ocelot->owq);
mutex_destroy(&ocelot->stats_lock);
} }
EXPORT_SYMBOL(ocelot_deinit); EXPORT_SYMBOL(ocelot_deinit);
......
...@@ -725,37 +725,42 @@ static void ocelot_get_stats64(struct net_device *dev, ...@@ -725,37 +725,42 @@ static void ocelot_get_stats64(struct net_device *dev,
struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot *ocelot = priv->port.ocelot; struct ocelot *ocelot = priv->port.ocelot;
int port = priv->port.index; int port = priv->port.index;
u64 *s;
/* Configure the port to read the stats from */ spin_lock(&ocelot->stats_lock);
ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port),
SYS_STAT_CFG); s = &ocelot->stats[port * OCELOT_NUM_STATS];
/* Get Rx stats */ /* Get Rx stats */
stats->rx_bytes = ocelot_read(ocelot, SYS_COUNT_RX_OCTETS); stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS];
stats->rx_packets = ocelot_read(ocelot, SYS_COUNT_RX_SHORTS) + stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] +
ocelot_read(ocelot, SYS_COUNT_RX_FRAGMENTS) + s[OCELOT_STAT_RX_FRAGMENTS] +
ocelot_read(ocelot, SYS_COUNT_RX_JABBERS) + s[OCELOT_STAT_RX_JABBERS] +
ocelot_read(ocelot, SYS_COUNT_RX_LONGS) + s[OCELOT_STAT_RX_LONGS] +
ocelot_read(ocelot, SYS_COUNT_RX_64) + s[OCELOT_STAT_RX_64] +
ocelot_read(ocelot, SYS_COUNT_RX_65_127) + s[OCELOT_STAT_RX_65_127] +
ocelot_read(ocelot, SYS_COUNT_RX_128_255) + s[OCELOT_STAT_RX_128_255] +
ocelot_read(ocelot, SYS_COUNT_RX_256_1023) + s[OCELOT_STAT_RX_256_511] +
ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) + s[OCELOT_STAT_RX_512_1023] +
ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX); s[OCELOT_STAT_RX_1024_1526] +
stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST); s[OCELOT_STAT_RX_1527_MAX];
stats->multicast = s[OCELOT_STAT_RX_MULTICAST];
stats->rx_dropped = dev->stats.rx_dropped; stats->rx_dropped = dev->stats.rx_dropped;
/* Get Tx stats */ /* Get Tx stats */
stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS); stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS];
stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) + stats->tx_packets = s[OCELOT_STAT_TX_64] +
ocelot_read(ocelot, SYS_COUNT_TX_65_127) + s[OCELOT_STAT_TX_65_127] +
ocelot_read(ocelot, SYS_COUNT_TX_128_511) + s[OCELOT_STAT_TX_128_255] +
ocelot_read(ocelot, SYS_COUNT_TX_512_1023) + s[OCELOT_STAT_TX_256_511] +
ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) + s[OCELOT_STAT_TX_512_1023] +
ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX); s[OCELOT_STAT_TX_1024_1526] +
stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) + s[OCELOT_STAT_TX_1527_MAX];
ocelot_read(ocelot, SYS_COUNT_TX_AGING); stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] +
stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION); s[OCELOT_STAT_TX_AGED];
stats->collisions = s[OCELOT_STAT_TX_COLLISION];
spin_unlock(&ocelot->stats_lock);
} }
static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
......
This diff is collapsed.
...@@ -180,13 +180,38 @@ const u32 vsc7514_sys_regmap[] = { ...@@ -180,13 +180,38 @@ const u32 vsc7514_sys_regmap[] = {
REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_64, 0x000024),
REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_65_127, 0x000028),
REG(SYS_COUNT_RX_128_255, 0x00002c), REG(SYS_COUNT_RX_128_255, 0x00002c),
REG(SYS_COUNT_RX_256_1023, 0x000030), REG(SYS_COUNT_RX_256_511, 0x000030),
REG(SYS_COUNT_RX_1024_1526, 0x000034), REG(SYS_COUNT_RX_512_1023, 0x000034),
REG(SYS_COUNT_RX_1527_MAX, 0x000038), REG(SYS_COUNT_RX_1024_1526, 0x000038),
REG(SYS_COUNT_RX_PAUSE, 0x00003c), REG(SYS_COUNT_RX_1527_MAX, 0x00003c),
REG(SYS_COUNT_RX_CONTROL, 0x000040), REG(SYS_COUNT_RX_PAUSE, 0x000040),
REG(SYS_COUNT_RX_LONGS, 0x000044), REG(SYS_COUNT_RX_CONTROL, 0x000044),
REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x000048), REG(SYS_COUNT_RX_LONGS, 0x000048),
REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c),
REG(SYS_COUNT_RX_RED_PRIO_0, 0x000050),
REG(SYS_COUNT_RX_RED_PRIO_1, 0x000054),
REG(SYS_COUNT_RX_RED_PRIO_2, 0x000058),
REG(SYS_COUNT_RX_RED_PRIO_3, 0x00005c),
REG(SYS_COUNT_RX_RED_PRIO_4, 0x000060),
REG(SYS_COUNT_RX_RED_PRIO_5, 0x000064),
REG(SYS_COUNT_RX_RED_PRIO_6, 0x000068),
REG(SYS_COUNT_RX_RED_PRIO_7, 0x00006c),
REG(SYS_COUNT_RX_YELLOW_PRIO_0, 0x000070),
REG(SYS_COUNT_RX_YELLOW_PRIO_1, 0x000074),
REG(SYS_COUNT_RX_YELLOW_PRIO_2, 0x000078),
REG(SYS_COUNT_RX_YELLOW_PRIO_3, 0x00007c),
REG(SYS_COUNT_RX_YELLOW_PRIO_4, 0x000080),
REG(SYS_COUNT_RX_YELLOW_PRIO_5, 0x000084),
REG(SYS_COUNT_RX_YELLOW_PRIO_6, 0x000088),
REG(SYS_COUNT_RX_YELLOW_PRIO_7, 0x00008c),
REG(SYS_COUNT_RX_GREEN_PRIO_0, 0x000090),
REG(SYS_COUNT_RX_GREEN_PRIO_1, 0x000094),
REG(SYS_COUNT_RX_GREEN_PRIO_2, 0x000098),
REG(SYS_COUNT_RX_GREEN_PRIO_3, 0x00009c),
REG(SYS_COUNT_RX_GREEN_PRIO_4, 0x0000a0),
REG(SYS_COUNT_RX_GREEN_PRIO_5, 0x0000a4),
REG(SYS_COUNT_RX_GREEN_PRIO_6, 0x0000a8),
REG(SYS_COUNT_RX_GREEN_PRIO_7, 0x0000ac),
REG(SYS_COUNT_TX_OCTETS, 0x000100), REG(SYS_COUNT_TX_OCTETS, 0x000100),
REG(SYS_COUNT_TX_UNICAST, 0x000104), REG(SYS_COUNT_TX_UNICAST, 0x000104),
REG(SYS_COUNT_TX_MULTICAST, 0x000108), REG(SYS_COUNT_TX_MULTICAST, 0x000108),
...@@ -196,11 +221,46 @@ const u32 vsc7514_sys_regmap[] = { ...@@ -196,11 +221,46 @@ const u32 vsc7514_sys_regmap[] = {
REG(SYS_COUNT_TX_PAUSE, 0x000118), REG(SYS_COUNT_TX_PAUSE, 0x000118),
REG(SYS_COUNT_TX_64, 0x00011c), REG(SYS_COUNT_TX_64, 0x00011c),
REG(SYS_COUNT_TX_65_127, 0x000120), REG(SYS_COUNT_TX_65_127, 0x000120),
REG(SYS_COUNT_TX_128_511, 0x000124), REG(SYS_COUNT_TX_128_255, 0x000124),
REG(SYS_COUNT_TX_512_1023, 0x000128), REG(SYS_COUNT_TX_256_511, 0x000128),
REG(SYS_COUNT_TX_1024_1526, 0x00012c), REG(SYS_COUNT_TX_512_1023, 0x00012c),
REG(SYS_COUNT_TX_1527_MAX, 0x000130), REG(SYS_COUNT_TX_1024_1526, 0x000130),
REG(SYS_COUNT_TX_AGING, 0x000170), REG(SYS_COUNT_TX_1527_MAX, 0x000134),
REG(SYS_COUNT_TX_YELLOW_PRIO_0, 0x000138),
REG(SYS_COUNT_TX_YELLOW_PRIO_1, 0x00013c),
REG(SYS_COUNT_TX_YELLOW_PRIO_2, 0x000140),
REG(SYS_COUNT_TX_YELLOW_PRIO_3, 0x000144),
REG(SYS_COUNT_TX_YELLOW_PRIO_4, 0x000148),
REG(SYS_COUNT_TX_YELLOW_PRIO_5, 0x00014c),
REG(SYS_COUNT_TX_YELLOW_PRIO_6, 0x000150),
REG(SYS_COUNT_TX_YELLOW_PRIO_7, 0x000154),
REG(SYS_COUNT_TX_GREEN_PRIO_0, 0x000158),
REG(SYS_COUNT_TX_GREEN_PRIO_1, 0x00015c),
REG(SYS_COUNT_TX_GREEN_PRIO_2, 0x000160),
REG(SYS_COUNT_TX_GREEN_PRIO_3, 0x000164),
REG(SYS_COUNT_TX_GREEN_PRIO_4, 0x000168),
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_DROP_LOCAL, 0x000200),
REG(SYS_COUNT_DROP_TAIL, 0x000204),
REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000208),
REG(SYS_COUNT_DROP_YELLOW_PRIO_1, 0x00020c),
REG(SYS_COUNT_DROP_YELLOW_PRIO_2, 0x000210),
REG(SYS_COUNT_DROP_YELLOW_PRIO_3, 0x000214),
REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218),
REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c),
REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220),
REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000214),
REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000218),
REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00021c),
REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000220),
REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000224),
REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000228),
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00022c),
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000230),
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000234),
REG(SYS_RESET_CFG, 0x000508), REG(SYS_RESET_CFG, 0x000508),
REG(SYS_CMID, 0x00050c), REG(SYS_CMID, 0x00050c),
REG(SYS_VLAN_ETYPE_CFG, 0x000510), REG(SYS_VLAN_ETYPE_CFG, 0x000510),
......
...@@ -105,11 +105,6 @@ ...@@ -105,11 +105,6 @@
#define REG_RESERVED_ADDR 0xffffffff #define REG_RESERVED_ADDR 0xffffffff
#define REG_RESERVED(reg) REG(reg, REG_RESERVED_ADDR) #define REG_RESERVED(reg) REG(reg, REG_RESERVED_ADDR)
#define for_each_stat(ocelot, stat) \
for ((stat) = (ocelot)->stats_layout; \
((stat)->name[0] != '\0'); \
(stat)++)
enum ocelot_target { enum ocelot_target {
ANA = 1, ANA = 1,
QS, QS,
...@@ -335,13 +330,38 @@ enum ocelot_reg { ...@@ -335,13 +330,38 @@ enum ocelot_reg {
SYS_COUNT_RX_64, SYS_COUNT_RX_64,
SYS_COUNT_RX_65_127, SYS_COUNT_RX_65_127,
SYS_COUNT_RX_128_255, SYS_COUNT_RX_128_255,
SYS_COUNT_RX_256_1023, SYS_COUNT_RX_256_511,
SYS_COUNT_RX_512_1023,
SYS_COUNT_RX_1024_1526, SYS_COUNT_RX_1024_1526,
SYS_COUNT_RX_1527_MAX, SYS_COUNT_RX_1527_MAX,
SYS_COUNT_RX_PAUSE, SYS_COUNT_RX_PAUSE,
SYS_COUNT_RX_CONTROL, SYS_COUNT_RX_CONTROL,
SYS_COUNT_RX_LONGS, SYS_COUNT_RX_LONGS,
SYS_COUNT_RX_CLASSIFIED_DROPS, SYS_COUNT_RX_CLASSIFIED_DROPS,
SYS_COUNT_RX_RED_PRIO_0,
SYS_COUNT_RX_RED_PRIO_1,
SYS_COUNT_RX_RED_PRIO_2,
SYS_COUNT_RX_RED_PRIO_3,
SYS_COUNT_RX_RED_PRIO_4,
SYS_COUNT_RX_RED_PRIO_5,
SYS_COUNT_RX_RED_PRIO_6,
SYS_COUNT_RX_RED_PRIO_7,
SYS_COUNT_RX_YELLOW_PRIO_0,
SYS_COUNT_RX_YELLOW_PRIO_1,
SYS_COUNT_RX_YELLOW_PRIO_2,
SYS_COUNT_RX_YELLOW_PRIO_3,
SYS_COUNT_RX_YELLOW_PRIO_4,
SYS_COUNT_RX_YELLOW_PRIO_5,
SYS_COUNT_RX_YELLOW_PRIO_6,
SYS_COUNT_RX_YELLOW_PRIO_7,
SYS_COUNT_RX_GREEN_PRIO_0,
SYS_COUNT_RX_GREEN_PRIO_1,
SYS_COUNT_RX_GREEN_PRIO_2,
SYS_COUNT_RX_GREEN_PRIO_3,
SYS_COUNT_RX_GREEN_PRIO_4,
SYS_COUNT_RX_GREEN_PRIO_5,
SYS_COUNT_RX_GREEN_PRIO_6,
SYS_COUNT_RX_GREEN_PRIO_7,
SYS_COUNT_TX_OCTETS, SYS_COUNT_TX_OCTETS,
SYS_COUNT_TX_UNICAST, SYS_COUNT_TX_UNICAST,
SYS_COUNT_TX_MULTICAST, SYS_COUNT_TX_MULTICAST,
...@@ -351,11 +371,46 @@ enum ocelot_reg { ...@@ -351,11 +371,46 @@ enum ocelot_reg {
SYS_COUNT_TX_PAUSE, SYS_COUNT_TX_PAUSE,
SYS_COUNT_TX_64, SYS_COUNT_TX_64,
SYS_COUNT_TX_65_127, SYS_COUNT_TX_65_127,
SYS_COUNT_TX_128_511, SYS_COUNT_TX_128_255,
SYS_COUNT_TX_256_511,
SYS_COUNT_TX_512_1023, SYS_COUNT_TX_512_1023,
SYS_COUNT_TX_1024_1526, SYS_COUNT_TX_1024_1526,
SYS_COUNT_TX_1527_MAX, SYS_COUNT_TX_1527_MAX,
SYS_COUNT_TX_YELLOW_PRIO_0,
SYS_COUNT_TX_YELLOW_PRIO_1,
SYS_COUNT_TX_YELLOW_PRIO_2,
SYS_COUNT_TX_YELLOW_PRIO_3,
SYS_COUNT_TX_YELLOW_PRIO_4,
SYS_COUNT_TX_YELLOW_PRIO_5,
SYS_COUNT_TX_YELLOW_PRIO_6,
SYS_COUNT_TX_YELLOW_PRIO_7,
SYS_COUNT_TX_GREEN_PRIO_0,
SYS_COUNT_TX_GREEN_PRIO_1,
SYS_COUNT_TX_GREEN_PRIO_2,
SYS_COUNT_TX_GREEN_PRIO_3,
SYS_COUNT_TX_GREEN_PRIO_4,
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_AGING,
SYS_COUNT_DROP_LOCAL,
SYS_COUNT_DROP_TAIL,
SYS_COUNT_DROP_YELLOW_PRIO_0,
SYS_COUNT_DROP_YELLOW_PRIO_1,
SYS_COUNT_DROP_YELLOW_PRIO_2,
SYS_COUNT_DROP_YELLOW_PRIO_3,
SYS_COUNT_DROP_YELLOW_PRIO_4,
SYS_COUNT_DROP_YELLOW_PRIO_5,
SYS_COUNT_DROP_YELLOW_PRIO_6,
SYS_COUNT_DROP_YELLOW_PRIO_7,
SYS_COUNT_DROP_GREEN_PRIO_0,
SYS_COUNT_DROP_GREEN_PRIO_1,
SYS_COUNT_DROP_GREEN_PRIO_2,
SYS_COUNT_DROP_GREEN_PRIO_3,
SYS_COUNT_DROP_GREEN_PRIO_4,
SYS_COUNT_DROP_GREEN_PRIO_5,
SYS_COUNT_DROP_GREEN_PRIO_6,
SYS_COUNT_DROP_GREEN_PRIO_7,
SYS_RESET_CFG, SYS_RESET_CFG,
SYS_SR_ETYPE_CFG, SYS_SR_ETYPE_CFG,
SYS_VLAN_ETYPE_CFG, SYS_VLAN_ETYPE_CFG,
...@@ -538,16 +593,111 @@ enum ocelot_ptp_pins { ...@@ -538,16 +593,111 @@ enum ocelot_ptp_pins {
TOD_ACC_PIN TOD_ACC_PIN
}; };
enum ocelot_stat {
OCELOT_STAT_RX_OCTETS,
OCELOT_STAT_RX_UNICAST,
OCELOT_STAT_RX_MULTICAST,
OCELOT_STAT_RX_BROADCAST,
OCELOT_STAT_RX_SHORTS,
OCELOT_STAT_RX_FRAGMENTS,
OCELOT_STAT_RX_JABBERS,
OCELOT_STAT_RX_CRC_ALIGN_ERRS,
OCELOT_STAT_RX_SYM_ERRS,
OCELOT_STAT_RX_64,
OCELOT_STAT_RX_65_127,
OCELOT_STAT_RX_128_255,
OCELOT_STAT_RX_256_511,
OCELOT_STAT_RX_512_1023,
OCELOT_STAT_RX_1024_1526,
OCELOT_STAT_RX_1527_MAX,
OCELOT_STAT_RX_PAUSE,
OCELOT_STAT_RX_CONTROL,
OCELOT_STAT_RX_LONGS,
OCELOT_STAT_RX_CLASSIFIED_DROPS,
OCELOT_STAT_RX_RED_PRIO_0,
OCELOT_STAT_RX_RED_PRIO_1,
OCELOT_STAT_RX_RED_PRIO_2,
OCELOT_STAT_RX_RED_PRIO_3,
OCELOT_STAT_RX_RED_PRIO_4,
OCELOT_STAT_RX_RED_PRIO_5,
OCELOT_STAT_RX_RED_PRIO_6,
OCELOT_STAT_RX_RED_PRIO_7,
OCELOT_STAT_RX_YELLOW_PRIO_0,
OCELOT_STAT_RX_YELLOW_PRIO_1,
OCELOT_STAT_RX_YELLOW_PRIO_2,
OCELOT_STAT_RX_YELLOW_PRIO_3,
OCELOT_STAT_RX_YELLOW_PRIO_4,
OCELOT_STAT_RX_YELLOW_PRIO_5,
OCELOT_STAT_RX_YELLOW_PRIO_6,
OCELOT_STAT_RX_YELLOW_PRIO_7,
OCELOT_STAT_RX_GREEN_PRIO_0,
OCELOT_STAT_RX_GREEN_PRIO_1,
OCELOT_STAT_RX_GREEN_PRIO_2,
OCELOT_STAT_RX_GREEN_PRIO_3,
OCELOT_STAT_RX_GREEN_PRIO_4,
OCELOT_STAT_RX_GREEN_PRIO_5,
OCELOT_STAT_RX_GREEN_PRIO_6,
OCELOT_STAT_RX_GREEN_PRIO_7,
OCELOT_STAT_TX_OCTETS,
OCELOT_STAT_TX_UNICAST,
OCELOT_STAT_TX_MULTICAST,
OCELOT_STAT_TX_BROADCAST,
OCELOT_STAT_TX_COLLISION,
OCELOT_STAT_TX_DROPS,
OCELOT_STAT_TX_PAUSE,
OCELOT_STAT_TX_64,
OCELOT_STAT_TX_65_127,
OCELOT_STAT_TX_128_255,
OCELOT_STAT_TX_256_511,
OCELOT_STAT_TX_512_1023,
OCELOT_STAT_TX_1024_1526,
OCELOT_STAT_TX_1527_MAX,
OCELOT_STAT_TX_YELLOW_PRIO_0,
OCELOT_STAT_TX_YELLOW_PRIO_1,
OCELOT_STAT_TX_YELLOW_PRIO_2,
OCELOT_STAT_TX_YELLOW_PRIO_3,
OCELOT_STAT_TX_YELLOW_PRIO_4,
OCELOT_STAT_TX_YELLOW_PRIO_5,
OCELOT_STAT_TX_YELLOW_PRIO_6,
OCELOT_STAT_TX_YELLOW_PRIO_7,
OCELOT_STAT_TX_GREEN_PRIO_0,
OCELOT_STAT_TX_GREEN_PRIO_1,
OCELOT_STAT_TX_GREEN_PRIO_2,
OCELOT_STAT_TX_GREEN_PRIO_3,
OCELOT_STAT_TX_GREEN_PRIO_4,
OCELOT_STAT_TX_GREEN_PRIO_5,
OCELOT_STAT_TX_GREEN_PRIO_6,
OCELOT_STAT_TX_GREEN_PRIO_7,
OCELOT_STAT_TX_AGED,
OCELOT_STAT_DROP_LOCAL,
OCELOT_STAT_DROP_TAIL,
OCELOT_STAT_DROP_YELLOW_PRIO_0,
OCELOT_STAT_DROP_YELLOW_PRIO_1,
OCELOT_STAT_DROP_YELLOW_PRIO_2,
OCELOT_STAT_DROP_YELLOW_PRIO_3,
OCELOT_STAT_DROP_YELLOW_PRIO_4,
OCELOT_STAT_DROP_YELLOW_PRIO_5,
OCELOT_STAT_DROP_YELLOW_PRIO_6,
OCELOT_STAT_DROP_YELLOW_PRIO_7,
OCELOT_STAT_DROP_GREEN_PRIO_0,
OCELOT_STAT_DROP_GREEN_PRIO_1,
OCELOT_STAT_DROP_GREEN_PRIO_2,
OCELOT_STAT_DROP_GREEN_PRIO_3,
OCELOT_STAT_DROP_GREEN_PRIO_4,
OCELOT_STAT_DROP_GREEN_PRIO_5,
OCELOT_STAT_DROP_GREEN_PRIO_6,
OCELOT_STAT_DROP_GREEN_PRIO_7,
OCELOT_NUM_STATS,
};
struct ocelot_stat_layout { struct ocelot_stat_layout {
u32 offset; u32 reg;
char name[ETH_GSTRING_LEN]; char name[ETH_GSTRING_LEN];
}; };
#define OCELOT_STAT_END { .name = "" }
struct ocelot_stats_region { struct ocelot_stats_region {
struct list_head node; struct list_head node;
u32 offset; u32 base;
int count; int count;
u32 *buf; u32 *buf;
}; };
...@@ -707,7 +857,6 @@ struct ocelot { ...@@ -707,7 +857,6 @@ struct ocelot {
const u32 *const *map; const u32 *const *map;
const struct ocelot_stat_layout *stats_layout; const struct ocelot_stat_layout *stats_layout;
struct list_head stats_regions; struct list_head stats_regions;
unsigned int num_stats;
u32 pool_size[OCELOT_SB_NUM][OCELOT_SB_POOL_NUM]; u32 pool_size[OCELOT_SB_NUM][OCELOT_SB_POOL_NUM];
int packet_buffer_size; int packet_buffer_size;
...@@ -750,7 +899,7 @@ struct ocelot { ...@@ -750,7 +899,7 @@ struct ocelot {
struct ocelot_psfp_list psfp; struct ocelot_psfp_list psfp;
/* Workqueue to check statistics for overflow with its lock */ /* Workqueue to check statistics for overflow with its lock */
struct mutex stats_lock; spinlock_t stats_lock;
u64 *stats; u64 *stats;
struct delayed_work stats_work; struct delayed_work stats_work;
struct workqueue_struct *stats_queue; struct workqueue_struct *stats_queue;
...@@ -786,8 +935,8 @@ struct ocelot_policer { ...@@ -786,8 +935,8 @@ struct ocelot_policer {
u32 burst; /* bytes */ u32 burst; /* bytes */
}; };
#define ocelot_bulk_read_rix(ocelot, reg, ri, buf, count) \ #define ocelot_bulk_read(ocelot, reg, buf, count) \
__ocelot_bulk_read_ix(ocelot, reg, reg##_RSZ * (ri), buf, count) __ocelot_bulk_read_ix(ocelot, reg, 0, buf, count)
#define ocelot_read_ix(ocelot, reg, gi, ri) \ #define ocelot_read_ix(ocelot, reg, gi, ri) \
__ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
......
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