Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[safe/jmp/linux-2.6] / drivers / net / gianfar.c
index 718cf77..4320a98 100644 (file)
@@ -44,8 +44,7 @@
  *  happen immediately, but will wait until either a set number
  *  of frames or amount of time have passed).  In NAPI, the
  *  interrupt handler will signal there is work to be done, and
- *  exit.  Without NAPI, the packet(s) will be handled
- *  immediately.  Both methods will start at the last known empty
+ *  exit. This method will start at the last known empty
  *  descriptor, and process every subsequent descriptor until there
  *  are none left with data (NAPI will stop after a set number of
  *  packets to give time to other tasks, but will eventually
 #include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
-#define SKB_ALLOC_TIMEOUT 1000000
 #undef BRIEF_GFAR_ERRORS
 #undef VERBOSE_GFAR_ERRORS
 
-#ifdef CONFIG_GFAR_NAPI
-#define RECEIVE(x) netif_receive_skb(x)
-#else
-#define RECEIVE(x) netif_rx(x)
-#endif
-
 const char gfar_driver_name[] = "Gianfar Ethernet";
 const char gfar_driver_version[] = "1.3";
 
 static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void gfar_reset_task(struct work_struct *work);
 static void gfar_timeout(struct net_device *dev);
 static int gfar_close(struct net_device *dev);
-struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
+struct sk_buff *gfar_new_skb(struct net_device *dev);
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb);
 static int gfar_set_mac_address(struct net_device *dev);
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id);
@@ -130,19 +125,17 @@ static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
 static void gfar_configure_serdes(struct net_device *dev);
-extern int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value);
-extern int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
-#ifdef CONFIG_GFAR_NAPI
 static int gfar_poll(struct napi_struct *napi, int budget);
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void gfar_netpoll(struct net_device *dev);
 #endif
 int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+static int gfar_clean_tx_ring(struct net_device *dev);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
 static void gfar_vlan_rx_register(struct net_device *netdev,
                                struct vlan_group *grp);
 void gfar_halt(struct net_device *dev);
+static void gfar_halt_nodisable(struct net_device *dev);
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
@@ -216,6 +209,8 @@ static int gfar_probe(struct platform_device *pdev)
 
        spin_lock_init(&priv->txlock);
        spin_lock_init(&priv->rxlock);
+       spin_lock_init(&priv->bflock);
+       INIT_WORK(&priv->reset_task, gfar_reset_task);
 
        platform_set_drvdata(pdev, dev);
 
@@ -260,9 +255,7 @@ static int gfar_probe(struct platform_device *pdev)
        dev->hard_start_xmit = gfar_start_xmit;
        dev->tx_timeout = gfar_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_GFAR_NAPI
        netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT);
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = gfar_netpoll;
 #endif
@@ -363,11 +356,7 @@ static int gfar_probe(struct platform_device *pdev)
 
        /* Even more device info helps when determining which kernel */
        /* provided which set of benchmarks. */
-#ifdef CONFIG_GFAR_NAPI
        printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
-#else
-       printk(KERN_INFO "%s: Running with NAPI disabled\n", dev->name);
-#endif
        printk(KERN_INFO "%s: %d/%d RX/TX BD ring size\n",
               dev->name, priv->rx_ring_size, priv->tx_ring_size);
 
@@ -393,6 +382,99 @@ static int gfar_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct gfar_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       u32 tempval;
+
+       int magic_packet = priv->wol_en &&
+               (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+       netif_device_detach(dev);
+
+       if (netif_running(dev)) {
+               spin_lock_irqsave(&priv->txlock, flags);
+               spin_lock(&priv->rxlock);
+
+               gfar_halt_nodisable(dev);
+
+               /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+               tempval = gfar_read(&priv->regs->maccfg1);
+
+               tempval &= ~MACCFG1_TX_EN;
+
+               if (!magic_packet)
+                       tempval &= ~MACCFG1_RX_EN;
+
+               gfar_write(&priv->regs->maccfg1, tempval);
+
+               spin_unlock(&priv->rxlock);
+               spin_unlock_irqrestore(&priv->txlock, flags);
+
+               napi_disable(&priv->napi);
+
+               if (magic_packet) {
+                       /* Enable interrupt on Magic Packet */
+                       gfar_write(&priv->regs->imask, IMASK_MAG);
+
+                       /* Enable Magic Packet mode */
+                       tempval = gfar_read(&priv->regs->maccfg2);
+                       tempval |= MACCFG2_MPEN;
+                       gfar_write(&priv->regs->maccfg2, tempval);
+               } else {
+                       phy_stop(priv->phydev);
+               }
+       }
+
+       return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct gfar_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       u32 tempval;
+       int magic_packet = priv->wol_en &&
+               (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+       if (!netif_running(dev)) {
+               netif_device_attach(dev);
+               return 0;
+       }
+
+       if (!magic_packet && priv->phydev)
+               phy_start(priv->phydev);
+
+       /* Disable Magic Packet mode, in case something
+        * else woke us up.
+        */
+
+       spin_lock_irqsave(&priv->txlock, flags);
+       spin_lock(&priv->rxlock);
+
+       tempval = gfar_read(&priv->regs->maccfg2);
+       tempval &= ~MACCFG2_MPEN;
+       gfar_write(&priv->regs->maccfg2, tempval);
+
+       gfar_start(dev);
+
+       spin_unlock(&priv->rxlock);
+       spin_unlock_irqrestore(&priv->txlock, flags);
+
+       netif_device_attach(dev);
+
+       napi_enable(&priv->napi);
+
+       return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
 
 /* Reads the controller's registers to determine what interface
  * connects it to the PHY.
@@ -476,24 +558,30 @@ static int init_phy(struct net_device *dev)
        return 0;
 }
 
+/*
+ * Initialize TBI PHY interface for communicating with the
+ * SERDES lynx PHY on the chip.  We communicate with this PHY
+ * through the MDIO bus on each controller, treating it as a
+ * "normal" PHY at the address found in the TBIPA register.  We assume
+ * that the TBIPA register is valid.  Either the MDIO bus code will set
+ * it to a value that doesn't conflict with other PHYs on the bus, or the
+ * value doesn't matter, as there are no other PHYs on the bus.
+ */
 static void gfar_configure_serdes(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
        struct gfar_mii __iomem *regs =
                        (void __iomem *)&priv->regs->gfar_mii_regs;
+       int tbipa = gfar_read(&priv->regs->tbipa);
 
-       /* Initialise TBI i/f to communicate with serdes (lynx phy) */
-
-       /* Single clk mode, mii mode off(for aerdes communication) */
-       gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+       /* Single clk mode, mii mode off(for serdes communication) */
+       gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT);
 
-       /* Supported pause and full-duplex, no half-duplex */
-       gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+       gfar_local_mdio_write(regs, tbipa, MII_ADVERTISE,
                        ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
                        ADVERTISE_1000XPSE_ASYM);
 
-       /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
-       gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+       gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE |
                        BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
 }
 
@@ -540,14 +628,11 @@ static void init_registers(struct net_device *dev)
 
        /* Initialize the Minimum Frame Length Register */
        gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
-
-       /* Assign the TBI an address which won't conflict with the PHYs */
-       gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
 }
 
 
 /* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
        struct gfar __iomem *regs = priv->regs;
@@ -570,6 +655,16 @@ void gfar_halt(struct net_device *dev)
                         (IEVENT_GRSC | IEVENT_GTSC)))
                        cpu_relax();
        }
+}
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       struct gfar __iomem *regs = priv->regs;
+       u32 tempval;
+
+       gfar_halt_nodisable(dev);
 
        /* Disable Rx and Tx */
        tempval = gfar_read(&regs->maccfg1);
@@ -632,6 +727,8 @@ static void free_skb_resources(struct gfar_private *priv)
                        dev_kfree_skb_any(priv->tx_skbuff[i]);
                        priv->tx_skbuff[i] = NULL;
                }
+
+               txbdp++;
        }
 
        kfree(priv->tx_skbuff);
@@ -783,14 +880,21 @@ int startup_gfar(struct net_device *dev)
 
        rxbdp = priv->rx_bd_base;
        for (i = 0; i < priv->rx_ring_size; i++) {
-               struct sk_buff *skb = NULL;
+               struct sk_buff *skb;
 
-               rxbdp->status = 0;
+               skb = gfar_new_skb(dev);
 
-               skb = gfar_new_skb(dev, rxbdp);
+               if (!skb) {
+                       printk(KERN_ERR "%s: Can't allocate RX buffers\n",
+                                       dev->name);
+
+                       goto err_rxalloc_fail;
+               }
 
                priv->rx_skbuff[i] = skb;
 
+               gfar_new_rxbdp(dev, rxbdp, skb);
+
                rxbdp++;
        }
 
@@ -916,6 +1020,7 @@ rx_irq_fail:
 tx_irq_fail:
        free_irq(priv->interruptError, dev);
 err_irq_fail:
+err_rxalloc_fail:
 rx_skb_fail:
        free_skb_resources(priv);
 tx_skb_fail:
@@ -932,14 +1037,10 @@ tx_skb_fail:
 /* Returns 0 for success. */
 static int gfar_enet_open(struct net_device *dev)
 {
-#ifdef CONFIG_GFAR_NAPI
        struct gfar_private *priv = netdev_priv(dev);
-#endif
        int err;
 
-#ifdef CONFIG_GFAR_NAPI
        napi_enable(&priv->napi);
-#endif
 
        /* Initialize a bunch of registers */
        init_registers(dev);
@@ -949,17 +1050,13 @@ static int gfar_enet_open(struct net_device *dev)
        err = init_phy(dev);
 
        if(err) {
-#ifdef CONFIG_GFAR_NAPI
                napi_disable(&priv->napi);
-#endif
                return err;
        }
 
        err = startup_gfar(dev);
        if (err) {
-#ifdef CONFIG_GFAR_NAPI
                napi_disable(&priv->napi);
-#endif
                return err;
        }
 
@@ -1115,10 +1212,9 @@ static int gfar_close(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
 
-#ifdef CONFIG_GFAR_NAPI
        napi_disable(&priv->napi);
-#endif
 
+       cancel_work_sync(&priv->reset_task);
        stop_gfar(dev);
 
        /* Disconnect from the PHY */
@@ -1131,7 +1227,7 @@ static int gfar_close(struct net_device *dev)
 }
 
 /* Changes the mac address if the controller is not running. */
-int gfar_set_mac_address(struct net_device *dev)
+static int gfar_set_mac_address(struct net_device *dev)
 {
        gfar_set_mac_for_addr(dev, 0, dev->dev_addr);
 
@@ -1185,7 +1281,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
        int frame_size = new_mtu + ETH_HLEN;
 
        if (priv->vlan_enable)
-               frame_size += VLAN_ETH_HLEN;
+               frame_size += VLAN_HLEN;
 
        if (gfar_uses_fcb(priv))
                frame_size += GMAC_FCB_LEN;
@@ -1233,34 +1329,40 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-/* gfar_timeout gets called when a packet has not been
+/* gfar_reset_task gets scheduled when a packet has not been
  * transmitted after a set amount of time.
  * For now, assume that clearing out all the structures, and
- * starting over will fix the problem. */
-static void gfar_timeout(struct net_device *dev)
+ * starting over will fix the problem.
+ */
+static void gfar_reset_task(struct work_struct *work)
 {
-       dev->stats.tx_errors++;
+       struct gfar_private *priv = container_of(work, struct gfar_private,
+                       reset_task);
+       struct net_device *dev = priv->dev;
 
        if (dev->flags & IFF_UP) {
                stop_gfar(dev);
                startup_gfar(dev);
        }
 
-       netif_schedule(dev);
+       netif_tx_schedule_all(dev);
 }
 
-/* Interrupt Handler for Transmit complete */
-static irqreturn_t gfar_transmit(int irq, void *dev_id)
+static void gfar_timeout(struct net_device *dev)
 {
-       struct net_device *dev = (struct net_device *) dev_id;
        struct gfar_private *priv = netdev_priv(dev);
-       struct txbd8 *bdp;
 
-       /* Clear IEVENT */
-       gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
+       dev->stats.tx_errors++;
+       schedule_work(&priv->reset_task);
+}
+
+/* Interrupt Handler for Transmit complete */
+static int gfar_clean_tx_ring(struct net_device *dev)
+{
+       struct txbd8 *bdp;
+       struct gfar_private *priv = netdev_priv(dev);
+       int howmany = 0;
 
-       /* Lock priv */
-       spin_lock(&priv->txlock);
        bdp = priv->dirty_tx;
        while ((bdp->status & TXBD_READY) == 0) {
                /* If dirty_tx and cur_tx are the same, then either the */
@@ -1269,7 +1371,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
                if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
                        break;
 
-               dev->stats.tx_packets++;
+               howmany++;
 
                /* Deferred means some collisions occurred during transmit, */
                /* but we eventually sent the packet. */
@@ -1278,11 +1380,15 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
 
                /* Free the sk buffer associated with this TxBD */
                dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
+
                priv->tx_skbuff[priv->skb_dirtytx] = NULL;
                priv->skb_dirtytx =
                    (priv->skb_dirtytx +
                     1) & TX_RING_MOD_MASK(priv->tx_ring_size);
 
+               /* Clean BD length for empty detection */
+               bdp->length = 0;
+
                /* update bdp to point at next bd in the ring (wrapping if necessary) */
                if (bdp->status & TXBD_WRAP)
                        bdp = priv->tx_bd_base;
@@ -1297,31 +1403,69 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
                        netif_wake_queue(dev);
        } /* while ((bdp->status & TXBD_READY) == 0) */
 
+       dev->stats.tx_packets += howmany;
+
+       return howmany;
+}
+
+/* Interrupt Handler for Transmit complete */
+static irqreturn_t gfar_transmit(int irq, void *dev_id)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct gfar_private *priv = netdev_priv(dev);
+
+       /* Clear IEVENT */
+       gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
+
+       /* Lock priv */
+       spin_lock(&priv->txlock);
+
+       gfar_clean_tx_ring(dev);
+
        /* If we are coalescing the interrupts, reset the timer */
        /* Otherwise, clear it */
-       if (priv->txcoalescing)
+       if (likely(priv->txcoalescing)) {
+               gfar_write(&priv->regs->txic, 0);
                gfar_write(&priv->regs->txic,
                           mk_ic_value(priv->txcount, priv->txtime));
-       else
-               gfar_write(&priv->regs->txic, 0);
+       }
 
        spin_unlock(&priv->txlock);
 
        return IRQ_HANDLED;
 }
 
-struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       u32 * status_len = (u32 *)bdp;
+       u16 flags;
+
+       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
+                       priv->rx_buffer_size, DMA_FROM_DEVICE);
+
+       flags = RXBD_EMPTY | RXBD_INTERRUPT;
+
+       if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
+               flags |= RXBD_WRAP;
+
+       eieio();
+
+       *status_len = (u32)flags << 16;
+}
+
+
+struct sk_buff * gfar_new_skb(struct net_device *dev)
 {
        unsigned int alignamount;
        struct gfar_private *priv = netdev_priv(dev);
        struct sk_buff *skb = NULL;
-       unsigned int timeout = SKB_ALLOC_TIMEOUT;
 
        /* We have to allocate the skb, so keep trying till we succeed */
-       while ((!skb) && timeout--)
-               skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
+       skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
-       if (NULL == skb)
+       if (!skb)
                return NULL;
 
        alignamount = RXBUF_ALIGNMENT -
@@ -1332,15 +1476,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
         */
        skb_reserve(skb, alignamount);
 
-       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
-                       priv->rx_buffer_size, DMA_FROM_DEVICE);
-
-       bdp->length = 0;
-
-       /* Mark the buffer empty */
-       eieio();
-       bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
-
        return skb;
 }
 
@@ -1386,21 +1521,16 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
        struct gfar_private *priv = netdev_priv(dev);
-#ifdef CONFIG_GFAR_NAPI
        u32 tempval;
-#else
-       unsigned long flags;
-#endif
-
-       /* Clear IEVENT, so rx interrupt isn't called again
-        * because of this interrupt */
-       gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
 
        /* support NAPI */
-#ifdef CONFIG_GFAR_NAPI
+       /* Clear IEVENT, so interrupts aren't called again
+        * because of the packets that have already arrived */
+       gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
+
        if (netif_rx_schedule_prep(dev, &priv->napi)) {
                tempval = gfar_read(&priv->regs->imask);
-               tempval &= IMASK_RX_DISABLED;
+               tempval &= IMASK_RTX_DISABLED;
                gfar_write(&priv->regs->imask, tempval);
 
                __netif_rx_schedule(dev, &priv->napi);
@@ -1410,35 +1540,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
                                dev->name, gfar_read(&priv->regs->ievent),
                                gfar_read(&priv->regs->imask));
        }
-#else
-
-       spin_lock_irqsave(&priv->rxlock, flags);
-       gfar_clean_rx_ring(dev, priv->rx_ring_size);
-
-       /* If we are coalescing interrupts, update the timer */
-       /* Otherwise, clear it */
-       if (priv->rxcoalescing)
-               gfar_write(&priv->regs->rxic,
-                          mk_ic_value(priv->rxcount, priv->rxtime));
-       else
-               gfar_write(&priv->regs->rxic, 0);
-
-       spin_unlock_irqrestore(&priv->rxlock, flags);
-#endif
 
        return IRQ_HANDLED;
 }
 
-static inline int gfar_rx_vlan(struct sk_buff *skb,
-               struct vlan_group *vlgrp, unsigned short vlctl)
-{
-#ifdef CONFIG_GFAR_NAPI
-       return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl);
-#else
-       return vlan_hwaccel_rx(skb, vlgrp, vlctl);
-#endif
-}
-
 static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
 {
        /* If valid headers were found, and valid sums
@@ -1495,10 +1600,11 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
                skb->protocol = eth_type_trans(skb, dev);
 
                /* Send the packet up the stack */
-               if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
-                       ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
-               else
-                       ret = RECEIVE(skb);
+               if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN))) {
+                       ret = vlan_hwaccel_receive_skb(skb, priv->vlgrp,
+                                                      fcb->vlctl);
+               } else
+                       ret = netif_receive_skb(skb);
 
                if (NET_RX_DROP == ret)
                        priv->extra_stats.kernel_dropped++;
@@ -1523,12 +1629,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
        bdp = priv->cur_rx;
 
        while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+               struct sk_buff *newskb;
                rmb();
+
+               /* Add another skb for the future */
+               newskb = gfar_new_skb(dev);
+
                skb = priv->rx_skbuff[priv->skb_currx];
 
-               if (!(bdp->status &
-                     (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET
-                      | RXBD_CRCERR | RXBD_OVERRUN | RXBD_TRUNCATED))) {
+               /* We drop the frame if we failed to allocate a new buffer */
+               if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
+                                bdp->status & RXBD_ERR)) {
+                       count_errors(bdp->status, dev);
+
+                       if (unlikely(!newskb))
+                               newskb = skb;
+
+                       if (skb) {
+                               dma_unmap_single(&priv->dev->dev,
+                                               bdp->bufPtr,
+                                               priv->rx_buffer_size,
+                                               DMA_FROM_DEVICE);
+
+                               dev_kfree_skb_any(skb);
+                       }
+               } else {
                        /* Increment the number of packets */
                        dev->stats.rx_packets++;
                        howmany++;
@@ -1539,23 +1664,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
                        gfar_process_frame(dev, skb, pkt_len);
 
                        dev->stats.rx_bytes += pkt_len;
-               } else {
-                       count_errors(bdp->status, dev);
-
-                       if (skb)
-                               dev_kfree_skb_any(skb);
-
-                       priv->rx_skbuff[priv->skb_currx] = NULL;
                }
 
                dev->last_rx = jiffies;
 
-               /* Clear the status flags for this buffer */
-               bdp->status &= ~RXBD_STATS;
+               priv->rx_skbuff[priv->skb_currx] = newskb;
 
-               /* Add another skb for the future */
-               skb = gfar_new_skb(dev, bdp);
-               priv->rx_skbuff[priv->skb_currx] = skb;
+               /* Setup the new bdp */
+               gfar_new_rxbdp(dev, bdp, newskb);
 
                /* Update to the next pointer */
                if (bdp->status & RXBD_WRAP)
@@ -1565,9 +1681,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
 
                /* update to point at the next skb */
                priv->skb_currx =
-                   (priv->skb_currx +
-                    1) & RX_RING_MOD_MASK(priv->rx_ring_size);
-
+                   (priv->skb_currx + 1) &
+                   RX_RING_MOD_MASK(priv->rx_ring_size);
        }
 
        /* Update the current rxbd pointer to be the next one */
@@ -1576,12 +1691,18 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
        return howmany;
 }
 
-#ifdef CONFIG_GFAR_NAPI
 static int gfar_poll(struct napi_struct *napi, int budget)
 {
        struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
        struct net_device *dev = priv->dev;
        int howmany;
+       unsigned long flags;
+
+       /* If we fail to get the lock, don't bother with the TX BDs */
+       if (spin_trylock_irqsave(&priv->txlock, flags)) {
+               gfar_clean_tx_ring(dev);
+               spin_unlock_irqrestore(&priv->txlock, flags);
+       }
 
        howmany = gfar_clean_rx_ring(dev, budget);
 
@@ -1595,16 +1716,15 @@ static int gfar_poll(struct napi_struct *napi, int budget)
 
                /* If we are coalescing interrupts, update the timer */
                /* Otherwise, clear it */
-               if (priv->rxcoalescing)
+               if (likely(priv->rxcoalescing)) {
+                       gfar_write(&priv->regs->rxic, 0);
                        gfar_write(&priv->regs->rxic,
                                   mk_ic_value(priv->rxcount, priv->rxtime));
-               else
-                       gfar_write(&priv->regs->rxic, 0);
+               }
        }
 
        return howmany;
 }
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /*
@@ -1724,7 +1844,6 @@ static void adjust_link(struct net_device *dev)
                if (!priv->oldlink) {
                        new_state = 1;
                        priv->oldlink = 1;
-                       netif_schedule(dev);
                }
        } else if (priv->oldlink) {
                new_state = 1;
@@ -1909,7 +2028,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        u32 events = gfar_read(&priv->regs->ievent);
 
        /* Clear IEVENT */
-       gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+       gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+       /* Magic Packet is not an error. */
+       if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+           (events & IEVENT_MAG))
+               events &= ~IEVENT_MAG;
 
        /* Hmm... */
        if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1943,11 +2067,6 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
 
                gfar_receive(irq, dev_id);
 
-#ifndef CONFIG_GFAR_NAPI
-               /* Clear the halt bit in RSTAT */
-               gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
-#endif
-
                if (netif_msg_rx_err(priv))
                        printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
                               dev->name, gfar_read(&priv->regs->rstat));
@@ -1975,12 +2094,18 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:fsl-gianfar");
+
 /* Structure for a device driver */
 static struct platform_driver gfar_driver = {
        .probe = gfar_probe,
        .remove = gfar_remove,
+       .suspend = gfar_suspend,
+       .resume = gfar_resume,
        .driver = {
                .name = "fsl-gianfar",
+               .owner = THIS_MODULE,
        },
 };