Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6686a36 authored by Tianyi Gou's avatar Tianyi Gou Committed by Matt Wagantall
Browse files

net_sched: Add flow control support to prio qdisc



Add enable_flow flag to the prio qdisc.  Packet flow is
enabled by default, but can be disabled from userspace
(e.g. IPROUTE2 tc tool).  This allows for suspending packet
dequeue on a per-qdisc basis, which is needed to supprot
Quality of Service (QOS) when using WWAN modem.

Change-Id: I932f296be946f1acc3b00c7d8569bbb733d33622
Acked-by: default avatarAndrew Richardson <randrew@qualcomm.com>
CRs-Fixed: 283471
Signed-off-by: default avatarTianyi Gou <tgou@codeaurora.org>
(cherry picked from commit 341cb4c4bb476f6017f817dad5df725f6f82af06)
Signed-off-by: default avatarJosh Cartwright <joshc@codeaurora.org>
parent 49d1507e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ struct tc_fifo_qopt {
struct tc_prio_qopt {
	int	bands;			/* Number of bands */
	__u8	priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> PRIO band */
	__u8	enable_flow;		/* Enable dequeue */
};

/* MULTIQ section */
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ struct prio_sched_data {
	struct tcf_proto __rcu *filter_list;
	u8  prio2band[TC_PRIO_MAX+1];
	struct Qdisc *queues[TCQ_PRIO_BANDS];
	u8 enable_flow;
};


@@ -98,6 +99,9 @@ static struct sk_buff *prio_peek(struct Qdisc *sch)
	struct prio_sched_data *q = qdisc_priv(sch);
	int prio;

	if (!q->enable_flow)
		return NULL;

	for (prio = 0; prio < q->bands; prio++) {
		struct Qdisc *qdisc = q->queues[prio];
		struct sk_buff *skb = qdisc->ops->peek(qdisc);
@@ -112,6 +116,9 @@ static struct sk_buff *prio_dequeue(struct Qdisc *sch)
	struct prio_sched_data *q = qdisc_priv(sch);
	int prio;

	if (!q->enable_flow)
		return NULL;

	for (prio = 0; prio < q->bands; prio++) {
		struct Qdisc *qdisc = q->queues[prio];
		struct sk_buff *skb = qdisc_dequeue_peeked(qdisc);
@@ -152,6 +159,7 @@ prio_reset(struct Qdisc *sch)
	for (prio = 0; prio < q->bands; prio++)
		qdisc_reset(q->queues[prio]);
	sch->q.qlen = 0;
	q->enable_flow = 1;
}

static void
@@ -184,6 +192,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
	}

	sch_tree_lock(sch);
	q->enable_flow = qopt->enable_flow;
	q->bands = qopt->bands;
	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);

@@ -247,6 +256,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
	struct tc_prio_qopt opt;

	opt.bands = q->bands;
	opt.enable_flow = q->enable_flow;
	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX + 1);

	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))