aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-16 01:42:40 -0700
committerDavid S. Miller <davem@davemloft.net>2008-07-17 19:21:19 -0700
commit7698b4fcabcd790efc4f226bada1e7b5870653af (patch)
tree031ce7a911fc5bff995421a5615d9ab25416a479 /net/sched/sch_generic.c
parentpkt_sched: Make QDISC_RUNNING a qdisc state. (diff)
downloadlinux-dev-7698b4fcabcd790efc4f226bada1e7b5870653af.tar.xz
linux-dev-7698b4fcabcd790efc4f226bada1e7b5870653af.zip
pkt_sched: Add and use qdisc_root() and qdisc_root_lock().
When code wants to lock the qdisc tree state, the logic operation it's doing is locking the top-level qdisc that sits of the root of the netdev_queue. Add qdisc_root_lock() to represent this and convert the easiest cases. In order for this to work out in all cases, we have to hook up the noop_qdisc to a dummy netdev_queue. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index ac208c2b2d10..739a8711ab30 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -151,14 +151,17 @@ static inline int qdisc_restart(struct netdev_queue *txq,
{
int ret = NETDEV_TX_BUSY;
struct net_device *dev;
+ spinlock_t *root_lock;
struct sk_buff *skb;
/* Dequeue packet */
if (unlikely((skb = dequeue_skb(q)) == NULL))
return 0;
- /* And release queue */
- spin_unlock(&txq->lock);
+ root_lock = qdisc_root_lock(q);
+
+ /* And release qdisc */
+ spin_unlock(root_lock);
dev = txq->dev;
@@ -167,7 +170,7 @@ static inline int qdisc_restart(struct netdev_queue *txq,
ret = dev_hard_start_xmit(skb, dev, txq);
HARD_TX_UNLOCK(dev, txq);
- spin_lock(&txq->lock);
+ spin_lock(root_lock);
switch (ret) {
case NETDEV_TX_OK:
@@ -345,12 +348,18 @@ struct Qdisc_ops noop_qdisc_ops __read_mostly = {
.owner = THIS_MODULE,
};
+static struct netdev_queue noop_netdev_queue = {
+ .lock = __SPIN_LOCK_UNLOCKED(noop_netdev_queue.lock),
+ .qdisc = &noop_qdisc,
+};
+
struct Qdisc noop_qdisc = {
.enqueue = noop_enqueue,
.dequeue = noop_dequeue,
.flags = TCQ_F_BUILTIN,
.ops = &noop_qdisc_ops,
.list = LIST_HEAD_INIT(noop_qdisc.list),
+ .dev_queue = &noop_netdev_queue,
};
EXPORT_SYMBOL(noop_qdisc);
@@ -666,19 +675,21 @@ static bool some_qdisc_is_running(struct net_device *dev, int lock)
for (i = 0; i < dev->num_tx_queues; i++) {
struct netdev_queue *dev_queue;
+ spinlock_t *root_lock;
struct Qdisc *q;
int val;
dev_queue = netdev_get_tx_queue(dev, i);
q = dev_queue->qdisc;
+ root_lock = qdisc_root_lock(q);
if (lock)
- spin_lock_bh(&dev_queue->lock);
+ spin_lock_bh(root_lock);
val = test_bit(__QDISC_STATE_RUNNING, &q->state);
if (lock)
- spin_unlock_bh(&dev_queue->lock);
+ spin_unlock_bh(root_lock);
if (val)
return true;