[NET]: Make NAPI polling independent of struct net_device objects.
[linux-3.10.git] / drivers / net / ixp2000 / ixpdev.c
index d9ce1ae..6c0dd49 100644 (file)
@@ -74,9 +74,9 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-static int ixpdev_rx(struct net_device *dev, int *budget)
+static int ixpdev_rx(struct net_device *dev, int processed, int budget)
 {
-       while (*budget > 0) {
+       while (processed < budget) {
                struct ixpdev_rx_desc *desc;
                struct sk_buff *skb;
                void *buf;
@@ -122,29 +122,34 @@ static int ixpdev_rx(struct net_device *dev, int *budget)
 
 err:
                ixp2000_reg_write(RING_RX_PENDING, _desc);
-               dev->quota--;
-               (*budget)--;
+               processed++;
        }
 
-       return 1;
+       return processed;
 }
 
 /* dev always points to nds[0].  */
-static int ixpdev_poll(struct net_device *dev, int *budget)
+static int ixpdev_poll(struct napi_struct *napi, int budget)
 {
+       struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
+       struct net_device *dev = ip->dev;
+       int rx;
+
        /* @@@ Have to stop polling when nds[0] is administratively
         * downed while we are polling.  */
+       rx = 0;
        do {
                ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
 
-               if (ixpdev_rx(dev, budget))
-                       return 1;
+               rx = ixpdev_rx(dev, rx, budget);
+               if (rx >= budget)
+                       break;
        } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
 
-       netif_rx_complete(dev);
+       netif_rx_complete(dev, napi);
        ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
 
-       return 0;
+       return rx;
 }
 
 static void ixpdev_tx_complete(void)
@@ -199,9 +204,12 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
         * Any of the eight receive units signaled RX?
         */
        if (status & 0x00ff) {
+               struct net_device *dev = nds[0];
+               struct ixpdev_priv *ip = netdev_priv(dev);
+
                ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
-               if (likely(__netif_rx_schedule_prep(nds[0]))) {
-                       __netif_rx_schedule(nds[0]);
+               if (likely(napi_schedule_prep(&ip->napi))) {
+                       __netif_rx_schedule(dev, &ip->napi);
                } else {
                        printk(KERN_CRIT "ixp2000: irq while polling!!\n");
                }
@@ -232,11 +240,13 @@ static int ixpdev_open(struct net_device *dev)
        struct ixpdev_priv *ip = netdev_priv(dev);
        int err;
 
+       napi_enable(&ip->napi);
        if (!nds_open++) {
                err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
                                        IRQF_SHARED, "ixp2000_eth", nds);
                if (err) {
                        nds_open--;
+                       napi_disable(&ip->napi);
                        return err;
                }
 
@@ -254,6 +264,7 @@ static int ixpdev_close(struct net_device *dev)
        struct ixpdev_priv *ip = netdev_priv(dev);
 
        netif_stop_queue(dev);
+       napi_disable(&ip->napi);
        set_port_admin_status(ip->channel, 0);
 
        if (!--nds_open) {
@@ -274,7 +285,6 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
                return NULL;
 
        dev->hard_start_xmit = ixpdev_xmit;
-       dev->poll = ixpdev_poll;
        dev->open = ixpdev_open;
        dev->stop = ixpdev_close;
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -282,9 +292,10 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
 #endif
 
        dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-       dev->weight = 64;
 
        ip = netdev_priv(dev);
+       ip->dev = dev;
+       netif_napi_add(dev, &ip->napi, ixpdev_poll, 64);
        ip->channel = channel;
        ip->tx_queue_entries = 0;