FS_ENET: Add polling support
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / net / fs_enet / fs_enet-main.c
index a4a2a0e..dcbe83c 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
  *
- * Copyright (c) 2003 Intracom S.A. 
+ * Copyright (c) 2003 Intracom S.A.
  *  by Pantelis Antoniou <panto@intracom.gr>
- * 
- * 2005 (c) MontaVista Software, Inc. 
+ *
+ * 2005 (c) MontaVista Software, Inc.
  * Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
  * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
  *
- * This file is licensed under the terms of the GNU General Public License 
- * version 2. This program is licensed "as is" without any warranty of any 
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
  * kind, whether express or implied.
  */
 
@@ -39,8 +39,6 @@
 
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
-
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
@@ -61,6 +59,9 @@ module_param(fs_enet_debug, int, 0);
 MODULE_PARM_DESC(fs_enet_debug,
                 "Freescale bitmapped debugging message enable value");
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void fs_enet_netpoll(struct net_device *dev);
+#endif
 
 static void fs_set_multicast_list(struct net_device *dev)
 {
@@ -70,18 +71,16 @@ static void fs_set_multicast_list(struct net_device *dev)
 }
 
 /* NAPI receive function */
-static int fs_enet_rx_napi(struct net_device *dev, int *budget)
+static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
 {
-       struct fs_enet_private *fep = netdev_priv(dev);
+       struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
+       struct net_device *dev = to_net_dev(fep->dev);
        const struct fs_platform_info *fpi = fep->fpi;
        cbd_t *bdp;
        struct sk_buff *skb, *skbn, *skbt;
        int received = 0;
        u16 pkt_len, sc;
        int curidx;
-       int rx_work_limit = 0;  /* pacify gcc */
-
-       rx_work_limit = min(dev->quota, *budget);
 
        if (!netif_running(dev))
                return 0;
@@ -96,7 +95,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
        (*fep->ops->napi_clear_rx_event)(dev);
 
        while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
-
                curidx = bdp - fep->rx_bd_base;
 
                /*
@@ -109,7 +107,7 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
                               dev->name);
 
                /*
-                * Check for errors. 
+                * Check for errors.
                 */
                if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
                          BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
@@ -136,11 +134,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
                        skbn = skb;
 
                } else {
-
-                       /* napi, got packet but no quota */
-                       if (--rx_work_limit < 0)
-                               break;
-
                        skb = fep->rx_skbuff[curidx];
 
                        dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
@@ -191,7 +184,7 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
                CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
 
                /*
-                * Update BD pointer to next entry. 
+                * Update BD pointer to next entry.
                 */
                if ((sc & BD_ENET_RX_WRAP) == 0)
                        bdp++;
@@ -199,22 +192,19 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
                        bdp = fep->rx_bd_base;
 
                (*fep->ops->rx_bd_done)(dev);
+
+               if (received >= budget)
+                       break;
        }
 
        fep->cur_rx = bdp;
 
-       dev->quota -= received;
-       *budget -= received;
-
-       if (rx_work_limit < 0)
-               return 1;       /* not done */
-
-       /* done */
-       netif_rx_complete(dev);
-
-       (*fep->ops->napi_enable_rx)(dev);
-
-       return 0;
+       if (received >= budget) {
+               /* done */
+               netif_rx_complete(dev, napi);
+               (*fep->ops->napi_enable_rx)(dev);
+       }
+       return received;
 }
 
 /* non NAPI receive function */
@@ -247,7 +237,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
                               dev->name);
 
                /*
-                * Check for errors. 
+                * Check for errors.
                 */
                if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
                          BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
@@ -325,7 +315,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
                CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
 
                /*
-                * Update BD pointer to next entry. 
+                * Update BD pointer to next entry.
                 */
                if ((sc & BD_ENET_RX_WRAP) == 0)
                        bdp++;
@@ -348,7 +338,7 @@ static void fs_enet_tx(struct net_device *dev)
        int dirtyidx, do_wake, do_restart;
        u16 sc;
 
-       spin_lock(&fep->lock);
+       spin_lock(&fep->tx_lock);
        bdp = fep->dirty_tx;
 
        do_wake = do_restart = 0;
@@ -362,7 +352,7 @@ static void fs_enet_tx(struct net_device *dev)
                skb = fep->tx_skbuff[dirtyidx];
 
                /*
-                * Check for errors. 
+                * Check for errors.
                 */
                if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
                          BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
@@ -402,13 +392,13 @@ static void fs_enet_tx(struct net_device *dev)
                                skb->len, DMA_TO_DEVICE);
 
                /*
-                * Free the sk buffer associated with this last transmit. 
+                * Free the sk buffer associated with this last transmit.
                 */
                dev_kfree_skb_irq(skb);
                fep->tx_skbuff[dirtyidx] = NULL;
 
                /*
-                * Update pointer to next buffer descriptor to be transmitted. 
+                * Update pointer to next buffer descriptor to be transmitted.
                 */
                if ((sc & BD_ENET_TX_WRAP) == 0)
                        bdp++;
@@ -428,7 +418,7 @@ static void fs_enet_tx(struct net_device *dev)
        if (do_restart)
                (*fep->ops->tx_restart)(dev);
 
-       spin_unlock(&fep->lock);
+       spin_unlock(&fep->tx_lock);
 
        if (do_wake)
                netif_wake_queue(dev);
@@ -470,7 +460,7 @@ fs_enet_interrupt(int irq, void *dev_id)
                        if (!fpi->use_napi)
                                fs_enet_rx_non_napi(dev);
                        else {
-                               napi_ok = netif_rx_schedule_prep(dev);
+                               napi_ok = napi_schedule_prep(&fep->napi);
 
                                (*fep->ops->napi_disable_rx)(dev);
                                (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
@@ -478,7 +468,7 @@ fs_enet_interrupt(int irq, void *dev_id)
                                /* NOTE: it is possible for FCCs in NAPI mode    */
                                /* to submit a spurious interrupt while in poll  */
                                if (napi_ok)
-                                       __netif_rx_schedule(dev);
+                                       __netif_rx_schedule(dev, &fep->napi);
                        }
                }
 
@@ -504,7 +494,7 @@ void fs_init_bds(struct net_device *dev)
        fep->cur_rx = fep->rx_bd_base;
 
        /*
-        * Initialize the receive buffer descriptors. 
+        * Initialize the receive buffer descriptors.
         */
        for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
                skb = dev_alloc_skb(ENET_RX_FRSIZE);
@@ -524,7 +514,7 @@ void fs_init_bds(struct net_device *dev)
                        ((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
        }
        /*
-        * if we failed, fillup remainder 
+        * if we failed, fillup remainder
         */
        for (; i < fep->rx_ring; i++, bdp++) {
                fep->rx_skbuff[i] = NULL;
@@ -532,7 +522,7 @@ void fs_init_bds(struct net_device *dev)
        }
 
        /*
-        * ...and the same for transmit.  
+        * ...and the same for transmit.
         */
        for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
                fep->tx_skbuff[i] = NULL;
@@ -550,7 +540,7 @@ void fs_cleanup_bds(struct net_device *dev)
        int i;
 
        /*
-        * Reset SKB transmit buffers.  
+        * Reset SKB transmit buffers.
         */
        for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
                if ((skb = fep->tx_skbuff[i]) == NULL)
@@ -565,7 +555,7 @@ void fs_cleanup_bds(struct net_device *dev)
        }
 
        /*
-        * Reset SKB receive buffers 
+        * Reset SKB receive buffers
         */
        for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
                if ((skb = fep->rx_skbuff[i]) == NULL)
@@ -595,7 +585,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&fep->tx_lock, flags);
 
        /*
-        * Fill in a Tx ring entry 
+        * Fill in a Tx ring entry
         */
        bdp = fep->cur_tx;
 
@@ -614,19 +604,19 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        curidx = bdp - fep->tx_bd_base;
        /*
-        * Clear all of the status flags. 
+        * Clear all of the status flags.
         */
        CBDC_SC(bdp, BD_ENET_TX_STATS);
 
        /*
-        * Save skb pointer. 
+        * Save skb pointer.
         */
        fep->tx_skbuff[curidx] = skb;
 
        fep->stats.tx_bytes += skb->len;
 
        /*
-        * Push the data cache so the CPM does not get stale memory data. 
+        * Push the data cache so the CPM does not get stale memory data.
         */
        CBDW_BUFADDR(bdp, dma_map_single(fep->dev,
                                skb->data, skb->len, DMA_TO_DEVICE));
@@ -635,7 +625,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        /*
-        * If this was the last BD in the ring, start at the beginning again. 
+        * If this was the last BD in the ring, start at the beginning again.
         */
        if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
                fep->cur_tx++;
@@ -799,18 +789,22 @@ static int fs_enet_open(struct net_device *dev)
        int r;
        int err;
 
+       napi_enable(&fep->napi);
+
        /* Install our interrupt handler. */
        r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
        if (r != 0) {
                printk(KERN_ERR DRV_MODULE_NAME
                       ": %s Could not allocate FS_ENET IRQ!", dev->name);
+               napi_disable(&fep->napi);
                return -EINVAL;
        }
 
        err = fs_init_phy(dev);
-       if(err)
+       if(err) {
+               napi_disable(&fep->napi);
                return err;
-
+       }
        phy_start(fep->phydev);
 
        return 0;
@@ -823,10 +817,13 @@ static int fs_enet_close(struct net_device *dev)
 
        netif_stop_queue(dev);
        netif_carrier_off(dev);
+       napi_disable(&fep->napi);
        phy_stop(fep->phydev);
 
        spin_lock_irqsave(&fep->lock, flags);
+       spin_lock(&fep->tx_lock);
        (*fep->ops->stop)(dev);
+       spin_unlock(&fep->tx_lock);
        spin_unlock_irqrestore(&fep->lock, flags);
 
        /* release any irqs */
@@ -915,9 +912,7 @@ static const struct ethtool_ops fs_ethtool_ops = {
        .get_link = ethtool_op_get_link,
        .get_msglevel = fs_get_msglevel,
        .set_msglevel = fs_set_msglevel,
-       .get_tx_csum = ethtool_op_get_tx_csum,
        .set_tx_csum = ethtool_op_set_tx_csum,  /* local! */
-       .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
        .get_regs = fs_get_regs,
 };
@@ -961,10 +956,8 @@ static struct net_device *fs_init_instance(struct device *dev,
                err = -ENOMEM;
                goto err;
        }
-       SET_MODULE_OWNER(ndev);
 
        fep = netdev_priv(ndev);
-       memset(fep, 0, privsize);       /* clear everything */
 
        fep->dev = dev;
        dev_set_drvdata(dev, ndev);
@@ -1013,13 +1006,13 @@ static struct net_device *fs_init_instance(struct device *dev,
        spin_lock_init(&fep->tx_lock);
 
        /*
-        * Set the Ethernet address. 
+        * Set the Ethernet address.
         */
        for (i = 0; i < 6; i++)
                ndev->dev_addr[i] = fpi->macaddr[i];
-       
+
        r = (*fep->ops->allocate_bd)(ndev);
-       
+
        if (fep->ring_base == NULL) {
                printk(KERN_ERR DRV_MODULE_NAME
                       ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
@@ -1038,7 +1031,7 @@ static struct net_device *fs_init_instance(struct device *dev,
        fep->rx_ring = fpi->rx_ring;
 
        /*
-        * The FEC Ethernet specific entries in the device structure. 
+        * The FEC Ethernet specific entries in the device structure.
         */
        ndev->open = fs_enet_open;
        ndev->hard_start_xmit = fs_enet_start_xmit;
@@ -1047,10 +1040,14 @@ static struct net_device *fs_init_instance(struct device *dev,
        ndev->stop = fs_enet_close;
        ndev->get_stats = fs_enet_get_stats;
        ndev->set_multicast_list = fs_set_multicast_list;
-       if (fpi->use_napi) {
-               ndev->poll = fs_enet_rx_napi;
-               ndev->weight = fpi->napi_weight;
-       }
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       ndev->poll_controller = fs_enet_netpoll;
+#endif
+
+       netif_napi_add(ndev, &fep->napi,
+                      fs_enet_rx_napi, fpi->napi_weight);
+
        ndev->ethtool_ops = &fs_ethtool_ops;
        ndev->do_ioctl = fs_ioctl;
 
@@ -1262,7 +1259,7 @@ static int __init fs_init(void)
 err:
        cleanup_immap();
        return r;
-       
+
 }
 
 static void __exit fs_cleanup(void)
@@ -1273,6 +1270,15 @@ static void __exit fs_cleanup(void)
        cleanup_immap();
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void fs_enet_netpoll(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       fs_enet_interrupt(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+#endif
+
 /**************************************************************************************/
 
 module_init(fs_init);