netpoll: Don't drop all received packets.
[firefly-linux-kernel-4.4.55.git] / net / core / netpoll.c
index a664f7829a6d16db4579789ca5b8c40654cc78d7..793dc04d2f190748b3e4f25e870d035c349d4842 100644 (file)
@@ -51,8 +51,6 @@ static atomic_t trapped;
 DEFINE_STATIC_SRCU(netpoll_srcu);
 
 #define USEC_PER_POLL  50
-#define NETPOLL_RX_ENABLED  1
-#define NETPOLL_RX_DROP     2
 
 #define MAX_SKB_SIZE                                                   \
        (sizeof(struct ethhdr) +                                        \
@@ -144,8 +142,7 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
  * network adapter, forcing superfluous retries and possibly timeouts.
  * Thus, we set our budget to greater than 1.
  */
-static int poll_one_napi(struct netpoll_info *npinfo,
-                        struct napi_struct *napi, int budget)
+static int poll_one_napi(struct napi_struct *napi, int budget)
 {
        int work;
 
@@ -156,34 +153,26 @@ static int poll_one_napi(struct netpoll_info *npinfo,
        if (!test_bit(NAPI_STATE_SCHED, &napi->state))
                return budget;
 
-       npinfo->rx_flags |= NETPOLL_RX_DROP;
-       atomic_inc(&trapped);
        set_bit(NAPI_STATE_NPSVC, &napi->state);
 
        work = napi->poll(napi, budget);
+       WARN_ONCE(work > budget, "%pF exceeded budget in poll\n", napi->poll);
        trace_napi_poll(napi);
 
        clear_bit(NAPI_STATE_NPSVC, &napi->state);
-       atomic_dec(&trapped);
-       npinfo->rx_flags &= ~NETPOLL_RX_DROP;
 
        return budget - work;
 }
 
-static void poll_napi(struct net_device *dev)
+static void poll_napi(struct net_device *dev, int budget)
 {
        struct napi_struct *napi;
-       int budget = 16;
 
        list_for_each_entry(napi, &dev->napi_list, dev_list) {
                if (napi->poll_owner != smp_processor_id() &&
                    spin_trylock(&napi->poll_lock)) {
-                       budget = poll_one_napi(rcu_dereference_bh(dev->npinfo),
-                                              napi, budget);
+                       budget = poll_one_napi(napi, budget);
                        spin_unlock(&napi->poll_lock);
-
-                       if (!budget)
-                               break;
                }
        }
 }
@@ -202,6 +191,8 @@ static void netpoll_poll_dev(struct net_device *dev)
 {
        const struct net_device_ops *ops;
        struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);
+       bool rx_processing = netpoll_rx_processing(ni);
+       int budget = rx_processing? 16 : 0;
 
        /* Don't do any rx activity if the dev_lock mutex is held
         * the dev_open/close paths use this to block netpoll activity
@@ -215,6 +206,9 @@ static void netpoll_poll_dev(struct net_device *dev)
                return;
        }
 
+       if (rx_processing)
+               atomic_inc(&trapped);
+
        ops = dev->netdev_ops;
        if (!ops->ndo_poll_controller) {
                up(&ni->dev_lock);
@@ -224,7 +218,10 @@ static void netpoll_poll_dev(struct net_device *dev)
        /* Process pending work on NIC */
        ops->ndo_poll_controller(dev);
 
-       poll_napi(dev);
+       poll_napi(dev, budget);
+
+       if (rx_processing)
+               atomic_dec(&trapped);
 
        up(&ni->dev_lock);
 
@@ -540,7 +537,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
        int hlen, tlen;
        int hits = 0, proto;
 
-       if (list_empty(&npinfo->rx_np))
+       if (!netpoll_rx_processing(npinfo))
                return;
 
        /* Before checking the packet, we do some early
@@ -772,7 +769,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
        struct netpoll *np, *tmp;
        uint16_t source;
 
-       if (list_empty(&npinfo->rx_np))
+       if (!netpoll_rx_processing(npinfo))
                goto out;
 
        if (skb->dev->type != ARPHRD_ETHER)
@@ -1052,7 +1049,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
                        goto out;
                }
 
-               npinfo->rx_flags = 0;
                INIT_LIST_HEAD(&npinfo->rx_np);
 
                spin_lock_init(&npinfo->rx_lock);
@@ -1078,7 +1074,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
 
        if (np->rx_skb_hook) {
                spin_lock_irqsave(&npinfo->rx_lock, flags);
-               npinfo->rx_flags |= NETPOLL_RX_ENABLED;
                list_add_tail(&np->rx, &npinfo->rx_np);
                spin_unlock_irqrestore(&npinfo->rx_lock, flags);
        }
@@ -1260,8 +1255,6 @@ void __netpoll_cleanup(struct netpoll *np)
        if (!list_empty(&npinfo->rx_np)) {
                spin_lock_irqsave(&npinfo->rx_lock, flags);
                list_del(&np->rx);
-               if (list_empty(&npinfo->rx_np))
-                       npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
                spin_unlock_irqrestore(&npinfo->rx_lock, flags);
        }