aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/sch_gred.c2
-rw-r--r--net/sched/sch_red.c4
-rw-r--r--net/sched/sch_teql.c31
3 files changed, 23 insertions, 14 deletions
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index b9493a09a870..6cd8ddfb512d 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -385,7 +385,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
385 struct gred_sched_data *q; 385 struct gred_sched_data *q;
386 386
387 if (table->tab[dp] == NULL) { 387 if (table->tab[dp] == NULL) {
388 table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL); 388 table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC);
389 if (table->tab[dp] == NULL) 389 if (table->tab[dp] == NULL)
390 return -ENOMEM; 390 return -ENOMEM;
391 } 391 }
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 6649463da1b6..d617161f8dd3 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -209,8 +209,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
209 ctl->Plog, ctl->Scell_log, 209 ctl->Plog, ctl->Scell_log,
210 nla_data(tb[TCA_RED_STAB])); 210 nla_data(tb[TCA_RED_STAB]));
211 211
212 if (skb_queue_empty(&sch->q)) 212 if (!q->qdisc->q.qlen)
213 red_end_of_idle_period(&q->parms); 213 red_start_of_idle_period(&q->parms);
214 214
215 sch_tree_unlock(sch); 215 sch_tree_unlock(sch);
216 return 0; 216 return 0;
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index a3b7120fcc74..4f4c52c0eeb3 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
225 225
226 226
227static int 227static int
228__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) 228__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
229 struct net_device *dev, struct netdev_queue *txq,
230 struct neighbour *mn)
229{ 231{
230 struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); 232 struct teql_sched_data *q = qdisc_priv(txq->qdisc);
231 struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc);
232 struct neighbour *mn = dst_get_neighbour(skb_dst(skb));
233 struct neighbour *n = q->ncache; 233 struct neighbour *n = q->ncache;
234 234
235 if (mn->tbl == NULL) 235 if (mn->tbl == NULL)
@@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
262} 262}
263 263
264static inline int teql_resolve(struct sk_buff *skb, 264static inline int teql_resolve(struct sk_buff *skb,
265 struct sk_buff *skb_res, struct net_device *dev) 265 struct sk_buff *skb_res,
266 struct net_device *dev,
267 struct netdev_queue *txq)
266{ 268{
267 struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); 269 struct dst_entry *dst = skb_dst(skb);
270 struct neighbour *mn;
271 int res;
272
268 if (txq->qdisc == &noop_qdisc) 273 if (txq->qdisc == &noop_qdisc)
269 return -ENODEV; 274 return -ENODEV;
270 275
271 if (dev->header_ops == NULL || 276 if (!dev->header_ops || !dst)
272 skb_dst(skb) == NULL ||
273 dst_get_neighbour(skb_dst(skb)) == NULL)
274 return 0; 277 return 0;
275 return __teql_resolve(skb, skb_res, dev); 278
279 rcu_read_lock();
280 mn = dst_get_neighbour(dst);
281 res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0;
282 rcu_read_unlock();
283
284 return res;
276} 285}
277 286
278static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) 287static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -307,7 +316,7 @@ restart:
307 continue; 316 continue;
308 } 317 }
309 318
310 switch (teql_resolve(skb, skb_res, slave)) { 319 switch (teql_resolve(skb, skb_res, slave, slave_txq)) {
311 case 0: 320 case 0:
312 if (__netif_tx_trylock(slave_txq)) { 321 if (__netif_tx_trylock(slave_txq)) {
313 unsigned int length = qdisc_pkt_len(skb); 322 unsigned int length = qdisc_pkt_len(skb);