[NET]: Make NAPI polling independent of struct net_device objects.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / net / b44.c
index 879a2fff474e007f62907e642d1ea9fdab2ec04b..b92b3e25c42ad2429e497756b69b181ecbe1791f 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_ether.h>
+#include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -68,8 +69,8 @@
          (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
 #define NEXT_TX(N)             (((N) + 1) & (B44_TX_RING_SIZE - 1))
 
-#define RX_PKT_BUF_SZ          (1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ          (B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET          30
+#define RX_PKT_BUF_SZ          (1536 + RX_PKT_OFFSET + 64)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH           (B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque)
 
        spin_unlock_irq(&bp->lock);
 
-       bp->timer.expires = jiffies + HZ;
-       add_timer(&bp->timer);
+       mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
 }
 
 static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                src_map = &bp->rx_buffers[src_idx];
        dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
        map = &bp->rx_buffers[dest_idx];
-       skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+       skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
        if (skb == NULL)
                return -ENOMEM;
 
@@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
                dev_kfree_skb_any(skb);
-               skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+               skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
                if (skb == NULL)
                        return -ENOMEM;
                mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
                }
        }
 
-       skb->dev = bp->dev;
-       skb_reserve(skb, bp->rx_offset);
+       rh = (struct rx_header *) skb->data;
+       skb_reserve(skb, RX_PKT_OFFSET);
 
-       rh = (struct rx_header *)
-               (skb->data - bp->rx_offset);
        rh->len = 0;
        rh->flags = 0;
 
@@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
        if (src_map != NULL)
                src_map->skb = NULL;
 
-       ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+       ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
        if (dest_idx == (B44_RX_RING_SIZE - 1))
                ctrl |= DESC_CTRL_EOT;
 
        dp = &bp->rx_ring[dest_idx];
        dp->ctrl = cpu_to_le32(ctrl);
-       dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+       dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
 
        if (bp->flags & B44_FLAG_RX_RING_HACK)
                b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget)
                                            PCI_DMA_FROMDEVICE);
                rh = (struct rx_header *) skb->data;
                len = le16_to_cpu(rh->len);
-               if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+               if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
                    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
                drop_it:
                        b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget)
                        pci_unmap_single(bp->pdev, map,
                                         skb_size, PCI_DMA_FROMDEVICE);
                        /* Leave out rx_header */
-                       skb_put(skb, len+bp->rx_offset);
-                       skb_pull(skb,bp->rx_offset);
+                       skb_put(skb, len + RX_PKT_OFFSET);
+                       skb_pull(skb, RX_PKT_OFFSET);
                } else {
                        struct sk_buff *copy_skb;
 
@@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget)
                        skb_reserve(copy_skb, 2);
                        skb_put(copy_skb, len);
                        /* DMA sync done above, copy just the actual packet */
-                       skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+                       skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
                                                         copy_skb->data, len);
                        skb = copy_skb;
                }
@@ -850,10 +848,11 @@ static int b44_rx(struct b44 *bp, int budget)
        return received;
 }
 
-static int b44_poll(struct net_device *netdev, int *budget)
+static int b44_poll(struct napi_struct *napi, int budget)
 {
-       struct b44 *bp = netdev_priv(netdev);
-       int done;
+       struct b44 *bp = container_of(napi, struct b44, napi);
+       struct net_device *netdev = bp->dev;
+       int work_done;
 
        spin_lock_irq(&bp->lock);
 
@@ -864,22 +863,9 @@ static int b44_poll(struct net_device *netdev, int *budget)
        }
        spin_unlock_irq(&bp->lock);
 
-       done = 1;
-       if (bp->istat & ISTAT_RX) {
-               int orig_budget = *budget;
-               int work_done;
-
-               if (orig_budget > netdev->quota)
-                       orig_budget = netdev->quota;
-
-               work_done = b44_rx(bp, orig_budget);
-
-               *budget -= work_done;
-               netdev->quota -= work_done;
-
-               if (work_done >= orig_budget)
-                       done = 0;
-       }
+       work_done = 0;
+       if (bp->istat & ISTAT_RX)
+               work_done += b44_rx(bp, budget);
 
        if (bp->istat & ISTAT_ERRORS) {
                unsigned long flags;
@@ -890,15 +876,15 @@ static int b44_poll(struct net_device *netdev, int *budget)
                b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
                netif_wake_queue(bp->dev);
                spin_unlock_irqrestore(&bp->lock, flags);
-               done = 1;
+               work_done = 0;
        }
 
-       if (done) {
-               netif_rx_complete(netdev);
+       if (work_done < budget) {
+               netif_rx_complete(netdev, napi);
                b44_enable_ints(bp);
        }
 
-       return (done ? 0 : 1);
+       return work_done;
 }
 
 static irqreturn_t b44_interrupt(int irq, void *dev_id)
@@ -926,13 +912,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
                        goto irq_ack;
                }
 
-               if (netif_rx_schedule_prep(dev)) {
+               if (netif_rx_schedule_prep(dev, &bp->napi)) {
                        /* NOTE: These writes are posted by the readback of
                         *       the ISTAT register below.
                         */
                        bp->istat = istat;
                        __b44_disable_ints(bp);
-                       __netif_rx_schedule(dev);
+                       __netif_rx_schedule(dev, &bp->napi);
                } else {
                        printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
                               dev->name);
@@ -969,7 +955,6 @@ static void b44_tx_timeout(struct net_device *dev)
 static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct b44 *bp = netdev_priv(dev);
-       struct sk_buff *bounce_skb;
        int rc = NETDEV_TX_OK;
        dma_addr_t mapping;
        u32 len, entry, ctrl;
@@ -987,12 +972,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
        if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+               struct sk_buff *bounce_skb;
+
                /* Chip can't handle DMA to/from >1GB, use bounce buffer */
                if (!dma_mapping_error(mapping))
                        pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
 
-               bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
-                                            GFP_ATOMIC|GFP_DMA);
+               bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
                if (!bounce_skb)
                        goto err_out;
 
@@ -1001,13 +987,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
                        if (!dma_mapping_error(mapping))
                                pci_unmap_single(bp->pdev, mapping,
-                                        len, PCI_DMA_TODEVICE);
+                                                len, PCI_DMA_TODEVICE);
                        dev_kfree_skb_any(bounce_skb);
                        goto err_out;
                }
 
-               skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
-                                         skb->len);
+               skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
                dev_kfree_skb_any(skb);
                skb = bounce_skb;
        }
@@ -1396,12 +1381,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
        bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
        if (reset_kind == B44_PARTIAL_RESET) {
                bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-                                     (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+                                     (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
        } else {
                bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
                bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
                bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-                                     (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+                                     (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
                bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
                bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -1423,6 +1408,8 @@ static int b44_open(struct net_device *dev)
        if (err)
                goto out;
 
+       napi_enable(&bp->napi);
+
        b44_init_rings(bp);
        b44_init_hw(bp, B44_FULL_RESET);
 
@@ -1430,6 +1417,7 @@ static int b44_open(struct net_device *dev)
 
        err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
        if (unlikely(err < 0)) {
+               napi_disable(&bp->napi);
                b44_chip_reset(bp);
                b44_free_rings(bp);
                b44_free_consistent(bp);
@@ -1522,14 +1510,13 @@ static void b44_setup_pseudo_magicp(struct b44 *bp)
        u8 *pwol_pattern;
        u8 pwol_mask[B44_PMASK_SIZE];
 
-       pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL);
+       pwol_pattern = kzalloc(B44_PATTERN_SIZE, GFP_KERNEL);
        if (!pwol_pattern) {
                printk(KERN_ERR PFX "Memory not available for WOL\n");
                return;
        }
 
        /* Ipv4 magic packet pattern - pattern 0.*/
-       memset(pwol_pattern, 0, B44_PATTERN_SIZE);
        memset(pwol_mask, 0, B44_PMASK_SIZE);
        plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
                                  B44_ETHIPV4UDP_HLEN);
@@ -1613,7 +1600,7 @@ static int b44_close(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       netif_poll_disable(dev);
+       napi_disable(&bp->napi);
 
        del_timer_sync(&bp->timer);
 
@@ -1630,8 +1617,6 @@ static int b44_close(struct net_device *dev)
 
        free_irq(dev->irq, dev);
 
-       netif_poll_enable(dev);
-
        if (bp->flags & B44_FLAG_WOL_ENABLE) {
                b44_init_hw(bp, B44_PARTIAL_RESET);
                b44_setup_wol(bp);
@@ -2037,7 +2022,6 @@ static const struct ethtool_ops b44_ethtool_ops = {
        .get_strings            = b44_get_strings,
        .get_stats_count        = b44_get_stats_count,
        .get_ethtool_stats      = b44_get_ethtool_stats,
-       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -2093,11 +2077,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
 
        bp->phy_addr = eeprom[90] & 0x1f;
 
-       /* With this, plus the rx_header prepended to the data by the
-        * hardware, we'll land the ethernet header on a 2-byte boundary.
-        */
-       bp->rx_offset = 30;
-
        bp->imask = IMASK_DEF;
 
        bp->core_unit = ssb_core_unit(bp);
@@ -2204,8 +2183,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
        dev->set_mac_address = b44_set_mac_addr;
        dev->do_ioctl = b44_ioctl;
        dev->tx_timeout = b44_tx_timeout;
-       dev->poll = b44_poll;
-       dev->weight = 64;
+       netif_napi_add(dev, &bp->napi, b44_poll, 64);
        dev->watchdog_timeo = B44_TX_TIMEOUT;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = b44_poll_controller;
@@ -2348,11 +2326,11 @@ static int b44_resume(struct pci_dev *pdev)
        netif_device_attach(bp->dev);
        spin_unlock_irq(&bp->lock);
 
-       bp->timer.expires = jiffies + HZ;
-       add_timer(&bp->timer);
-
        b44_enable_ints(bp);
        netif_wake_queue(dev);
+
+       mod_timer(&bp->timer, jiffies + 1);
+
        return 0;
 }