IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop()
[safe/jmp/linux-2.6] / drivers / net / ixp2000 / ixpdev.c
index 52c5a1c..7b70c66 100644 (file)
@@ -9,15 +9,13 @@
  * (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
-#include <asm/arch/uengine.h>
-#include <asm/mach-types.h>
+#include <asm/hardware/uengine.h>
 #include <asm/io.h>
 #include "ixp2400_rx.ucode"
 #include "ixp2400_tx.ucode"
@@ -75,9 +73,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;
@@ -109,44 +107,46 @@ static int ixpdev_rx(struct net_device *dev, int *budget)
                if (unlikely(!netif_running(nds[desc->channel])))
                        goto err;
 
-               skb = dev_alloc_skb(desc->pkt_length + 2);
+               skb = netdev_alloc_skb(dev, desc->pkt_length + 2);
                if (likely(skb != NULL)) {
-                       skb->dev = nds[desc->channel];
                        skb_reserve(skb, 2);
-                       eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+                       skb_copy_to_linear_data(skb, buf, desc->pkt_length);
                        skb_put(skb, desc->pkt_length);
-                       skb->protocol = eth_type_trans(skb, skb->dev);
+                       skb->protocol = eth_type_trans(skb, nds[desc->channel]);
 
-                       skb->dev->last_rx = jiffies;
+                       dev->last_rx = jiffies;
 
                        netif_receive_skb(skb);
                }
 
 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)
 {
-       /* @@@ Have to stop polling when nds[0] is administratively
-        * downed while we are polling.  */
+       struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
+       struct net_device *dev = ip->dev;
+       int rx;
+
+       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)
@@ -189,7 +189,7 @@ static void ixpdev_tx_complete(void)
        }
 }
 
-static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
 {
        u32 status;
 
@@ -201,9 +201,12 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * 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_test(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");
                }
@@ -224,7 +227,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static void ixpdev_poll_controller(struct net_device *dev)
 {
        disable_irq(IRQ_IXP2000_THDA0);
-       ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+       ixpdev_interrupt(IRQ_IXP2000_THDA0, dev);
        enable_irq(IRQ_IXP2000_THDA0);
 }
 #endif
@@ -234,11 +237,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,
-                                       SA_SHIRQ, "ixp2000_eth", nds);
+                                       IRQF_SHARED, "ixp2000_eth", nds);
                if (err) {
                        nds_open--;
+                       napi_disable(&ip->napi);
                        return err;
                }
 
@@ -256,6 +261,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) {
@@ -276,7 +282,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
@@ -284,9 +289,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;
 
@@ -299,10 +305,7 @@ int ixpdev_init(int __nds_count, struct net_device **__nds,
        int i;
        int err;
 
-       if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) {
-               static void __too_many_rx_or_tx_buffers(void);
-               __too_many_rx_or_tx_buffers();
-       }
+       BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192);
 
        printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);