diff options
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r-- | include/net/sch_generic.h | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 03ca5d826757..3c8728aaab4e 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -23,11 +23,17 @@ struct qdisc_rate_table { | |||
23 | }; | 23 | }; |
24 | 24 | ||
25 | enum qdisc_state_t { | 25 | enum qdisc_state_t { |
26 | __QDISC_STATE_RUNNING, | ||
27 | __QDISC_STATE_SCHED, | 26 | __QDISC_STATE_SCHED, |
28 | __QDISC_STATE_DEACTIVATED, | 27 | __QDISC_STATE_DEACTIVATED, |
29 | }; | 28 | }; |
30 | 29 | ||
30 | /* | ||
31 | * following bits are only changed while qdisc lock is held | ||
32 | */ | ||
33 | enum qdisc___state_t { | ||
34 | __QDISC___STATE_RUNNING, | ||
35 | }; | ||
36 | |||
31 | struct qdisc_size_table { | 37 | struct qdisc_size_table { |
32 | struct list_head list; | 38 | struct list_head list; |
33 | struct tc_sizespec szopts; | 39 | struct tc_sizespec szopts; |
@@ -72,10 +78,27 @@ struct Qdisc { | |||
72 | unsigned long state; | 78 | unsigned long state; |
73 | struct sk_buff_head q; | 79 | struct sk_buff_head q; |
74 | struct gnet_stats_basic_packed bstats; | 80 | struct gnet_stats_basic_packed bstats; |
81 | unsigned long __state; | ||
75 | struct gnet_stats_queue qstats; | 82 | struct gnet_stats_queue qstats; |
76 | struct rcu_head rcu_head; | 83 | struct rcu_head rcu_head; |
84 | spinlock_t busylock; | ||
77 | }; | 85 | }; |
78 | 86 | ||
87 | static inline bool qdisc_is_running(struct Qdisc *qdisc) | ||
88 | { | ||
89 | return test_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
90 | } | ||
91 | |||
92 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) | ||
93 | { | ||
94 | return !__test_and_set_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
95 | } | ||
96 | |||
97 | static inline void qdisc_run_end(struct Qdisc *qdisc) | ||
98 | { | ||
99 | __clear_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
100 | } | ||
101 | |||
79 | struct Qdisc_class_ops { | 102 | struct Qdisc_class_ops { |
80 | /* Child qdisc manipulation */ | 103 | /* Child qdisc manipulation */ |
81 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); | 104 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); |
@@ -313,12 +336,24 @@ extern void qdisc_calculate_pkt_len(struct sk_buff *skb, | |||
313 | extern void tcf_destroy(struct tcf_proto *tp); | 336 | extern void tcf_destroy(struct tcf_proto *tp); |
314 | extern void tcf_destroy_chain(struct tcf_proto **fl); | 337 | extern void tcf_destroy_chain(struct tcf_proto **fl); |
315 | 338 | ||
316 | /* Reset all TX qdiscs of a device. */ | 339 | /* Reset all TX qdiscs greater then index of a device. */ |
340 | static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) | ||
341 | { | ||
342 | struct Qdisc *qdisc; | ||
343 | |||
344 | for (; i < dev->num_tx_queues; i++) { | ||
345 | qdisc = netdev_get_tx_queue(dev, i)->qdisc; | ||
346 | if (qdisc) { | ||
347 | spin_lock_bh(qdisc_lock(qdisc)); | ||
348 | qdisc_reset(qdisc); | ||
349 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
317 | static inline void qdisc_reset_all_tx(struct net_device *dev) | 354 | static inline void qdisc_reset_all_tx(struct net_device *dev) |
318 | { | 355 | { |
319 | unsigned int i; | 356 | qdisc_reset_all_tx_gt(dev, 0); |
320 | for (i = 0; i < dev->num_tx_queues; i++) | ||
321 | qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc); | ||
322 | } | 357 | } |
323 | 358 | ||
324 | /* Are all TX queues of the device empty? */ | 359 | /* Are all TX queues of the device empty? */ |
@@ -571,9 +606,16 @@ static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen) | |||
571 | } | 606 | } |
572 | 607 | ||
573 | #ifdef CONFIG_NET_CLS_ACT | 608 | #ifdef CONFIG_NET_CLS_ACT |
574 | static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask) | 609 | static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask, |
610 | int action) | ||
575 | { | 611 | { |
576 | struct sk_buff *n = skb_clone(skb, gfp_mask); | 612 | struct sk_buff *n; |
613 | |||
614 | if ((action == TC_ACT_STOLEN || action == TC_ACT_QUEUED) && | ||
615 | !skb_shared(skb)) | ||
616 | n = skb_get(skb); | ||
617 | else | ||
618 | n = skb_clone(skb, gfp_mask); | ||
577 | 619 | ||
578 | if (n) { | 620 | if (n) { |
579 | n->tc_verd = SET_TC_VERD(n->tc_verd, 0); | 621 | n->tc_verd = SET_TC_VERD(n->tc_verd, 0); |