summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/dev.c4
-rw-r--r--net/sched/cls_route.c4
-rw-r--r--net/sched/sch_api.c26
-rw-r--r--net/sched/sch_generic.c6
-rw-r--r--net/sched/sch_ingress.c9
5 files changed, 26 insertions, 23 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 7f31d0f8842..c8f5ea9aea8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1747,10 +1747,10 @@ static int ing_filter(struct sk_buff *skb)
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
- spin_lock(&dev->queue_lock);
+ spin_lock(&dev->ingress_lock);
if ((q = dev->qdisc_ingress) != NULL)
result = q->enqueue(skb, q);
- spin_unlock(&dev->queue_lock);
+ spin_unlock(&dev->ingress_lock);
}
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index e92d716c915..cc941d0ee3a 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -89,9 +89,9 @@ static __inline__ int route4_fastmap_hash(u32 id, int iif)
static inline
void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
{
- spin_lock_bh(&dev->queue_lock);
+ qdisc_lock_tree(dev);
memset(head->fastmap, 0, sizeof(head->fastmap));
- spin_unlock_bh(&dev->queue_lock);
+ qdisc_unlock_tree(dev);
}
static inline void
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 0ce6914f598..8699e7006d8 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -500,12 +500,16 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
if (handle == TC_H_INGRESS) {
sch->flags |= TCQ_F_INGRESS;
+ sch->stats_lock = &dev->ingress_lock;
handle = TC_H_MAKE(TC_H_INGRESS, 0);
- } else if (handle == 0) {
- handle = qdisc_alloc_handle(dev);
- err = -ENOMEM;
- if (handle == 0)
- goto err_out3;
+ } else {
+ sch->stats_lock = &dev->queue_lock;
+ if (handle == 0) {
+ handle = qdisc_alloc_handle(dev);
+ err = -ENOMEM;
+ if (handle == 0)
+ goto err_out3;
+ }
}
sch->handle = handle;
@@ -654,9 +658,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
return err;
if (q) {
qdisc_notify(skb, n, clid, q, NULL);
- spin_lock_bh(&dev->queue_lock);
+ qdisc_lock_tree(dev);
qdisc_destroy(q);
- spin_unlock_bh(&dev->queue_lock);
+ qdisc_unlock_tree(dev);
}
} else {
qdisc_notify(skb, n, clid, NULL, q);
@@ -789,17 +793,17 @@ graft:
err = qdisc_graft(dev, p, clid, q, &old_q);
if (err) {
if (q) {
- spin_lock_bh(&dev->queue_lock);
+ qdisc_lock_tree(dev);
qdisc_destroy(q);
- spin_unlock_bh(&dev->queue_lock);
+ qdisc_unlock_tree(dev);
}
return err;
}
qdisc_notify(skb, n, clid, old_q, q);
if (old_q) {
- spin_lock_bh(&dev->queue_lock);
+ qdisc_lock_tree(dev);
qdisc_destroy(old_q);
- spin_unlock_bh(&dev->queue_lock);
+ qdisc_unlock_tree(dev);
}
}
return 0;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 1894eb72f6c..3385ee59254 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -42,16 +42,20 @@
* The idea is the following:
* - enqueue, dequeue are serialized via top level device
* spinlock dev->queue_lock.
+ * - ingress filtering is serialized via top level device
+ * spinlock dev->ingress_lock.
* - updates to tree and tree walking are only done under the rtnl mutex.
*/
void qdisc_lock_tree(struct net_device *dev)
{
spin_lock_bh(&dev->queue_lock);
+ spin_lock(&dev->ingress_lock);
}
void qdisc_unlock_tree(struct net_device *dev)
{
+ spin_unlock(&dev->ingress_lock);
spin_unlock_bh(&dev->queue_lock);
}
@@ -431,7 +435,6 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
sch->dequeue = ops->dequeue;
sch->dev = dev;
dev_hold(dev);
- sch->stats_lock = &dev->queue_lock;
atomic_set(&sch->refcnt, 1);
return sch;
@@ -447,6 +450,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
sch = qdisc_alloc(dev, ops);
if (IS_ERR(sch))
goto errout;
+ sch->stats_lock = &dev->queue_lock;
sch->parent = parentid;
if (!ops->init || ops->init(sch, NULL) == 0)
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 1fb60aba1e6..ad22dc6af22 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -248,16 +248,11 @@ ing_hook(unsigned int hook, struct sk_buff **pskb,
skb->dev ? (*pskb)->dev->name : "(no dev)",
skb->len);
-/*
-revisit later: Use a private since lock dev->queue_lock is also
-used on the egress (might slow things for an iota)
-*/
-
if (dev->qdisc_ingress) {
- spin_lock(&dev->queue_lock);
+ spin_lock(&dev->ingress_lock);
if ((q = dev->qdisc_ingress) != NULL)
fwres = q->enqueue(skb, q);
- spin_unlock(&dev->queue_lock);
+ spin_unlock(&dev->ingress_lock);
}
return fwres;