aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_prio.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_prio.c')
-rw-r--r--net/sched/sch_prio.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 79359b69ad8d..8e5cd34aaa74 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -24,7 +24,7 @@
24 24
25struct prio_sched_data { 25struct prio_sched_data {
26 int bands; 26 int bands;
27 struct tcf_proto *filter_list; 27 struct tcf_proto __rcu *filter_list;
28 u8 prio2band[TC_PRIO_MAX+1]; 28 u8 prio2band[TC_PRIO_MAX+1];
29 struct Qdisc *queues[TCQ_PRIO_BANDS]; 29 struct Qdisc *queues[TCQ_PRIO_BANDS];
30}; 30};
@@ -36,11 +36,13 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
36 struct prio_sched_data *q = qdisc_priv(sch); 36 struct prio_sched_data *q = qdisc_priv(sch);
37 u32 band = skb->priority; 37 u32 band = skb->priority;
38 struct tcf_result res; 38 struct tcf_result res;
39 struct tcf_proto *fl;
39 int err; 40 int err;
40 41
41 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; 42 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
42 if (TC_H_MAJ(skb->priority) != sch->handle) { 43 if (TC_H_MAJ(skb->priority) != sch->handle) {
43 err = tc_classify(skb, q->filter_list, &res); 44 fl = rcu_dereference_bh(q->filter_list);
45 err = tc_classify(skb, fl, &res);
44#ifdef CONFIG_NET_CLS_ACT 46#ifdef CONFIG_NET_CLS_ACT
45 switch (err) { 47 switch (err) {
46 case TC_ACT_STOLEN: 48 case TC_ACT_STOLEN:
@@ -50,7 +52,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
50 return NULL; 52 return NULL;
51 } 53 }
52#endif 54#endif
53 if (!q->filter_list || err < 0) { 55 if (!fl || err < 0) {
54 if (TC_H_MAJ(band)) 56 if (TC_H_MAJ(band))
55 band = 0; 57 band = 0;
56 return q->queues[q->prio2band[band & TC_PRIO_MAX]]; 58 return q->queues[q->prio2band[band & TC_PRIO_MAX]];
@@ -75,7 +77,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
75 if (qdisc == NULL) { 77 if (qdisc == NULL) {
76 78
77 if (ret & __NET_XMIT_BYPASS) 79 if (ret & __NET_XMIT_BYPASS)
78 sch->qstats.drops++; 80 qdisc_qstats_drop(sch);
79 kfree_skb(skb); 81 kfree_skb(skb);
80 return ret; 82 return ret;
81 } 83 }
@@ -87,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
87 return NET_XMIT_SUCCESS; 89 return NET_XMIT_SUCCESS;
88 } 90 }
89 if (net_xmit_drop_count(ret)) 91 if (net_xmit_drop_count(ret))
90 sch->qstats.drops++; 92 qdisc_qstats_drop(sch);
91 return ret; 93 return ret;
92} 94}
93 95
@@ -322,9 +324,8 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
322 struct Qdisc *cl_q; 324 struct Qdisc *cl_q;
323 325
324 cl_q = q->queues[cl - 1]; 326 cl_q = q->queues[cl - 1];
325 cl_q->qstats.qlen = cl_q->q.qlen; 327 if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
326 if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 || 328 gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0)
327 gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
328 return -1; 329 return -1;
329 330
330 return 0; 331 return 0;
@@ -351,7 +352,8 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
351 } 352 }
352} 353}
353 354
354static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl) 355static struct tcf_proto __rcu **prio_find_tcf(struct Qdisc *sch,
356 unsigned long cl)
355{ 357{
356 struct prio_sched_data *q = qdisc_priv(sch); 358 struct prio_sched_data *q = qdisc_priv(sch);
357 359