Commit f4ae9c08 authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

net: dsa: bcm_sf2: Add support for CFP statistics

Return CFP policer statistics (Green, Yellow or Red) as part of the
standard ethtool statistics. This helps debug when CFP rules may not be
hit (0 counter).
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent badd62c2
...@@ -897,19 +897,33 @@ static const struct b53_io_ops bcm_sf2_io_ops = { ...@@ -897,19 +897,33 @@ static const struct b53_io_ops bcm_sf2_io_ops = {
static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port, static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *data) u32 stringset, uint8_t *data)
{ {
int cnt = b53_get_sset_count(ds, port, stringset);
b53_get_strings(ds, port, stringset, data); b53_get_strings(ds, port, stringset, data);
bcm_sf2_cfp_get_strings(ds, port, stringset,
data + cnt * ETH_GSTRING_LEN);
} }
static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port, static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data) uint64_t *data)
{ {
int cnt = b53_get_sset_count(ds, port, ETH_SS_STATS);
b53_get_ethtool_stats(ds, port, data); b53_get_ethtool_stats(ds, port, data);
bcm_sf2_cfp_get_ethtool_stats(ds, port, data + cnt);
} }
static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds, int port, static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds, int port,
int sset) int sset)
{ {
return b53_get_sset_count(ds, port, sset); int cnt = b53_get_sset_count(ds, port, sset);
if (cnt < 0)
return cnt;
cnt += bcm_sf2_cfp_get_sset_count(ds, port, sset);
return cnt;
} }
static const struct dsa_switch_ops bcm_sf2_ops = { static const struct dsa_switch_ops bcm_sf2_ops = {
......
...@@ -213,5 +213,10 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, ...@@ -213,5 +213,10 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv); int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv);
void bcm_sf2_cfp_exit(struct dsa_switch *ds); void bcm_sf2_cfp_exit(struct dsa_switch *ds);
int bcm_sf2_cfp_resume(struct dsa_switch *ds); int bcm_sf2_cfp_resume(struct dsa_switch *ds);
void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *data);
void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data);
int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset);
#endif /* __BCM_SF2_H */ #endif /* __BCM_SF2_H */
...@@ -1201,3 +1201,91 @@ int bcm_sf2_cfp_resume(struct dsa_switch *ds) ...@@ -1201,3 +1201,91 @@ int bcm_sf2_cfp_resume(struct dsa_switch *ds)
return ret; return ret;
} }
static const struct bcm_sf2_cfp_stat {
unsigned int offset;
unsigned int ram_loc;
const char *name;
} bcm_sf2_cfp_stats[] = {
{
.offset = CORE_STAT_GREEN_CNTR,
.ram_loc = GREEN_STAT_RAM,
.name = "Green"
},
{
.offset = CORE_STAT_YELLOW_CNTR,
.ram_loc = YELLOW_STAT_RAM,
.name = "Yellow"
},
{
.offset = CORE_STAT_RED_CNTR,
.ram_loc = RED_STAT_RAM,
.name = "Red"
},
};
void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *data)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
char buf[ETH_GSTRING_LEN];
unsigned int i, j, iter;
if (stringset != ETH_SS_STATS)
return;
for (i = 1; i < priv->num_cfp_rules; i++) {
for (j = 0; j < s; j++) {
snprintf(buf, sizeof(buf),
"CFP%03d_%sCntr",
i, bcm_sf2_cfp_stats[j].name);
iter = (i - 1) * s + j;
strlcpy(data + iter * ETH_GSTRING_LEN,
buf, ETH_GSTRING_LEN);
}
}
}
void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
const struct bcm_sf2_cfp_stat *stat;
unsigned int i, j, iter;
struct cfp_rule *rule;
int ret;
mutex_lock(&priv->cfp.lock);
for (i = 1; i < priv->num_cfp_rules; i++) {
rule = bcm_sf2_cfp_rule_find(priv, port, i);
if (!rule)
continue;
for (j = 0; j < s; j++) {
stat = &bcm_sf2_cfp_stats[j];
bcm_sf2_cfp_rule_addr_set(priv, i);
ret = bcm_sf2_cfp_op(priv, stat->ram_loc | OP_SEL_READ);
if (ret)
continue;
iter = (i - 1) * s + j;
data[iter] = core_readl(priv, stat->offset);
}
}
mutex_unlock(&priv->cfp.lock);
}
int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
if (sset != ETH_SS_STATS)
return 0;
/* 3 counters per CFP rules */
return (priv->num_cfp_rules - 1) * ARRAY_SIZE(bcm_sf2_cfp_stats);
}
...@@ -400,6 +400,10 @@ enum bcm_sf2_reg_offs { ...@@ -400,6 +400,10 @@ enum bcm_sf2_reg_offs {
#define CORE_RATE_METER6 0x281e0 #define CORE_RATE_METER6 0x281e0
#define CIR_REF_CNT_MASK 0x7ffff #define CIR_REF_CNT_MASK 0x7ffff
#define CORE_STAT_GREEN_CNTR 0x28200
#define CORE_STAT_YELLOW_CNTR 0x28210
#define CORE_STAT_RED_CNTR 0x28220
#define CORE_CFP_CTL_REG 0x28400 #define CORE_CFP_CTL_REG 0x28400
#define CFP_EN_MAP_MASK 0x1ff #define CFP_EN_MAP_MASK 0x1ff
......
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