ipg: missing Kconfig dependency
[safe/jmp/linux-2.6] / drivers / net / tc35815.c
index 1a1b74c..d887c05 100644 (file)
  *
  * (C) Copyright TOSHIBA CORPORATION 2004-2005
  * All Rights Reserved.
- *
- *  Revision History:
- *     1.13    64-bit proof.
- *     1.14    Do not round-up transmit length.
- *     1.15    Define TC35815_DMA_SYNC_ONDEMAND, cleanup.
- *     1.16    Fix free_page bug introduced in 1.15
- *     1.17    Add mii/ethtool ioctl support.
- *             Remove workaround for early TX4938.  Cleanup.
- *     1.20    Kernel 2.6.
- *     1.21    Fix receive packet length (omit CRC).
- *             Call netif_carrier_on/netif_carrier_off.
- *             Add kernel/module options (speed, duplex, doforce).
- *             Do not try "force link mode" by default.
- *             Reconfigure CAM on restarting.
- *             Reset PHY on restarting.
- *             Add workaround for 100MHalf HUB.
- *     1.22    Minor fix.
- *     1.23    Minor cleanup.
- *     1.24    Remove tc35815_setup since new stype option
- *             ("tc35815.speed=10", etc.) can be used for 2.6 kernel.
- *     1.25    TX4939 support.
- *     1.26    Minor cleanup.
- *     1.27    Move TX4939 PCFG.SPEEDn control code out from this driver.
- *             Cleanup init_dev_addr. (NETDEV_REGISTER event notifier
- *             can overwrite dev_addr)
- *             support ETHTOOL_GPERMADDR.
- *     1.28    Minor cleanup.
- *     1.29    support netpoll.
- *     1.30    Minor cleanup.
- *     1.31    NAPI support. (disabled by default)
- *             Use DMA_RxAlign_2 if possible.
- *             Do not use PackedBuffer.
- *             Cleanup.
- *     1.32    Fix free buffer management on non-PackedBuffer mode.
- *     1.33    Fix netpoll build.
- *     1.34    Fix netpoll locking.  "BH rule" for NAPI is not enough with
- *             netpoll, hard_start_xmit might be called from irq context.
- *             PM support.
  */
 
 #ifdef TC35815_NAPI
-#define DRV_VERSION    "1.34-NAPI"
+#define DRV_VERSION    "1.36-NAPI"
 #else
-#define DRV_VERSION    "1.34"
+#define DRV_VERSION    "1.36"
 #endif
 static const char *version = "tc35815.c:v" DRV_VERSION "\n";
 #define MODNAME                        "tc35815"
@@ -87,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
 #include <linux/pci.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -451,6 +414,9 @@ enum tc35815_timer_state {
 struct tc35815_local {
        struct pci_dev *pci_dev;
 
+       struct net_device *dev;
+       struct napi_struct napi;
+
        /* statistics */
        struct net_device_stats stats;
        struct {
@@ -578,7 +544,6 @@ static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev,
        skb = dev_alloc_skb(RX_BUF_SIZE);
        if (!skb)
                return NULL;
-       skb->dev = dev;
        *dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE,
                                     PCI_DMA_FROMDEVICE);
        if (pci_dma_mapping_error(*dma_handle)) {
@@ -604,7 +569,7 @@ static int  tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t     tc35815_interrupt(int irq, void *dev_id);
 #ifdef TC35815_NAPI
 static int     tc35815_rx(struct net_device *dev, int limit);
-static int     tc35815_poll(struct net_device *dev, int *budget);
+static int     tc35815_poll(struct napi_struct *napi, int budget);
 #else
 static void    tc35815_rx(struct net_device *dev);
 #endif
@@ -636,13 +601,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
 static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
                          int val);
 
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address.  The platform code
+ * should provide a "tc35815-mac" device with a MAC address in its
+ * platform_data.
+ */
+static int __devinit tc35815_mac_match(struct device *dev, void *data)
+{
+       struct platform_device *plat_dev = to_platform_device(dev);
+       struct pci_dev *pci_dev = data;
+       unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+       return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+       struct tc35815_local *lp = dev->priv;
+       struct device *pd = bus_find_device(&platform_bus_type, NULL,
+                                           lp->pci_dev, tc35815_mac_match);
+       if (pd) {
+               if (pd->platform_data)
+                       memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+               put_device(pd);
+               return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+       }
+       return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+       return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
 {
        struct tc35815_regs __iomem *tr =
                (struct tc35815_regs __iomem *)dev->base_addr;
        int i;
 
-       /* dev_addr will be overwritten on NETDEV_REGISTER event */
        while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
                ;
        for (i = 0; i < 6; i += 2) {
@@ -654,6 +652,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev)
                dev->dev_addr[i] = data & 0xff;
                dev->dev_addr[i+1] = data >> 8;
        }
+       if (!is_valid_ether_addr(dev->dev_addr))
+               return tc35815_read_plat_dev_addr(dev);
+       return 0;
 }
 
 static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -684,9 +685,9 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
                dev_err(&pdev->dev, "unable to alloc new ethernet\n");
                return -ENOMEM;
        }
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
        lp = dev->priv;
+       lp->dev = dev;
 
        /* enable device (incl. PCI PM wakeup), and bus-mastering */
        rc = pci_enable_device (pdev);
@@ -740,8 +741,7 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
        dev->tx_timeout = tc35815_tx_timeout;
        dev->watchdog_timeo = TC35815_TX_TIMEOUT;
 #ifdef TC35815_NAPI
-       dev->poll = tc35815_poll;
-       dev->weight = NAPI_WEIGHT;
+       netif_napi_add(dev, &lp->napi, tc35815_poll, NAPI_WEIGHT);
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = tc35815_poll_controller;
@@ -750,8 +750,6 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) ioaddr;
 
-       /* dev->priv/lp zeroed and aligned in alloc_etherdev */
-       lp = dev->priv;
        spin_lock_init(&lp->lock);
        lp->pci_dev = pdev;
        lp->boardtype = ent->driver_data;
@@ -763,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
        tc35815_chip_reset(dev);
 
        /* Retrieve the ethernet address. */
-       tc35815_init_dev_addr(dev);
+       if (tc35815_init_dev_addr(dev)) {
+               dev_warn(&pdev->dev, "not valid ether addr\n");
+               random_ether_addr(dev->dev_addr);
+       }
 
        rc = register_netdev (dev);
        if (rc)
@@ -1236,6 +1237,10 @@ tc35815_open(struct net_device *dev)
                return -EAGAIN;
        }
 
+#ifdef TC35815_NAPI
+       napi_enable(&lp->napi);
+#endif
+
        /* Reset the hardware here. Don't forget to set the station address. */
        spin_lock_irq(&lp->lock);
        tc35815_chip_init(dev);
@@ -1435,6 +1440,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
 static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
+       struct tc35815_local *lp = netdev_priv(dev);
        struct tc35815_regs __iomem *tr =
                (struct tc35815_regs __iomem *)dev->base_addr;
 #ifdef TC35815_NAPI
@@ -1443,8 +1449,8 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
        if (!(dmactl & DMA_IntMask)) {
                /* disable interrupts */
                tc_writel(dmactl | DMA_IntMask, &tr->DMA_Ctl);
-               if (netif_rx_schedule_prep(dev))
-                       __netif_rx_schedule(dev);
+               if (netif_rx_schedule_prep(dev, &lp->napi))
+                       __netif_rx_schedule(dev, &lp->napi);
                else {
                        printk(KERN_ERR "%s: interrupt taken in poll\n",
                               dev->name);
@@ -1455,7 +1461,6 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
        }
        return IRQ_NONE;
 #else
-       struct tc35815_local *lp = dev->priv;
        int handled;
        u32 status;
 
@@ -1550,6 +1555,11 @@ tc35815_rx(struct net_device *dev)
                                                            PCI_DMA_FROMDEVICE);
 #endif
                                memcpy(data + offset, rxbuf, len);
+#ifdef TC35815_DMA_SYNC_ONDEMAND
+                               pci_dma_sync_single_for_device(lp->pci_dev,
+                                                              dma, len,
+                                                              PCI_DMA_FROMDEVICE);
+#endif
                                offset += len;
                                cur_bd++;
                        }
@@ -1644,7 +1654,7 @@ tc35815_rx(struct net_device *dev)
                                        panic_queues(dev);
                                }
 #endif
-                               /* pass BD to controler */
+                               /* pass BD to controller */
 #ifndef TC35815_USE_PACKEDBUFFER
                                if (!lp->rx_skbs[curid].skb) {
                                        lp->rx_skbs[curid].skb =
@@ -1684,7 +1694,7 @@ tc35815_rx(struct net_device *dev)
                }
 #endif
                for (i = 0; i < (bd_count + 1) / 2 + 1; i++) {
-                       /* pass FD to controler */
+                       /* pass FD to controller */
 #ifdef DEBUG
                        lp->rfd_cur->fd.FDNext = cpu_to_le32(0xdeaddead);
 #else
@@ -1720,13 +1730,12 @@ tc35815_rx(struct net_device *dev)
 }
 
 #ifdef TC35815_NAPI
-static int
-tc35815_poll(struct net_device *dev, int *budget)
+static int tc35815_poll(struct napi_struct *napi, int budget)
 {
-       struct tc35815_local *lp = dev->priv;
+       struct tc35815_local *lp = container_of(napi, struct tc35815_local, napi);
+       struct net_device *dev = lp->dev;
        struct tc35815_regs __iomem *tr =
                (struct tc35815_regs __iomem *)dev->base_addr;
-       int limit = min(*budget, dev->quota);
        int received = 0, handled;
        u32 status;
 
@@ -1738,23 +1747,19 @@ tc35815_poll(struct net_device *dev, int *budget)
                handled = tc35815_do_interrupt(dev, status, limit);
                if (handled >= 0) {
                        received += handled;
-                       limit -= handled;
-                       if (limit <= 0)
+                       if (received >= budget)
                                break;
                }
                status = tc_readl(&tr->Int_Src);
        } while (status);
        spin_unlock(&lp->lock);
 
-       dev->quota -= received;
-       *budget -= received;
-       if (limit <= 0)
-               return 1;
-
-       netif_rx_complete(dev);
-       /* enable interrupts */
-       tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
-       return 0;
+       if (received < budget) {
+               netif_rx_complete(dev, napi);
+               /* enable interrupts */
+               tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
+       }
+       return received;
 }
 #endif
 
@@ -1943,7 +1948,11 @@ static int
 tc35815_close(struct net_device *dev)
 {
        struct tc35815_local *lp = dev->priv;
+
        netif_stop_queue(dev);
+#ifdef TC35815_NAPI
+       napi_disable(&lp->napi);
+#endif
 
        /* Flush the Tx and disable Rx here. */
 
@@ -2152,10 +2161,16 @@ static void tc35815_set_msglevel(struct net_device *dev, u32 datum)
        lp->msg_enable = datum;
 }
 
-static int tc35815_get_stats_count(struct net_device *dev)
+static int tc35815_get_sset_count(struct net_device *dev, int sset)
 {
        struct tc35815_local *lp = dev->priv;
-       return sizeof(lp->lstats) / sizeof(int);
+
+       switch (sset) {
+       case ETH_SS_STATS:
+               return sizeof(lp->lstats) / sizeof(int);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static void tc35815_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
@@ -2190,9 +2205,8 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
        .get_msglevel           = tc35815_get_msglevel,
        .set_msglevel           = tc35815_set_msglevel,
        .get_strings            = tc35815_get_strings,
-       .get_stats_count        = tc35815_get_stats_count,
+       .get_sset_count         = tc35815_get_sset_count,
        .get_ethtool_stats      = tc35815_get_ethtool_stats,
-       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)