return received;
 }
 
-static void fs_enet_tx(struct net_device *dev)
+static int fs_enet_tx_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_tx);
+       struct net_device *dev = fep->ndev;
        cbd_t __iomem *bdp;
        struct sk_buff *skb;
        int dirtyidx, do_wake, do_restart;
        u16 sc;
+       int has_tx_work = 0;
 
        spin_lock(&fep->tx_lock);
        bdp = fep->dirty_tx;
 
+       /* clear TX status bits for napi*/
+       (*fep->ops->napi_clear_tx_event)(dev);
+
        do_wake = do_restart = 0;
        while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
                dirtyidx = bdp - fep->tx_bd_base;
                /*
                 * Free the sk buffer associated with this last transmit.
                 */
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb(skb);
                fep->tx_skbuff[dirtyidx] = NULL;
 
                /*
                 */
                if (!fep->tx_free++)
                        do_wake = 1;
+               has_tx_work = 1;
        }
 
        fep->dirty_tx = bdp;
        if (do_restart)
                (*fep->ops->tx_restart)(dev);
 
+       if (!has_tx_work) {
+               napi_complete(napi);
+               (*fep->ops->napi_enable_tx)(dev);
+       }
+
        spin_unlock(&fep->tx_lock);
 
        if (do_wake)
                netif_wake_queue(dev);
+
+       if (has_tx_work)
+               return budget;
+       return 0;
 }
 
 /*
                                __napi_schedule(&fep->napi);
                }
 
-               if (int_events & fep->ev_tx)
-                       fs_enet_tx(dev);
+               if (int_events & fep->ev_tx) {
+                       napi_ok = napi_schedule_prep(&fep->napi_tx);
+
+                       (*fep->ops->napi_disable_tx)(dev);
+                       (*fep->ops->clear_int_events)(dev, fep->ev_napi_tx);
+
+                       /* NOTE: it is possible for FCCs in NAPI mode    */
+                       /* to submit a spurious interrupt while in poll  */
+                       if (napi_ok)
+                               __napi_schedule(&fep->napi_tx);
+               }
        }
 
        handled = nr > 0;
        cbd_t __iomem *bdp;
        int curidx;
        u16 sc;
-       unsigned long flags;
 
 #ifdef CONFIG_FS_ENET_MPC5121_FEC
        if (((unsigned long)skb->data) & 0x3) {
                }
        }
 #endif
-       spin_lock_irqsave(&fep->tx_lock, flags);
+       spin_lock(&fep->tx_lock);
 
        /*
         * Fill in a Tx ring entry
 
        if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
                netif_stop_queue(dev);
-               spin_unlock_irqrestore(&fep->tx_lock, flags);
+               spin_unlock(&fep->tx_lock);
 
                /*
                 * Ooops.  All transmit buffers are full.  Bail out.
 
        (*fep->ops->tx_kickstart)(dev);
 
-       spin_unlock_irqrestore(&fep->tx_lock, flags);
+       spin_unlock(&fep->tx_lock);
 
        return NETDEV_TX_OK;
 }
        fs_init_bds(fep->ndev);
 
        napi_enable(&fep->napi);
+       napi_enable(&fep->napi_tx);
 
        /* Install our interrupt handler. */
        r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
        if (r != 0) {
                dev_err(fep->dev, "Could not allocate FS_ENET IRQ!");
                napi_disable(&fep->napi);
+               napi_disable(&fep->napi_tx);
                return -EINVAL;
        }
 
        if (err) {
                free_irq(fep->interrupt, dev);
                napi_disable(&fep->napi);
+               napi_disable(&fep->napi_tx);
                return err;
        }
        phy_start(fep->phydev);
        netif_stop_queue(dev);
        netif_carrier_off(dev);
        napi_disable(&fep->napi);
+       napi_disable(&fep->napi_tx);
        phy_stop(fep->phydev);
 
        spin_lock_irqsave(&fep->lock, flags);
        ndev->netdev_ops = &fs_enet_netdev_ops;
        ndev->watchdog_timeo = 2 * HZ;
        netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight);
+       netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2);
 
        ndev->ethtool_ops = &fs_ethtool_ops;
 
 
        void (*napi_clear_rx_event)(struct net_device *dev);
        void (*napi_enable_rx)(struct net_device *dev);
        void (*napi_disable_rx)(struct net_device *dev);
+       void (*napi_clear_tx_event)(struct net_device *dev);
+       void (*napi_enable_tx)(struct net_device *dev);
+       void (*napi_disable_tx)(struct net_device *dev);
        void (*rx_bd_done)(struct net_device *dev);
        void (*tx_kickstart)(struct net_device *dev);
        u32 (*get_int_events)(struct net_device *dev);
 
 struct fs_enet_private {
        struct napi_struct napi;
+       struct napi_struct napi_tx;
        struct device *dev;     /* pointer back to the device (must be initialized first) */
        struct net_device *ndev;
        spinlock_t lock;        /* during all ops except TX pckt processing */
 
        /* event masks */
        u32 ev_napi_rx;         /* mask of NAPI rx events */
+       u32 ev_napi_tx;         /* mask of NAPI rx events */
        u32 ev_rx;              /* rx event mask          */
        u32 ev_tx;              /* tx event mask          */
        u32 ev_err;             /* error event mask       */
 
 #define DRV_MODULE_NAME                "fs_enet"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.0"
-#define DRV_MODULE_RELDATE     "Aug 8, 2005"
+#define DRV_MODULE_VERSION     "1.1"
+#define DRV_MODULE_RELDATE     "Sep 22, 2014"
 
 /***************************************************************************/
 
 
 }
 
 #define FCC_NAPI_RX_EVENT_MSK  (FCC_ENET_RXF | FCC_ENET_RXB)
+#define FCC_NAPI_TX_EVENT_MSK  (FCC_ENET_TXF | FCC_ENET_TXB)
 #define FCC_RX_EVENT           (FCC_ENET_RXF)
 #define FCC_TX_EVENT           (FCC_ENET_TXB)
 #define FCC_ERR_EVENT_MSK      (FCC_ENET_TXE)
                return -EINVAL;
 
        fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
+       fep->ev_napi_tx = FCC_NAPI_TX_EVENT_MSK;
        fep->ev_rx = FCC_RX_EVENT;
        fep->ev_tx = FCC_TX_EVENT;
        fep->ev_err = FCC_ERR_EVENT_MSK;
        C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
 }
 
+static void napi_clear_tx_event(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       fcc_t __iomem *fccp = fep->fcc.fccp;
+
+       W16(fccp, fcc_fcce, FCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       fcc_t __iomem *fccp = fep->fcc.fccp;
+
+       S16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       fcc_t __iomem *fccp = fep->fcc.fccp;
+
+       C16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
+}
+
 static void rx_bd_done(struct net_device *dev)
 {
        /* nothing */
        .napi_clear_rx_event    = napi_clear_rx_event,
        .napi_enable_rx         = napi_enable_rx,
        .napi_disable_rx        = napi_disable_rx,
+       .napi_clear_tx_event    = napi_clear_tx_event,
+       .napi_enable_tx         = napi_enable_tx,
+       .napi_disable_tx        = napi_disable_tx,
        .rx_bd_done             = rx_bd_done,
        .tx_kickstart           = tx_kickstart,
        .get_int_events         = get_int_events,
 
 }
 
 #define FEC_NAPI_RX_EVENT_MSK  (FEC_ENET_RXF | FEC_ENET_RXB)
+#define FEC_NAPI_TX_EVENT_MSK  (FEC_ENET_TXF | FEC_ENET_TXB)
 #define FEC_RX_EVENT           (FEC_ENET_RXF)
 #define FEC_TX_EVENT           (FEC_ENET_TXF)
 #define FEC_ERR_EVENT_MSK      (FEC_ENET_HBERR | FEC_ENET_BABR | \
        fep->fec.htlo = 0;
 
        fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
+       fep->ev_napi_tx = FEC_NAPI_TX_EVENT_MSK;
        fep->ev_rx = FEC_RX_EVENT;
        fep->ev_tx = FEC_TX_EVENT;
        fep->ev_err = FEC_ERR_EVENT_MSK;
        FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
 }
 
+static void napi_clear_tx_event(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct fec __iomem *fecp = fep->fec.fecp;
+
+       FW(fecp, ievent, FEC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct fec __iomem *fecp = fep->fec.fecp;
+
+       FS(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct fec __iomem *fecp = fep->fec.fecp;
+
+       FC(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
+}
+
 static void rx_bd_done(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
        .napi_clear_rx_event    = napi_clear_rx_event,
        .napi_enable_rx         = napi_enable_rx,
        .napi_disable_rx        = napi_disable_rx,
+       .napi_clear_tx_event    = napi_clear_tx_event,
+       .napi_enable_tx         = napi_enable_tx,
+       .napi_disable_tx        = napi_disable_tx,
        .rx_bd_done             = rx_bd_done,
        .tx_kickstart           = tx_kickstart,
        .get_int_events         = get_int_events,
 
 }
 
 #define SCC_NAPI_RX_EVENT_MSK  (SCCE_ENET_RXF | SCCE_ENET_RXB)
+#define SCC_NAPI_TX_EVENT_MSK  (SCCE_ENET_TXF | SCCE_ENET_TXB)
 #define SCC_RX_EVENT           (SCCE_ENET_RXF)
 #define SCC_TX_EVENT           (SCCE_ENET_TXB)
 #define SCC_ERR_EVENT_MSK      (SCCE_ENET_TXE | SCCE_ENET_BSY)
        fep->scc.htlo = 0;
 
        fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
+       fep->ev_napi_tx = SCC_NAPI_TX_EVENT_MSK;
        fep->ev_rx = SCC_RX_EVENT;
        fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
        fep->ev_err = SCC_ERR_EVENT_MSK;
        C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
 }
 
+static void napi_clear_tx_event(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       scc_t __iomem *sccp = fep->scc.sccp;
+
+       W16(sccp, scc_scce, SCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       scc_t __iomem *sccp = fep->scc.sccp;
+
+       S16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       scc_t __iomem *sccp = fep->scc.sccp;
+
+       C16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
+}
+
 static void rx_bd_done(struct net_device *dev)
 {
        /* nothing */
        .napi_clear_rx_event    = napi_clear_rx_event,
        .napi_enable_rx         = napi_enable_rx,
        .napi_disable_rx        = napi_disable_rx,
+       .napi_clear_tx_event    = napi_clear_tx_event,
+       .napi_enable_tx         = napi_enable_tx,
+       .napi_disable_tx        = napi_disable_tx,
        .rx_bd_done             = rx_bd_done,
        .tx_kickstart           = tx_kickstart,
        .get_int_events         = get_int_events,