mirror of https://gitee.com/openkylin/linux.git
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: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
badd62c249
commit
f4ae9c0840
|
@ -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,
|
||||
u32 stringset, uint8_t *data)
|
||||
{
|
||||
int cnt = b53_get_sset_count(ds, port, stringset);
|
||||
|
||||
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,
|
||||
uint64_t *data)
|
||||
{
|
||||
int cnt = b53_get_sset_count(ds, port, ETH_SS_STATS);
|
||||
|
||||
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,
|
||||
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 = {
|
||||
|
|
|
@ -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);
|
||||
void bcm_sf2_cfp_exit(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 */
|
||||
|
|
|
@ -1201,3 +1201,91 @@ int bcm_sf2_cfp_resume(struct dsa_switch *ds)
|
|||
|
||||
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 {
|
|||
#define CORE_RATE_METER6 0x281e0
|
||||
#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 CFP_EN_MAP_MASK 0x1ff
|
||||
|
||||
|
|
Loading…
Reference in New Issue