diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index f01a9c41f112..a0bc087616a4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1786,6 +1786,40 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
1786 | return netdev_get_tx_queue(dev, queue_index); | 1786 | return netdev_get_tx_queue(dev, queue_index); |
1787 | } | 1787 | } |
1788 | 1788 | ||
1789 | static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | ||
1790 | struct net_device *dev, | ||
1791 | struct netdev_queue *txq) | ||
1792 | { | ||
1793 | spinlock_t *root_lock = qdisc_lock(q); | ||
1794 | int rc; | ||
1795 | |||
1796 | spin_lock(root_lock); | ||
1797 | if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) { | ||
1798 | kfree_skb(skb); | ||
1799 | rc = NET_XMIT_DROP; | ||
1800 | } else if ((q->flags & TCQ_F_CAN_BYPASS) && !qdisc_qlen(q) && | ||
1801 | !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) { | ||
1802 | /* | ||
1803 | * This is a work-conserving queue; there are no old skbs | ||
1804 | * waiting to be sent out; and the qdisc is not running - | ||
1805 | * xmit the skb directly. | ||
1806 | */ | ||
1807 | __qdisc_update_bstats(q, skb->len); | ||
1808 | if (sch_direct_xmit(skb, q, dev, txq, root_lock)) | ||
1809 | __qdisc_run(q); | ||
1810 | else | ||
1811 | clear_bit(__QDISC_STATE_RUNNING, &q->state); | ||
1812 | |||
1813 | rc = NET_XMIT_SUCCESS; | ||
1814 | } else { | ||
1815 | rc = qdisc_enqueue_root(skb, q); | ||
1816 | qdisc_run(q); | ||
1817 | } | ||
1818 | spin_unlock(root_lock); | ||
1819 | |||
1820 | return rc; | ||
1821 | } | ||
1822 | |||
1789 | /** | 1823 | /** |
1790 | * dev_queue_xmit - transmit a buffer | 1824 | * dev_queue_xmit - transmit a buffer |
1791 | * @skb: buffer to transmit | 1825 | * @skb: buffer to transmit |
@@ -1859,19 +1893,7 @@ gso: | |||
1859 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); | 1893 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); |
1860 | #endif | 1894 | #endif |
1861 | if (q->enqueue) { | 1895 | if (q->enqueue) { |
1862 | spinlock_t *root_lock = qdisc_lock(q); | 1896 | rc = __dev_xmit_skb(skb, q, dev, txq); |
1863 | |||
1864 | spin_lock(root_lock); | ||
1865 | |||
1866 | if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) { | ||
1867 | kfree_skb(skb); | ||
1868 | rc = NET_XMIT_DROP; | ||
1869 | } else { | ||
1870 | rc = qdisc_enqueue_root(skb, q); | ||
1871 | qdisc_run(q); | ||
1872 | } | ||
1873 | spin_unlock(root_lock); | ||
1874 | |||
1875 | goto out; | 1897 | goto out; |
1876 | } | 1898 | } |
1877 | 1899 | ||