]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/core/dev.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
[karo-tx-linux.git] / net / core / dev.c
index 29101c98399f40b6b8e42c31a255d8f1fb6bd7a1..7869ae3837ca741e344b1731dc50d8408d8bcb6c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     NET3    Protocol independent device support routines.
+ *      NET3    Protocol independent device support routines.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -7,7 +7,7 @@
  *             2 of the License, or (at your option) any later version.
  *
  *     Derived from the non IP parts of dev.c 1.0.19
- *             Authors:        Ross Biro
+ *              Authors:       Ross Biro
  *                             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *                             Mark Evans, <evansmp@uhura.aston.ac.uk>
  *
@@ -21,9 +21,9 @@
  *
  *     Changes:
  *              D.J. Barrow     :       Fixed bug where dev->refcnt gets set
- *                                     to 2 if register_netdev gets called
- *                                     before net_dev_init & also removed a
- *                                     few lines of code in the process.
+ *                                      to 2 if register_netdev gets called
+ *                                      before net_dev_init & also removed a
+ *                                      few lines of code in the process.
  *             Alan Cox        :       device private ioctl copies fields back.
  *             Alan Cox        :       Transmit queue code does relevant
  *                                     stunts to keep the queue safe.
@@ -36,7 +36,7 @@
  *             Alan Cox        :       100 backlog just doesn't cut it when
  *                                     you start doing multicast video 8)
  *             Alan Cox        :       Rewrote net_bh and list manager.
- *             Alan Cox        :       Fix ETH_P_ALL echoback lengths.
+ *              Alan Cox        :       Fix ETH_P_ALL echoback lengths.
  *             Alan Cox        :       Took out transmit every packet pass
  *                                     Saved a few bytes in the ioctl handler
  *             Alan Cox        :       Network driver sets packet type before
@@ -46,7 +46,7 @@
  *             Richard Kooijman:       Timestamp fixes.
  *             Alan Cox        :       Wrong field in SIOCGIFDSTADDR
  *             Alan Cox        :       Device lock protection.
- *             Alan Cox        :       Fixed nasty side effect of device close
+ *              Alan Cox        :       Fixed nasty side effect of device close
  *                                     changes.
  *             Rudi Cilibrasi  :       Pass the right thing to
  *                                     set_mac_address()
@@ -67,8 +67,8 @@
  *     Paul Rusty Russell      :       SIOCSIFNAME
  *              Pekka Riikonen  :      Netdev boot-time settings code
  *              Andrew Morton   :       Make unregister_netdevice wait
- *                                     indefinitely on dev->refcnt
- *             J Hadi Salim    :       - Backlog queue sampling
+ *                                      indefinitely on dev->refcnt
+ *              J Hadi Salim    :       - Backlog queue sampling
  *                                     - netif_rx() feedback
  */
 
@@ -192,7 +192,8 @@ static seqcount_t devnet_rename_seq;
 
 static inline void dev_base_seq_inc(struct net *net)
 {
-       while (++net->dev_base_seq == 0);
+       while (++net->dev_base_seq == 0)
+               ;
 }
 
 static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
@@ -274,8 +275,8 @@ EXPORT_PER_CPU_SYMBOL(softnet_data);
  * register_netdevice() inits txq->_xmit_lock and sets lockdep class
  * according to dev->type
  */
-static const unsigned short netdev_lock_type[] =
-       {ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25,
+static const unsigned short netdev_lock_type[] = {
+        ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25,
         ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET,
         ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM,
         ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP,
@@ -291,22 +292,22 @@ static const unsigned short netdev_lock_type[] =
         ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE,
         ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE};
 
-static const char *const netdev_lock_name[] =
-       {"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
-        "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET",
-        "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM",
-        "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP",
-        "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD",
-        "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25",
-        "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP",
-        "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD",
-        "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI",
-        "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE",
-        "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET",
-        "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
-        "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM",
-        "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE",
-        "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"};
+static const char *const netdev_lock_name[] = {
+       "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
+       "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET",
+       "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM",
+       "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP",
+       "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD",
+       "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25",
+       "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP",
+       "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD",
+       "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI",
+       "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE",
+       "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET",
+       "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
+       "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM",
+       "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE",
+       "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"};
 
 static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
 static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
@@ -352,10 +353,11 @@ static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
 #endif
 
 /*******************************************************************************
+ *
+ *             Protocol management and registration routines
+ *
+ *******************************************************************************/
 
-               Protocol management and registration routines
-
-*******************************************************************************/
 
 /*
  *     Add a protocol ID to the list. Now that the input handler is
@@ -538,10 +540,10 @@ void dev_remove_offload(struct packet_offload *po)
 EXPORT_SYMBOL(dev_remove_offload);
 
 /******************************************************************************
-
                    Device Boot-time Settings Routines
-
-*******************************************************************************/
+ *
*                   Device Boot-time Settings Routines
+ *
+ ******************************************************************************/
 
 /* Boot time configuration table */
 static struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX];
@@ -574,13 +576,13 @@ static int netdev_boot_setup_add(char *name, struct ifmap *map)
 }
 
 /**
- *     netdev_boot_setup_check - check boot time settings
- *     @dev: the netdevice
+ * netdev_boot_setup_check     - check boot time settings
+ * @dev: the netdevice
  *
- *     Check boot time settings for the device.
- *     The found settings are set for the device to be used
- *     later in the device probing.
- *     Returns 0 if no settings found, 1 if they are.
+ * Check boot time settings for the device.
+ * The found settings are set for the device to be used
+ * later in the device probing.
+ * Returns 0 if no settings found, 1 if they are.
  */
 int netdev_boot_setup_check(struct net_device *dev)
 {
@@ -590,10 +592,10 @@ int netdev_boot_setup_check(struct net_device *dev)
        for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
                if (s[i].name[0] != '\0' && s[i].name[0] != ' ' &&
                    !strcmp(dev->name, s[i].name)) {
-                       dev->irq        = s[i].map.irq;
-                       dev->base_addr  = s[i].map.base_addr;
-                       dev->mem_start  = s[i].map.mem_start;
-                       dev->mem_end    = s[i].map.mem_end;
+                       dev->irq = s[i].map.irq;
+                       dev->base_addr = s[i].map.base_addr;
+                       dev->mem_start = s[i].map.mem_start;
+                       dev->mem_end = s[i].map.mem_end;
                        return 1;
                }
        }
@@ -603,14 +605,14 @@ EXPORT_SYMBOL(netdev_boot_setup_check);
 
 
 /**
- *     netdev_boot_base        - get address from boot time settings
- *     @prefix: prefix for network device
- *     @unit: id for network device
+ * netdev_boot_base    - get address from boot time settings
+ * @prefix: prefix for network device
+ * @unit: id for network device
  *
- *     Check boot time settings for the base address of device.
- *     The found settings are set for the device to be used
- *     later in the device probing.
- *     Returns 0 if no settings found.
+ * Check boot time settings for the base address of device.
+ * The found settings are set for the device to be used
+ * later in the device probing.
+ * Returns 0 if no settings found.
  */
 unsigned long netdev_boot_base(const char *prefix, int unit)
 {
@@ -663,10 +665,10 @@ int __init netdev_boot_setup(char *str)
 __setup("netdev=", netdev_boot_setup);
 
 /*******************************************************************************
-
                          Device Interface Subroutines
-
-*******************************************************************************/
+ *
*                         Device Interface Subroutines
+ *
+ *******************************************************************************/
 
 /**
  *     dev_get_iflink  - get 'iflink' value of a interface
@@ -737,15 +739,15 @@ struct net_device *__dev_get_by_name(struct net *net, const char *name)
 EXPORT_SYMBOL(__dev_get_by_name);
 
 /**
- *     dev_get_by_name_rcu     - find a device by its name
- *     @net: the applicable net namespace
- *     @name: name to find
+ * dev_get_by_name_rcu - find a device by its name
+ * @net: the applicable net namespace
+ * @name: name to find
  *
- *     Find an interface by name.
- *     If the name is found a pointer to the device is returned.
- *     If the name is not found then %NULL is returned.
- *     The reference counters are not incremented so the caller must be
- *     careful with locks. The caller must hold RCU lock.
+ * Find an interface by name.
+ * If the name is found a pointer to the device is returned.
+ * If the name is not found then %NULL is returned.
+ * The reference counters are not incremented so the caller must be
+ * careful with locks. The caller must hold RCU lock.
  */
 
 struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)
@@ -1289,8 +1291,8 @@ void netdev_state_change(struct net_device *dev)
 EXPORT_SYMBOL(netdev_state_change);
 
 /**
- *     netdev_notify_peers - notify network peers about existence of @dev
- *     @dev: network device
+ * netdev_notify_peers - notify network peers about existence of @dev
+ * @dev: network device
  *
  * Generate traffic such that interested network peers are aware of
  * @dev, such as by generating a gratuitous ARP. This may be used when
@@ -1302,6 +1304,7 @@ void netdev_notify_peers(struct net_device *dev)
 {
        rtnl_lock();
        call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
+       call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev);
        rtnl_unlock();
 }
 EXPORT_SYMBOL(netdev_notify_peers);
@@ -1518,17 +1521,17 @@ static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
 static int dev_boot_phase = 1;
 
 /**
- *     register_netdevice_notifier - register a network notifier block
- *     @nb: notifier
+ * register_netdevice_notifier - register a network notifier block
+ * @nb: notifier
  *
- *     Register a notifier to be called when network device events occur.
- *     The notifier passed is linked into the kernel structures and must
- *     not be reused until it has been unregistered. A negative errno code
- *     is returned on a failure.
+ * Register a notifier to be called when network device events occur.
+ * The notifier passed is linked into the kernel structures and must
+ * not be reused until it has been unregistered. A negative errno code
+ * is returned on a failure.
  *
- *     When registered all registration and up events are replayed
- *     to the new notifier to allow device to have a race free
- *     view of the network device list.
+ * When registered all registration and up events are replayed
+ * to the new notifier to allow device to have a race free
+ * view of the network device list.
  */
 
 int register_netdevice_notifier(struct notifier_block *nb)
@@ -1585,17 +1588,17 @@ outroll:
 EXPORT_SYMBOL(register_netdevice_notifier);
 
 /**
- *     unregister_netdevice_notifier - unregister a network notifier block
- *     @nb: notifier
+ * unregister_netdevice_notifier - unregister a network notifier block
+ * @nb: notifier
  *
- *     Unregister a notifier previously registered by
- *     register_netdevice_notifier(). The notifier is unlinked into the
- *     kernel structures and may then be reused. A negative errno code
- *     is returned on a failure.
+ * Unregister a notifier previously registered by
+ * register_netdevice_notifier(). The notifier is unlinked into the
+ * kernel structures and may then be reused. A negative errno code
+ * is returned on a failure.
  *
- *     After unregistering unregister and down device events are synthesized
- *     for all devices on the device list to the removed notifier to remove
- *     the need for special case cleanup code.
+ * After unregistering unregister and down device events are synthesized
+ * for all devices on the device list to the removed notifier to remove
+ * the need for special case cleanup code.
  */
 
 int unregister_netdevice_notifier(struct notifier_block *nb)
@@ -1696,27 +1699,54 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
 static struct static_key netstamp_needed __read_mostly;
 #ifdef HAVE_JUMP_LABEL
 static atomic_t netstamp_needed_deferred;
+static atomic_t netstamp_wanted;
 static void netstamp_clear(struct work_struct *work)
 {
        int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
+       int wanted;
 
-       while (deferred--)
-               static_key_slow_dec(&netstamp_needed);
+       wanted = atomic_add_return(deferred, &netstamp_wanted);
+       if (wanted > 0)
+               static_key_enable(&netstamp_needed);
+       else
+               static_key_disable(&netstamp_needed);
 }
 static DECLARE_WORK(netstamp_work, netstamp_clear);
 #endif
 
 void net_enable_timestamp(void)
 {
+#ifdef HAVE_JUMP_LABEL
+       int wanted;
+
+       while (1) {
+               wanted = atomic_read(&netstamp_wanted);
+               if (wanted <= 0)
+                       break;
+               if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted + 1) == wanted)
+                       return;
+       }
+       atomic_inc(&netstamp_needed_deferred);
+       schedule_work(&netstamp_work);
+#else
        static_key_slow_inc(&netstamp_needed);
+#endif
 }
 EXPORT_SYMBOL(net_enable_timestamp);
 
 void net_disable_timestamp(void)
 {
 #ifdef HAVE_JUMP_LABEL
-       /* net_disable_timestamp() can be called from non process context */
-       atomic_inc(&netstamp_needed_deferred);
+       int wanted;
+
+       while (1) {
+               wanted = atomic_read(&netstamp_wanted);
+               if (wanted <= 1)
+                       break;
+               if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted - 1) == wanted)
+                       return;
+       }
+       atomic_dec(&netstamp_needed_deferred);
        schedule_work(&netstamp_work);
 #else
        static_key_slow_dec(&netstamp_needed);
@@ -2403,28 +2433,6 @@ void netif_schedule_queue(struct netdev_queue *txq)
 }
 EXPORT_SYMBOL(netif_schedule_queue);
 
-/**
- *     netif_wake_subqueue - allow sending packets on subqueue
- *     @dev: network device
- *     @queue_index: sub queue index
- *
- * Resume individual transmit queue of a device with multiple transmit queues.
- */
-void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
-{
-       struct netdev_queue *txq = netdev_get_tx_queue(dev, queue_index);
-
-       if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &txq->state)) {
-               struct Qdisc *q;
-
-               rcu_read_lock();
-               q = rcu_dereference(txq->qdisc);
-               __netif_schedule(q);
-               rcu_read_unlock();
-       }
-}
-EXPORT_SYMBOL(netif_wake_subqueue);
-
 void netif_tx_wake_queue(struct netdev_queue *dev_queue)
 {
        if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state)) {
@@ -2518,6 +2526,7 @@ u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
 
        if (dev->num_tc) {
                u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
+
                qoffset = dev->tc_to_txq[tc].offset;
                qcount = dev->tc_to_txq[tc].count;
        }
@@ -2654,9 +2663,10 @@ EXPORT_SYMBOL(skb_mac_gso_segment);
 static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
 {
        if (tx_path)
-               return skb->ip_summed != CHECKSUM_PARTIAL;
-       else
-               return skb->ip_summed == CHECKSUM_NONE;
+               return skb->ip_summed != CHECKSUM_PARTIAL &&
+                      skb->ip_summed != CHECKSUM_NONE;
+
+       return skb->ip_summed == CHECKSUM_NONE;
 }
 
 /**
@@ -2675,11 +2685,12 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
 struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
                                  netdev_features_t features, bool tx_path)
 {
+       struct sk_buff *segs;
+
        if (unlikely(skb_needs_check(skb, tx_path))) {
                int err;
 
-               skb_warn_bad_offload(skb);
-
+               /* We're going to init ->check field in TCP or UDP header */
                err = skb_cow_head(skb, 0);
                if (err < 0)
                        return ERR_PTR(err);
@@ -2707,7 +2718,12 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
        skb_reset_mac_header(skb);
        skb_reset_mac_len(skb);
 
-       return skb_mac_gso_segment(skb, features);
+       segs = skb_mac_gso_segment(skb, features);
+
+       if (unlikely(skb_needs_check(skb, tx_path)))
+               skb_warn_bad_offload(skb);
+
+       return segs;
 }
 EXPORT_SYMBOL(__skb_gso_segment);
 
@@ -2732,9 +2748,11 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_HIGHMEM
        int i;
+
        if (!(dev->features & NETIF_F_HIGHDMA)) {
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
                        if (PageHighMem(skb_frag_page(frag)))
                                return 1;
                }
@@ -2748,6 +2766,7 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
                        dma_addr_t addr = page_to_phys(skb_frag_page(frag));
+
                        if (!pdev->dma_mask || addr + PAGE_SIZE - 1 > *pdev->dma_mask)
                                return 1;
                }
@@ -3148,9 +3167,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
        if (!cl)
                return skb;
 
-       /* skb->tc_verd and qdisc_skb_cb(skb)->pkt_len were already set
-        * earlier by the caller.
-        */
+       /* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */
        qdisc_bstats_cpu_update(cl->q, skb);
 
        switch (tc_classify(skb, cl, &cl_res, false)) {
@@ -3225,6 +3242,7 @@ static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
        if (queue_index < 0 || skb->ooo_okay ||
            queue_index >= dev->real_num_tx_queues) {
                int new_index = get_xps_queue(dev, skb);
+
                if (new_index < 0)
                        new_index = skb_tx_hash(dev, skb);
 
@@ -3254,6 +3272,7 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,
 
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
+
                if (ops->ndo_select_queue)
                        queue_index = ops->ndo_select_queue(dev, skb, accel_priv,
                                                            __netdev_pick_tx);
@@ -3315,7 +3334,7 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 
        qdisc_pkt_len_init(skb);
 #ifdef CONFIG_NET_CLS_ACT
-       skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
+       skb->tc_at_ingress = 0;
 # ifdef CONFIG_NET_EGRESS
        if (static_key_false(&egress_needed)) {
                skb = sch_handle_egress(skb, &rc, dev);
@@ -3342,16 +3361,16 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
        }
 
        /* The device has no queue. Common case for software devices:
-          loopback, all the sorts of tunnels...
+        * loopback, all the sorts of tunnels...
 
-          Really, it is unlikely that netif_tx_lock protection is necessary
-          here.  (f.e. loopback and IP tunnels are clean ignoring statistics
-          counters.)
-          However, it is possible, that they rely on protection
-          made by us here.
+        * Really, it is unlikely that netif_tx_lock protection is necessary
+        * here.  (f.e. loopback and IP tunnels are clean ignoring statistics
+        * counters.)
+        * However, it is possible, that they rely on protection
+        * made by us here.
 
-          Check this and shot the lock. It is not prone from deadlocks.
-          Either shot noqueue qdisc, it is even simpler 8)
+        * Check this and shot the lock. It is not prone from deadlocks.
+        *Either shot noqueue qdisc, it is even simpler 8)
         */
        if (dev->flags & IFF_UP) {
                int cpu = smp_processor_id(); /* ok because BHs are off */
@@ -3413,16 +3432,20 @@ int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
 EXPORT_SYMBOL(dev_queue_xmit_accel);
 
 
-/*=======================================================================
                      Receiver routines
 =======================================================================*/
+/*************************************************************************
*                     Receiver routines
*************************************************************************/
 
 int netdev_max_backlog __read_mostly = 1000;
 EXPORT_SYMBOL(netdev_max_backlog);
 
 int netdev_tstamp_prequeue __read_mostly = 1;
 int netdev_budget __read_mostly = 300;
-int weight_p __read_mostly = 64;            /* old backlog weight */
+int weight_p __read_mostly = 64;           /* old backlog weight */
+int dev_weight_rx_bias __read_mostly = 1;  /* bias for backlog weight */
+int dev_weight_tx_bias __read_mostly = 1;  /* bias for output_queue quota */
+int dev_rx_weight __read_mostly = 64;
+int dev_tx_weight __read_mostly = 64;
 
 /* Called with irq disabled */
 static inline void ____napi_schedule(struct softnet_data *sd,
@@ -3779,6 +3802,7 @@ static int netif_rx_internal(struct sk_buff *skb)
 #endif
        {
                unsigned int qtail;
+
                ret = enqueue_to_backlog(skb, get_cpu(), &qtail);
                put_cpu();
        }
@@ -3838,6 +3862,7 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
 
                while (clist) {
                        struct sk_buff *skb = clist;
+
                        clist = clist->next;
 
                        WARN_ON(atomic_read(&skb->users));
@@ -3911,7 +3936,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
        }
 
        qdisc_skb_cb(skb)->pkt_len = skb->len;
-       skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
+       skb->tc_at_ingress = 1;
        qdisc_bstats_cpu_update(cl->q, skb);
 
        switch (tc_classify(skb, cl, &cl_res, false)) {
@@ -3976,9 +4001,7 @@ int netdev_rx_handler_register(struct net_device *dev,
                               rx_handler_func_t *rx_handler,
                               void *rx_handler_data)
 {
-       ASSERT_RTNL();
-
-       if (dev->rx_handler)
+       if (netdev_is_rx_handler_busy(dev))
                return -EBUSY;
 
        /* Note: rx_handler_data must be set before rx_handler */
@@ -4084,12 +4107,8 @@ another_round:
                        goto out;
        }
 
-#ifdef CONFIG_NET_CLS_ACT
-       if (skb->tc_verd & TC_NCLS) {
-               skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
-               goto ncls;
-       }
-#endif
+       if (skb_skip_tc_classify(skb))
+               goto skip_classify;
 
        if (pfmemalloc)
                goto skip_taps;
@@ -4117,10 +4136,8 @@ skip_taps:
                        goto out;
        }
 #endif
-#ifdef CONFIG_NET_CLS_ACT
-       skb->tc_verd = 0;
-ncls:
-#endif
+       skb_reset_tc(skb);
+skip_classify:
        if (pfmemalloc && !skb_pfmemalloc_protocol(skb))
                goto drop;
 
@@ -4521,6 +4538,11 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        if (&ptype->list == head)
                goto normal;
 
+       if (IS_ERR(pp) && PTR_ERR(pp) == -EINPROGRESS) {
+               ret = GRO_CONSUMED;
+               goto ok;
+       }
+
        same_flow = NAPI_GRO_CB(skb)->same_flow;
        ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED;
 
@@ -4616,6 +4638,7 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
        case GRO_MERGED_FREE:
                if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
                        skb_dst_drop(skb);
+                       secpath_reset(skb);
                        kmem_cache_free(skbuff_head_cache, skb);
                } else {
                        __kfree_skb(skb);
@@ -4624,6 +4647,7 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 
        case GRO_HELD:
        case GRO_MERGED:
+       case GRO_CONSUMED:
                break;
        }
 
@@ -4656,6 +4680,7 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
        skb->encapsulation = 0;
        skb_shinfo(skb)->gso_type = 0;
        skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
+       secpath_reset(skb);
 
        napi->skb = skb;
 }
@@ -4694,6 +4719,7 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi,
                break;
 
        case GRO_MERGED:
+       case GRO_CONSUMED:
                break;
        }
 
@@ -4830,7 +4856,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
                net_rps_action_and_irq_enable(sd);
        }
 
-       napi->weight = weight_p;
+       napi->weight = dev_rx_weight;
        while (again) {
                struct sk_buff *skb;
 
@@ -4885,6 +4911,39 @@ void __napi_schedule(struct napi_struct *n)
 }
 EXPORT_SYMBOL(__napi_schedule);
 
+/**
+ *     napi_schedule_prep - check if napi can be scheduled
+ *     @n: napi context
+ *
+ * Test if NAPI routine is already running, and if not mark
+ * it as running.  This is used as a condition variable
+ * insure only one NAPI poll instance runs.  We also make
+ * sure there is no pending NAPI disable.
+ */
+bool napi_schedule_prep(struct napi_struct *n)
+{
+       unsigned long val, new;
+
+       do {
+               val = READ_ONCE(n->state);
+               if (unlikely(val & NAPIF_STATE_DISABLE))
+                       return false;
+               new = val | NAPIF_STATE_SCHED;
+
+               /* Sets STATE_MISSED bit if STATE_SCHED was already set
+                * This was suggested by Alexander Duyck, as compiler
+                * emits better code than :
+                * if (val & NAPIF_STATE_SCHED)
+                *     new |= NAPIF_STATE_MISSED;
+                */
+               new |= (val & NAPIF_STATE_SCHED) / NAPIF_STATE_SCHED *
+                                                  NAPIF_STATE_MISSED;
+       } while (cmpxchg(&n->state, val, new) != val);
+
+       return !(val & NAPIF_STATE_SCHED);
+}
+EXPORT_SYMBOL(napi_schedule_prep);
+
 /**
  * __napi_schedule_irqoff - schedule for receive
  * @n: entry to schedule
@@ -4897,26 +4956,9 @@ void __napi_schedule_irqoff(struct napi_struct *n)
 }
 EXPORT_SYMBOL(__napi_schedule_irqoff);
 
-bool __napi_complete(struct napi_struct *n)
-{
-       BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
-
-       /* Some drivers call us directly, instead of calling
-        * napi_complete_done().
-        */
-       if (unlikely(test_bit(NAPI_STATE_IN_BUSY_POLL, &n->state)))
-               return false;
-
-       list_del_init(&n->poll_list);
-       smp_mb__before_atomic();
-       clear_bit(NAPI_STATE_SCHED, &n->state);
-       return true;
-}
-EXPORT_SYMBOL(__napi_complete);
-
 bool napi_complete_done(struct napi_struct *n, int work_done)
 {
-       unsigned long flags;
+       unsigned long flags, val, new;
 
        /*
         * 1) Don't let napi dequeue from the cpu poll list
@@ -4940,14 +4982,33 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
                else
                        napi_gro_flush(n, false);
        }
-       if (likely(list_empty(&n->poll_list))) {
-               WARN_ON_ONCE(!test_and_clear_bit(NAPI_STATE_SCHED, &n->state));
-       } else {
+       if (unlikely(!list_empty(&n->poll_list))) {
                /* If n->poll_list is not empty, we need to mask irqs */
                local_irq_save(flags);
-               __napi_complete(n);
+               list_del_init(&n->poll_list);
                local_irq_restore(flags);
        }
+
+       do {
+               val = READ_ONCE(n->state);
+
+               WARN_ON_ONCE(!(val & NAPIF_STATE_SCHED));
+
+               new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED);
+
+               /* If STATE_MISSED was set, leave STATE_SCHED set,
+                * because we will call napi->poll() one more time.
+                * This C code was suggested by Alexander Duyck to help gcc.
+                */
+               new |= (val & NAPIF_STATE_MISSED) / NAPIF_STATE_MISSED *
+                                                   NAPIF_STATE_SCHED;
+       } while (cmpxchg(&n->state, val, new) != val);
+
+       if (unlikely(val & NAPIF_STATE_MISSED)) {
+               __napi_schedule(n);
+               return false;
+       }
+
        return true;
 }
 EXPORT_SYMBOL(napi_complete_done);
@@ -4973,6 +5034,16 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock)
 {
        int rc;
 
+       /* Busy polling means there is a high chance device driver hard irq
+        * could not grab NAPI_STATE_SCHED, and that NAPI_STATE_MISSED was
+        * set in napi_schedule_prep().
+        * Since we are about to call napi->poll() once more, we can safely
+        * clear NAPI_STATE_MISSED.
+        *
+        * Note: x86 could use a single "lock and ..." instruction
+        * to perform these two clear_bit()
+        */
+       clear_bit(NAPI_STATE_MISSED, &napi->state);
        clear_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state);
 
        local_bh_disable();
@@ -4993,7 +5064,6 @@ bool sk_busy_loop(struct sock *sk, int nonblock)
 {
        unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0;
        int (*napi_poll)(struct napi_struct *napi, int budget);
-       int (*busy_poll)(struct napi_struct *dev);
        void *have_poll_lock = NULL;
        struct napi_struct *napi;
        int rc;
@@ -5008,17 +5078,10 @@ restart:
        if (!napi)
                goto out;
 
-       /* Note: ndo_busy_poll method is optional in linux-4.5 */
-       busy_poll = napi->dev->netdev_ops->ndo_busy_poll;
-
        preempt_disable();
        for (;;) {
                rc = 0;
                local_bh_disable();
-               if (busy_poll) {
-                       rc = busy_poll(napi);
-                       goto count;
-               }
                if (!napi_poll) {
                        unsigned long val = READ_ONCE(napi->state);
 
@@ -5043,9 +5106,6 @@ count:
                                        LINUX_MIB_BUSYPOLLRXPACKETS, rc);
                local_bh_enable();
 
-               if (rc == LL_FLUSH_FAILED)
-                       break; /* permanent failure */
-
                if (nonblock || !skb_queue_empty(&sk->sk_receive_queue) ||
                    busy_loop_timeout(end_time))
                        break;
@@ -5119,8 +5179,13 @@ static enum hrtimer_restart napi_watchdog(struct hrtimer *timer)
        struct napi_struct *napi;
 
        napi = container_of(timer, struct napi_struct, timer);
-       if (napi->gro_list)
-               napi_schedule(napi);
+
+       /* Note : we use a relaxed variant of napi_schedule_prep() not setting
+        * NAPI_STATE_MISSED, since we do not react to a device IRQ.
+        */
+       if (napi->gro_list && !napi_disable_pending(napi) &&
+           !test_and_set_bit(NAPI_STATE_SCHED, &napi->state))
+               __napi_schedule_irqoff(napi);
 
        return HRTIMER_NORESTART;
 }
@@ -5706,6 +5771,7 @@ static int netdev_adjacent_sysfs_add(struct net_device *dev,
                              struct list_head *dev_list)
 {
        char linkname[IFNAMSIZ+7];
+
        sprintf(linkname, dev_list == &dev->adj_list.upper ?
                "upper_%s" : "lower_%s", adj_dev->name);
        return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj),
@@ -5716,6 +5782,7 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev,
                               struct list_head *dev_list)
 {
        char linkname[IFNAMSIZ+7];
+
        sprintf(linkname, dev_list == &dev->adj_list.upper ?
                "upper_%s" : "lower_%s", name);
        sysfs_remove_link(&(dev->dev.kobj), linkname);
@@ -5985,6 +6052,7 @@ void netdev_upper_dev_unlink(struct net_device *dev,
                             struct net_device *upper_dev)
 {
        struct netdev_notifier_changeupper_info changeupper_info;
+
        ASSERT_RTNL();
 
        changeupper_info.upper_dev = upper_dev;
@@ -6151,50 +6219,6 @@ void netdev_lower_state_changed(struct net_device *lower_dev,
 }
 EXPORT_SYMBOL(netdev_lower_state_changed);
 
-int netdev_default_l2upper_neigh_construct(struct net_device *dev,
-                                          struct neighbour *n)
-{
-       struct net_device *lower_dev, *stop_dev;
-       struct list_head *iter;
-       int err;
-
-       netdev_for_each_lower_dev(dev, lower_dev, iter) {
-               if (!lower_dev->netdev_ops->ndo_neigh_construct)
-                       continue;
-               err = lower_dev->netdev_ops->ndo_neigh_construct(lower_dev, n);
-               if (err) {
-                       stop_dev = lower_dev;
-                       goto rollback;
-               }
-       }
-       return 0;
-
-rollback:
-       netdev_for_each_lower_dev(dev, lower_dev, iter) {
-               if (lower_dev == stop_dev)
-                       break;
-               if (!lower_dev->netdev_ops->ndo_neigh_destroy)
-                       continue;
-               lower_dev->netdev_ops->ndo_neigh_destroy(lower_dev, n);
-       }
-       return err;
-}
-EXPORT_SYMBOL_GPL(netdev_default_l2upper_neigh_construct);
-
-void netdev_default_l2upper_neigh_destroy(struct net_device *dev,
-                                         struct neighbour *n)
-{
-       struct net_device *lower_dev;
-       struct list_head *iter;
-
-       netdev_for_each_lower_dev(dev, lower_dev, iter) {
-               if (!lower_dev->netdev_ops->ndo_neigh_destroy)
-                       continue;
-               lower_dev->netdev_ops->ndo_neigh_destroy(lower_dev, n);
-       }
-}
-EXPORT_SYMBOL_GPL(netdev_default_l2upper_neigh_destroy);
-
 static void dev_change_rx_flags(struct net_device *dev, int flags)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
@@ -6447,8 +6471,8 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
        }
 
        /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
-          is important. Some (broken) drivers set IFF_PROMISC, when
-          IFF_ALLMULTI is requested not asking us and not reporting.
+        * is important. Some (broken) drivers set IFF_PROMISC, when
+        * IFF_ALLMULTI is requested not asking us and not reporting.
         */
        if ((flags ^ dev->gflags) & IFF_ALLMULTI) {
                int inc = (flags & IFF_ALLMULTI) ? 1 : -1;
@@ -6746,6 +6770,7 @@ EXPORT_SYMBOL(dev_change_xdp_fd);
 static int dev_new_index(struct net *net)
 {
        int ifindex = net->ifindex;
+
        for (;;) {
                if (++ifindex <= 0)
                        ifindex = 1;
@@ -6812,8 +6837,8 @@ static void rollback_registered_many(struct list_head *head)
 
 
                /* Notify protocols, that we are about to destroy
-                  this device. They should clean all the things.
-               */
+                * this device. They should clean all the things.
+                */
                call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
 
                if (!dev->rtnl_link_ops ||
@@ -6971,13 +6996,6 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
                features &= ~dev->gso_partial_features;
        }
 
-#ifdef CONFIG_NET_RX_BUSY_POLL
-       if (dev->netdev_ops->ndo_busy_poll)
-               features |= NETIF_F_BUSY_POLL;
-       else
-#endif
-               features &= ~NETIF_F_BUSY_POLL;
-
        return features;
 }
 
@@ -7166,6 +7184,7 @@ void netif_tx_stop_all_queues(struct net_device *dev)
 
        for (i = 0; i < dev->num_tx_queues; i++) {
                struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+
                netif_tx_stop_queue(txq);
        }
 }
@@ -7640,17 +7659,17 @@ void netdev_freemem(struct net_device *dev)
 }
 
 /**
- *     alloc_netdev_mqs - allocate network device
- *     @sizeof_priv:           size of private data to allocate space for
- *     @name:                  device name format string
- *     @name_assign_type:      origin of device name
- *     @setup:                 callback to initialize device
- *     @txqs:                  the number of TX subqueues to allocate
- *     @rxqs:                  the number of RX subqueues to allocate
- *
- *     Allocates a struct net_device with private data area for driver use
- *     and performs basic initialization.  Also allocates subqueue structs
- *     for each queue on the device.
+ * alloc_netdev_mqs - allocate network device
+ * @sizeof_priv: size of private data to allocate space for
+ * @name: device name format string
+ * @name_assign_type: origin of device name
+ * @setup: callback to initialize device
+ * @txqs: the number of TX subqueues to allocate
+ * @rxqs: the number of RX subqueues to allocate
+ *
+ * Allocates a struct net_device with private data area for driver use
+ * and performs basic initialization.  Also allocates subqueue structs
+ * for each queue on the device.
  */
 struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
                unsigned char name_assign_type,
@@ -7762,13 +7781,13 @@ free_dev:
 EXPORT_SYMBOL(alloc_netdev_mqs);
 
 /**
- *     free_netdev - free network device
- *     @dev: device
+ * free_netdev - free network device
+ * @dev: device
  *
- *     This function does the last stage of destroying an allocated device
- *     interface. The reference to the device object is released.
- *     If this is the last reference then it will be freed.
- *     Must be called in process context.
+ * This function does the last stage of destroying an allocated device
+ * interface. The reference to the device object is released. If this
+ * is the last reference then it will be freed.Must be called in process
+ * context.
  */
 void free_netdev(struct net_device *dev)
 {
@@ -7950,12 +7969,12 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        dev_shutdown(dev);
 
        /* Notify protocols, that we are about to destroy
-          this device. They should clean all the things.
-
-          Note that dev->reg_state stays at NETREG_REGISTERED.
-          This is wanted because this way 8021q and macvlan know
-          the device is just moving and can keep their slaves up.
-       */
+        * this device. They should clean all the things.
+        *
+        * Note that dev->reg_state stays at NETREG_REGISTERED.
+        * This is wanted because this way 8021q and macvlan know
+        * the device is just moving and can keep their slaves up.
+        */
        call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
        rcu_barrier();
        call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);