|
@@ -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;
|