Commit 9ac41f3c authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by David S. Miller

net: mvneta: move refill_err and skb_alloc_err in per-cpu stats

mvneta_ethtool_update_stats routine is currently reporting
skb_alloc_error and refill_error only for the first rx queue.
Fix the issue moving skb_alloc_err and refill_err in
mvneta_pcpu_stats structure.
Moreover this patch will be used to introduce xdp statistics
to ethtool for the mvneta driver

Fixes: 17a96da6 ("net: mvneta: discriminate error cause for missed packet")
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1b18f20
...@@ -397,8 +397,15 @@ static const struct mvneta_statistic mvneta_statistics[] = { ...@@ -397,8 +397,15 @@ static const struct mvneta_statistic mvneta_statistics[] = {
{ ETHTOOL_STAT_REFILL_ERR, T_SW, "refill_errors", }, { ETHTOOL_STAT_REFILL_ERR, T_SW, "refill_errors", },
}; };
struct mvneta_ethtool_stats {
u64 skb_alloc_error;
u64 refill_error;
};
struct mvneta_pcpu_stats { struct mvneta_pcpu_stats {
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
struct mvneta_ethtool_stats es;
u64 rx_packets; u64 rx_packets;
u64 rx_bytes; u64 rx_bytes;
u64 rx_dropped; u64 rx_dropped;
...@@ -660,10 +667,6 @@ struct mvneta_rx_queue { ...@@ -660,10 +667,6 @@ struct mvneta_rx_queue {
/* pointer to uncomplete skb buffer */ /* pointer to uncomplete skb buffer */
struct sk_buff *skb; struct sk_buff *skb;
int left_size; int left_size;
/* error counters */
u32 skb_alloc_err;
u32 refill_err;
}; };
static enum cpuhp_state online_hpstate; static enum cpuhp_state online_hpstate;
...@@ -1969,9 +1972,15 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq) ...@@ -1969,9 +1972,15 @@ int mvneta_rx_refill_queue(struct mvneta_port *pp, struct mvneta_rx_queue *rxq)
rx_desc = rxq->descs + curr_desc; rx_desc = rxq->descs + curr_desc;
if (!(rx_desc->buf_phys_addr)) { if (!(rx_desc->buf_phys_addr)) {
if (mvneta_rx_refill(pp, rx_desc, rxq, GFP_ATOMIC)) { if (mvneta_rx_refill(pp, rx_desc, rxq, GFP_ATOMIC)) {
struct mvneta_pcpu_stats *stats;
pr_err("Can't refill queue %d. Done %d from %d\n", pr_err("Can't refill queue %d. Done %d from %d\n",
rxq->id, i, rxq->refill_num); rxq->id, i, rxq->refill_num);
rxq->refill_err++;
stats = this_cpu_ptr(pp->stats);
u64_stats_update_begin(&stats->syncp);
stats->es.refill_error++;
u64_stats_update_end(&stats->syncp);
break; break;
} }
} }
...@@ -2193,9 +2202,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp, ...@@ -2193,9 +2202,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats); struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
netdev_err(dev, "Can't allocate skb on queue %d\n", rxq->id); netdev_err(dev, "Can't allocate skb on queue %d\n", rxq->id);
rxq->skb_alloc_err++;
u64_stats_update_begin(&stats->syncp); u64_stats_update_begin(&stats->syncp);
stats->es.skb_alloc_error++;
stats->rx_dropped++; stats->rx_dropped++;
u64_stats_update_end(&stats->syncp); u64_stats_update_end(&stats->syncp);
...@@ -2423,8 +2432,15 @@ static int mvneta_rx_hwbm(struct napi_struct *napi, ...@@ -2423,8 +2432,15 @@ static int mvneta_rx_hwbm(struct napi_struct *napi,
/* Refill processing */ /* Refill processing */
err = hwbm_pool_refill(&bm_pool->hwbm_pool, GFP_ATOMIC); err = hwbm_pool_refill(&bm_pool->hwbm_pool, GFP_ATOMIC);
if (err) { if (err) {
struct mvneta_pcpu_stats *stats;
netdev_err(dev, "Linux processing - Can't refill\n"); netdev_err(dev, "Linux processing - Can't refill\n");
rxq->refill_err++;
stats = this_cpu_ptr(pp->stats);
u64_stats_update_begin(&stats->syncp);
stats->es.refill_error++;
u64_stats_update_end(&stats->syncp);
goto err_drop_frame_ret_pool; goto err_drop_frame_ret_pool;
} }
...@@ -4420,45 +4436,70 @@ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset, ...@@ -4420,45 +4436,70 @@ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
} }
} }
static void
mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
struct mvneta_ethtool_stats *es)
{
unsigned int start;
int cpu;
for_each_possible_cpu(cpu) {
struct mvneta_pcpu_stats *stats;
u64 skb_alloc_error;
u64 refill_error;
stats = per_cpu_ptr(pp->stats, cpu);
do {
start = u64_stats_fetch_begin_irq(&stats->syncp);
skb_alloc_error = stats->es.skb_alloc_error;
refill_error = stats->es.refill_error;
} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
es->skb_alloc_error += skb_alloc_error;
es->refill_error += refill_error;
}
}
static void mvneta_ethtool_update_stats(struct mvneta_port *pp) static void mvneta_ethtool_update_stats(struct mvneta_port *pp)
{ {
struct mvneta_ethtool_stats stats = {};
const struct mvneta_statistic *s; const struct mvneta_statistic *s;
void __iomem *base = pp->base; void __iomem *base = pp->base;
u32 high, low; u32 high, low;
u64 val; u64 val;
int i; int i;
mvneta_ethtool_update_pcpu_stats(pp, &stats);
for (i = 0, s = mvneta_statistics; for (i = 0, s = mvneta_statistics;
s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
s++, i++) { s++, i++) {
val = 0;
switch (s->type) { switch (s->type) {
case T_REG_32: case T_REG_32:
val = readl_relaxed(base + s->offset); val = readl_relaxed(base + s->offset);
pp->ethtool_stats[i] += val;
break; break;
case T_REG_64: case T_REG_64:
/* Docs say to read low 32-bit then high */ /* Docs say to read low 32-bit then high */
low = readl_relaxed(base + s->offset); low = readl_relaxed(base + s->offset);
high = readl_relaxed(base + s->offset + 4); high = readl_relaxed(base + s->offset + 4);
val = (u64)high << 32 | low; val = (u64)high << 32 | low;
pp->ethtool_stats[i] += val;
break; break;
case T_SW: case T_SW:
switch (s->offset) { switch (s->offset) {
case ETHTOOL_STAT_EEE_WAKEUP: case ETHTOOL_STAT_EEE_WAKEUP:
val = phylink_get_eee_err(pp->phylink); val = phylink_get_eee_err(pp->phylink);
pp->ethtool_stats[i] += val;
break; break;
case ETHTOOL_STAT_SKB_ALLOC_ERR: case ETHTOOL_STAT_SKB_ALLOC_ERR:
val = pp->rxqs[0].skb_alloc_err; pp->ethtool_stats[i] = stats.skb_alloc_error;
break; break;
case ETHTOOL_STAT_REFILL_ERR: case ETHTOOL_STAT_REFILL_ERR:
val = pp->rxqs[0].refill_err; pp->ethtool_stats[i] = stats.refill_error;
break; break;
} }
break; break;
} }
pp->ethtool_stats[i] += val;
} }
} }
......
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