]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/net/tc35815.c
[B44]: port to native ssb support
[mirror_ubuntu-artful-kernel.git] / drivers / net / tc35815.c
index 463d600ed83d88a1f656430ac980537ddc6d8846..df8237360f58b2af627ac99c4ab04f66f4b72078 100644 (file)
@@ -23,9 +23,9 @@
  */
 
 #ifdef TC35815_NAPI
-#define DRV_VERSION    "1.35-NAPI"
+#define DRV_VERSION    "1.36-NAPI"
 #else
-#define DRV_VERSION    "1.35"
+#define DRV_VERSION    "1.36"
 #endif
 static const char *version = "tc35815.c:v" DRV_VERSION "\n";
 #define MODNAME                        "tc35815"
@@ -49,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>
 
@@ -413,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 {
@@ -565,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
@@ -597,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) {
@@ -615,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,
@@ -645,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);
@@ -701,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;
@@ -711,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;
@@ -724,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)
@@ -1197,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);
@@ -1396,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
@@ -1404,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);
@@ -1686,13 +1731,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;
 
@@ -1704,23 +1748,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
 
@@ -1909,7 +1949,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. */
 
@@ -2158,7 +2202,6 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
        .get_strings            = tc35815_get_strings,
        .get_stats_count        = tc35815_get_stats_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)