net: sched: Schedule PRIO qdisc when flow control released

The PRIO qdisc supports flow control, such that packet
dequeue can be disabled based on boolean flag 'enable_flow'.
When flow is re-enabled, the latency for new packets
arriving at network driver is high.  To reduce the delay in
scheduling packets, the qdisc will now invoke
__netif_schedule() to expedite dequeue.  This significantly
reduces the latency of packets arriving at network driver.

CRs-Fixed: 2085929
Change-Id: Ic5fe3faf86f177300d3018b9f60974ba3811641c
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 353c6a1..230f7e9 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 
@@ -164,6 +165,7 @@
 	struct Qdisc *queues[TCQ_PRIO_BANDS];
 	int oldbands = q->bands, i;
 	struct tc_prio_qopt *qopt;
+	int flow_change = 0;
 
 	if (nla_len(opt) < sizeof(*qopt))
 		return -EINVAL;
@@ -189,7 +191,10 @@
 	}
 
 	sch_tree_lock(sch);
-	q->enable_flow = qopt->enable_flow;
+	if (q->enable_flow != qopt->enable_flow) {
+		q->enable_flow = qopt->enable_flow;
+		flow_change = 1;
+	}
 	q->bands = qopt->bands;
 	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
 
@@ -205,6 +210,12 @@
 		q->queues[i] = queues[i];
 
 	sch_tree_unlock(sch);
+
+	/* Schedule qdisc when flow re-enabled */
+	if (flow_change && q->enable_flow) {
+		if (!test_bit(__QDISC_STATE_DEACTIVATED, &sch->state))
+			__netif_schedule(qdisc_root(sch));
+	}
 	return 0;
 }