Commit 990b50a5 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarJohn Hurley <john.hurley@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e49efd52
...@@ -112,11 +112,13 @@ enum nfp_qdisc_type { ...@@ -112,11 +112,13 @@ enum nfp_qdisc_type {
* @mq.prev_stats: previously reported @mq.stats * @mq.prev_stats: previously reported @mq.stats
* *
* @red: RED Qdisc specific parameters and state * @red: RED Qdisc specific parameters and state
* @red.threshold: ECN marking threshold * @red.num_bands: Number of valid entries in the @red.band table
* @red.stats: current stats of the RED Qdisc * @red.band: Per-band array of RED instances
* @red.prev_stats: previously reported @red.stats * @red.band.threshold: ECN marking threshold
* @red.xstats: extended stats for RED - current * @red.band.stats: current stats of the RED Qdisc
* @red.prev_xstats: extended stats for RED - previously reported * @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 nfp_qdisc {
struct net_device *netdev; struct net_device *netdev;
...@@ -138,12 +140,16 @@ struct nfp_qdisc { ...@@ -138,12 +140,16 @@ struct nfp_qdisc {
struct nfp_alink_stats prev_stats; struct nfp_alink_stats prev_stats;
} mq; } mq;
/* TC_SETUP_QDISC_RED */ /* TC_SETUP_QDISC_RED */
struct {
unsigned int num_bands;
struct { struct {
u32 threshold; u32 threshold;
struct nfp_alink_stats stats; struct nfp_alink_stats stats;
struct nfp_alink_stats prev_stats; struct nfp_alink_stats prev_stats;
struct nfp_alink_xstats xstats; struct nfp_alink_xstats xstats;
struct nfp_alink_xstats prev_xstats; struct nfp_alink_xstats prev_xstats;
} band[1];
} red; } red;
}; };
}; };
......
...@@ -46,20 +46,25 @@ nfp_abm_stats_update_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, ...@@ -46,20 +46,25 @@ nfp_abm_stats_update_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc,
unsigned int queue) unsigned int queue)
{ {
struct nfp_cpp *cpp = alink->abm->app->cpp; struct nfp_cpp *cpp = alink->abm->app->cpp;
unsigned int i;
int err; int err;
if (!qdisc->offloaded) if (!qdisc->offloaded)
return; return;
err = nfp_abm_ctrl_read_q_stats(alink, 0, queue, &qdisc->red.stats); 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) if (err)
nfp_err(cpp, "RED stats (%d, %d) read failed with error %d\n", nfp_err(cpp, "RED stats (%d, %d) read failed with error %d\n",
0, queue, err); i, queue, err);
err = nfp_abm_ctrl_read_q_xstats(alink, 0, queue, &qdisc->red.xstats); err = nfp_abm_ctrl_read_q_xstats(alink, i, queue,
&qdisc->red.band[i].xstats);
if (err) if (err)
nfp_err(cpp, "RED xstats (%d, %d) read failed with error %d\n", nfp_err(cpp, "RED xstats (%d, %d) read failed with error %d\n",
0, queue, err); i, queue, err);
}
} }
static void static void
...@@ -113,6 +118,8 @@ nfp_abm_qdisc_unlink_children(struct nfp_qdisc *qdisc, ...@@ -113,6 +118,8 @@ nfp_abm_qdisc_unlink_children(struct nfp_qdisc *qdisc,
static void static void
nfp_abm_qdisc_offload_stop(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc) 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 */ /* Don't complain when qdisc is getting unlinked */
if (qdisc->use_cnt) if (qdisc->use_cnt)
nfp_warn(alink->abm->app->cpp, "Offload of '%08x' stopped\n", 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) ...@@ -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)) if (!nfp_abm_qdisc_is_red(qdisc))
return; return;
qdisc->red.stats.backlog_pkts = 0; for (i = 0; i < qdisc->red.num_bands; i++) {
qdisc->red.stats.backlog_bytes = 0; qdisc->red.band[i].stats.backlog_pkts = 0;
qdisc->red.band[i].stats.backlog_bytes = 0;
}
} }
static int static int
...@@ -164,15 +173,26 @@ static int ...@@ -164,15 +173,26 @@ static int
nfp_abm_stats_init(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, nfp_abm_stats_init(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc,
unsigned int queue) unsigned int queue)
{ {
return __nfp_abm_stats_init(alink, 0, queue, unsigned int i;
&qdisc->red.prev_stats, int err;
&qdisc->red.prev_xstats);
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 static void
nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc,
unsigned int queue) unsigned int queue)
{ {
unsigned int i;
qdisc->offload_mark = qdisc->type == NFP_QDISC_RED && qdisc->offload_mark = qdisc->type == NFP_QDISC_RED &&
qdisc->params_ok && qdisc->params_ok &&
qdisc->use_cnt == 1 && qdisc->use_cnt == 1 &&
...@@ -186,7 +206,9 @@ nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc, ...@@ -186,7 +206,9 @@ nfp_abm_offload_compile_red(struct nfp_abm_link *alink, struct nfp_qdisc *qdisc,
if (!qdisc->offload_mark) if (!qdisc->offload_mark)
return; 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 static void
...@@ -217,8 +239,10 @@ void nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink) ...@@ -217,8 +239,10 @@ void nfp_abm_qdisc_offload_update(struct nfp_abm_link *alink)
size_t i; size_t i;
/* Mark all thresholds as unconfigured */ /* Mark all thresholds as unconfigured */
for (i = 0; i < abm->num_bands; i++)
__bitmap_set(abm->threshold_undef, __bitmap_set(abm->threshold_undef,
alink->queue_base, alink->total_queues); i * NFP_NET_MAX_RX_RINGS + alink->queue_base,
alink->total_queues);
/* Clear offload marks */ /* Clear offload marks */
radix_tree_for_each_slot(slot, &alink->qdiscs, &iter, 0) { 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) ...@@ -451,10 +475,10 @@ nfp_abm_red_xstats(struct nfp_abm_link *alink, struct tc_red_qopt_offload *opt)
if (!qdisc || !qdisc->offloaded) if (!qdisc || !qdisc->offloaded)
return -EOPNOTSUPP; return -EOPNOTSUPP;
nfp_abm_stats_red_calculate(&qdisc->red.xstats, nfp_abm_stats_red_calculate(&qdisc->red.band[0].xstats,
&qdisc->red.prev_xstats, &qdisc->red.band[0].prev_xstats,
opt->xstats); opt->xstats);
qdisc->red.prev_xstats = qdisc->red.xstats; qdisc->red.band[0].prev_xstats = qdisc->red.band[0].xstats;
return 0; return 0;
} }
...@@ -473,10 +497,10 @@ nfp_abm_red_stats(struct nfp_abm_link *alink, u32 handle, ...@@ -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. * counters back so carry on even if qdisc is not currently offloaded.
*/ */
nfp_abm_stats_calculate(&qdisc->red.stats, nfp_abm_stats_calculate(&qdisc->red.band[0].stats,
&qdisc->red.prev_stats, &qdisc->red.band[0].prev_stats,
stats->bstats, stats->qstats); 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; return qdisc->offloaded ? 0 : -EOPNOTSUPP;
} }
...@@ -538,8 +562,10 @@ nfp_abm_red_replace(struct net_device *netdev, struct nfp_abm_link *alink, ...@@ -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); qdisc->params_ok = nfp_abm_red_check_params(alink, opt);
if (qdisc->params_ok) if (qdisc->params_ok) {
qdisc->red.threshold = opt->set.min; qdisc->red.num_bands = 1;
qdisc->red.band[0].threshold = opt->set.min;
}
if (qdisc->use_cnt == 1) if (qdisc->use_cnt == 1)
nfp_abm_qdisc_offload_update(alink); nfp_abm_qdisc_offload_update(alink);
...@@ -592,7 +618,7 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle, ...@@ -592,7 +618,7 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle,
struct tc_qopt_offload_stats *stats) struct tc_qopt_offload_stats *stats)
{ {
struct nfp_qdisc *qdisc, *red; struct nfp_qdisc *qdisc, *red;
unsigned int i; unsigned int i, j;
qdisc = nfp_abm_qdisc_find(alink, handle); qdisc = nfp_abm_qdisc_find(alink, handle);
if (!qdisc) if (!qdisc)
...@@ -614,10 +640,12 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle, ...@@ -614,10 +640,12 @@ nfp_abm_mq_stats(struct nfp_abm_link *alink, u32 handle,
continue; continue;
red = qdisc->children[i]; red = qdisc->children[i];
for (j = 0; j < red->red.num_bands; j++) {
nfp_abm_stats_propagate(&qdisc->mq.stats, nfp_abm_stats_propagate(&qdisc->mq.stats,
&red->red.stats); &red->red.band[j].stats);
nfp_abm_stats_propagate(&qdisc->mq.prev_stats, nfp_abm_stats_propagate(&qdisc->mq.prev_stats,
&red->red.prev_stats); &red->red.band[j].prev_stats);
}
} }
nfp_abm_stats_calculate(&qdisc->mq.stats, &qdisc->mq.prev_stats, nfp_abm_stats_calculate(&qdisc->mq.stats, &qdisc->mq.prev_stats,
......
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