From 990b50a53ad80fe4e0357c7cc41a393eea2b0d76 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 19 Nov 2018 15:21:44 -0800 Subject: [PATCH] nfp: abm: wrap RED parameters in bands Wrap RED parameters and stats into a structure, and a 1-element array. Upcoming GRED offload will add the support for more bands. Signed-off-by: Jakub Kicinski Reviewed-by: John Hurley Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/abm/main.h | 26 +++--- .../net/ethernet/netronome/nfp/abm/qdisc.c | 88 ++++++++++++------- 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.h b/drivers/net/ethernet/netronome/nfp/abm/main.h index 054228c29184..47888288a706 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/main.h +++ b/drivers/net/ethernet/netronome/nfp/abm/main.h @@ -112,11 +112,13 @@ enum nfp_qdisc_type { * @mq.prev_stats: previously reported @mq.stats * * @red: RED Qdisc specific parameters and state - * @red.threshold: ECN marking threshold - * @red.stats: current stats of the RED Qdisc - * @red.prev_stats: previously reported @red.stats - * @red.xstats: extended stats for RED - current - * @red.prev_xstats: extended stats for RED - previously reported + * @red.num_bands: Number of valid entries in the @red.band table + * @red.band: Per-band array of RED instances + * @red.band.threshold: ECN marking threshold + * @red.band.stats: current stats of the RED Qdisc + * @red.band.prev_stats: previously reported @red.stats + * @red.band.xstats: extended stats for RED - current + * @red.band.prev_xstats: extended stats for RED - previously reported */ struct nfp_qdisc { struct net_device *netdev; @@ -139,11 +141,15 @@ struct nfp_qdisc { } mq; /* TC_SETUP_QDISC_RED */ struct { - u32 threshold; - struct nfp_alink_stats stats; - struct nfp_alink_stats prev_stats; - struct nfp_alink_xstats xstats; - struct nfp_alink_xstats prev_xstats; + unsigned int num_bands; + + struct { + u32 threshold; + struct nfp_alink_stats stats; + struct nfp_alink_stats prev_stats; + struct nfp_alink_xstats xstats; + struct nfp_alink_xstats prev_xstats; + } band[1]; } red; }; }; diff --git a/drivers/net/ethernet/netronome/nfp/abm/qdisc.c b/drivers/net/ethernet/netronome/nfp/abm/qdisc.c index 251ce3070564..b65b3177c94a 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/qdisc.c +++ b/drivers/net/ethernet/netronome/nfp/abm/qdisc.c @@ -46,20 +46,25 @@ nfp_abm_stats_update_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, unsigned int queue) { struct nfp_cpp *cpp = alink->abm->app->cpp; + unsigned int i; int err; if (!qdisc->offloaded) return; - err = nfp_abm_ctrl_read_q_stats(alink, 0, queue, &qdisc->red.stats); - if (err) - nfp_err(cpp, "RED stats (%d, %d) read failed with error %d\n", - 0, queue, err); - - err = nfp_abm_ctrl_read_q_xstats(alink, 0, queue, &qdisc->red.xstats); - if (err) - nfp_err(cpp, "RED xstats (%d, %d) read failed with error %d\n", - 0, queue, err); + for (i = 0; i < qdisc->red.num_bands; i++) { + err = nfp_abm_ctrl_read_q_stats(alink, i, queue, + &qdisc->red.band[i].stats); + if (err) + nfp_err(cpp, "RED stats (%d, %d) read failed with error %d\n", + i, queue, err); + + err = nfp_abm_ctrl_read_q_xstats(alink, i, queue, + &qdisc->red.band[i].xstats); + if (err) + nfp_err(cpp, "RED xstats (%d, %d) read failed with error %d\n", + i, queue, err); + } } static void @@ -113,6 +118,8 @@ nfp_abm_qdisc_unlink_children(struct nfp_qdisc *qdisc, static void nfp_abm_qdisc_offload_stop(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc) { + unsigned int i; + /* Don't complain when qdisc is getting unlinked */ if (qdisc->use_cnt) nfp_warn(alink->abm->app->cpp, "Offload of '%08x' stopped\n", @@ -121,8 +128,10 @@ nfp_abm_qdisc_offload_stop(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc) if (!nfp_abm_qdisc_is_red(qdisc)) return; - qdisc->red.stats.backlog_pkts = 0; - qdisc->red.stats.backlog_bytes = 0; + for (i = 0; i < qdisc->red.num_bands; i++) { + qdisc->red.band[i].stats.backlog_pkts = 0; + qdisc->red.band[i].stats.backlog_bytes = 0; + } } static int @@ -164,15 +173,26 @@ static int nfp_abm_stats_init(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, unsigned int queue) { - return __nfp_abm_stats_init(alink, 0, queue, - &qdisc->red.prev_stats, - &qdisc->red.prev_xstats); + unsigned int i; + int err; + + for (i = 0; i < qdisc->red.num_bands; i++) { + err = __nfp_abm_stats_init(alink, i, queue, + &qdisc->red.band[i].prev_stats, + &qdisc->red.band[i].prev_xstats); + if (err) + return err; + } + + return 0; } static void nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, unsigned int queue) { + unsigned int i; + qdisc->offload_mark = qdisc->type == NFP_QDISC_RED && qdisc->params_ok && qdisc->use_cnt == 1 && @@ -186,7 +206,9 @@ nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, if (!qdisc->offload_mark) return; - nfp_abm_ctrl_set_q_lvl(alink, 0, queue, qdisc->red.threshold); + for (i = 0; i < alink->abm->num_bands; i++) + nfp_abm_ctrl_set_q_lvl(alink, i, queue, + qdisc->red.band[i].threshold); } static void @@ -217,8 +239,10 @@ void nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink) size_t i; /* Mark all thresholds as unconfigured */ - __bitmap_set(abm->threshold_undef, - alink->queue_base, alink->total_queues); + for (i = 0; i < abm->num_bands; i++) + __bitmap_set(abm->threshold_undef, + i * NFP_NET_MAX_RX_RINGS + alink->queue_base, + alink->total_queues); /* Clear offload marks */ radix_tree_for_each_slot(slot, &alink->qdiscs, &iter, 0) { @@ -451,10 +475,10 @@ nfp_abm_red_xstats(struct nfp_abm_link *alink, struct tc_red_qopt_offload *opt) if (!qdisc || !qdisc->offloaded) return -EOPNOTSUPP; - nfp_abm_stats_red_calculate(&qdisc->red.xstats, - &qdisc->red.prev_xstats, + nfp_abm_stats_red_calculate(&qdisc->red.band[0].xstats, + &qdisc->red.band[0].prev_xstats, opt->xstats); - qdisc->red.prev_xstats = qdisc->red.xstats; + qdisc->red.band[0].prev_xstats = qdisc->red.band[0].xstats; return 0; } @@ -473,10 +497,10 @@ nfp_abm_red_stats(struct nfp_abm_link *alink, u32 handle, * counters back so carry on even if qdisc is not currently offloaded. */ - nfp_abm_stats_calculate(&qdisc->red.stats, - &qdisc->red.prev_stats, + nfp_abm_stats_calculate(&qdisc->red.band[0].stats, + &qdisc->red.band[0].prev_stats, stats->bstats, stats->qstats); - qdisc->red.prev_stats = qdisc->red.stats; + qdisc->red.band[0].prev_stats = qdisc->red.band[0].stats; return qdisc->offloaded ? 0 : -EOPNOTSUPP; } @@ -538,8 +562,10 @@ nfp_abm_red_replace(struct net_device *netdev, struct nfp_abm_link *alink, } qdisc->params_ok = nfp_abm_red_check_params(alink, opt); - if (qdisc->params_ok) - qdisc->red.threshold = opt->set.min; + if (qdisc->params_ok) { + qdisc->red.num_bands = 1; + qdisc->red.band[0].threshold = opt->set.min; + } if (qdisc->use_cnt == 1) nfp_abm_qdisc_offload_update(alink); @@ -592,7 +618,7 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle, struct tc_qopt_offload_stats *stats) { struct nfp_qdisc *qdisc, *red; - unsigned int i; + unsigned int i, j; qdisc = nfp_abm_qdisc_find(alink, handle); if (!qdisc) @@ -614,10 +640,12 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle, continue; red = qdisc->children[i]; - nfp_abm_stats_propagate(&qdisc->mq.stats, - &red->red.stats); - nfp_abm_stats_propagate(&qdisc->mq.prev_stats, - &red->red.prev_stats); + for (j = 0; j < red->red.num_bands; j++) { + nfp_abm_stats_propagate(&qdisc->mq.stats, + &red->red.band[j].stats); + nfp_abm_stats_propagate(&qdisc->mq.prev_stats, + &red->red.band[j].prev_stats); + } } nfp_abm_stats_calculate(&qdisc->mq.stats, &qdisc->mq.prev_stats, -- 2.30.2