diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_generic.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index f6803e1d6783..ec757f66896a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -174,7 +174,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, int ret = NETDEV_TX_BUSY; /* And release qdisc */ - spin_unlock(root_lock); + if (root_lock) + spin_unlock(root_lock); /* Note that we validate skb (GSO, checksum, ...) outside of locks */ if (validate) @@ -187,10 +188,13 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, HARD_TX_UNLOCK(dev, txq); } else { - spin_lock(root_lock); + if (root_lock) + spin_lock(root_lock); return qdisc_qlen(q); } - spin_lock(root_lock); + + if (root_lock) + spin_lock(root_lock); if (dev_xmit_complete(ret)) { /* Driver sent out skb successfully or skb was consumed */ @@ -231,9 +235,9 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, */ static inline int qdisc_restart(struct Qdisc *q, int *packets) { + spinlock_t *root_lock = NULL; struct netdev_queue *txq; struct net_device *dev; - spinlock_t *root_lock; struct sk_buff *skb; bool validate; @@ -242,7 +246,9 @@ static inline int qdisc_restart(struct Qdisc *q, int *packets) if (unlikely(!skb)) return 0; - root_lock = qdisc_lock(q); + if (!(q->flags & TCQ_F_NOLOCK)) + root_lock = qdisc_lock(q); + dev = qdisc_dev(q); txq = skb_get_tx_queue(dev, skb); @@ -880,14 +886,18 @@ static bool some_qdisc_is_busy(struct net_device *dev) dev_queue = netdev_get_tx_queue(dev, i); q = dev_queue->qdisc_sleeping; - root_lock = qdisc_lock(q); - spin_lock_bh(root_lock); + if (q->flags & TCQ_F_NOLOCK) { + val = test_bit(__QDISC_STATE_SCHED, &q->state); + } else { + root_lock = qdisc_lock(q); + spin_lock_bh(root_lock); - val = (qdisc_is_running(q) || - test_bit(__QDISC_STATE_SCHED, &q->state)); + val = (qdisc_is_running(q) || + test_bit(__QDISC_STATE_SCHED, &q->state)); - spin_unlock_bh(root_lock); + spin_unlock_bh(root_lock); + } if (val) return true; |