[brcm63xx] merge upstream fixes for bcm63xx_enet
authorflorian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 8 Aug 2009 11:25:36 +0000 (11:25 +0000)
committerflorian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 8 Aug 2009 11:25:36 +0000 (11:25 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17175 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/brcm63xx/patches-2.6.30/060-bcm63xx_enet_upstream_fixes.patch [new file with mode: 0644]

diff --git a/target/linux/brcm63xx/patches-2.6.30/060-bcm63xx_enet_upstream_fixes.patch b/target/linux/brcm63xx/patches-2.6.30/060-bcm63xx_enet_upstream_fixes.patch
new file mode 100644 (file)
index 0000000..0271aa6
--- /dev/null
@@ -0,0 +1,439 @@
+--- a/drivers/net/bcm63xx_enet.c       2009-07-31 22:06:20.000000000 +0200
++++ b/drivers/net/bcm63xx_enet.c       2009-08-05 10:02:28.000000000 +0200
+@@ -28,7 +28,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/platform_device.h>
+ #include <linux/if_vlan.h>
+-#include <linux/version.h>
+ #include <bcm63xx_dev_enet.h>
+ #include "bcm63xx_enet.h"
+@@ -321,7 +320,7 @@
+               if (len < copybreak) {
+                       struct sk_buff *nskb;
+-                      nskb = netdev_alloc_skb(dev, len + 2);
++                      nskb = netdev_alloc_skb(dev, len + NET_IP_ALIGN);
+                       if (!nskb) {
+                               /* forget packet, just rearm desc */
+                               priv->stats.rx_dropped++;
+@@ -452,11 +451,7 @@
+       /* no more packet in rx/tx queue, remove device from poll
+        * queue */
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+-      netif_rx_complete(dev, napi);
+-#else
+       napi_complete(napi);
+-#endif
+       /* restore rx/tx interrupt */
+       enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+@@ -508,11 +503,7 @@
+       enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
+       enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+-      netif_rx_schedule(dev, &priv->napi);
+-#else
+       napi_schedule(&priv->napi);
+-#endif
+       return IRQ_HANDLED;
+ }
+@@ -764,11 +755,11 @@
+               pr_info("%s: link %s", dev->name, phydev->link ?
+                       "UP" : "DOWN");
+               if (phydev->link)
+-                      printk(" - %d/%s - flow control %s", phydev->speed,
++                      pr_cont(" - %d/%s - flow control %s", phydev->speed,
+                              DUPLEX_FULL == phydev->duplex ? "full" : "half",
+                              phydev->pause == 1 ? "rx&tx" : "off");
+-              printk("\n");
++              pr_cont("\n");
+       }
+ }
+@@ -782,6 +773,7 @@
+       priv = netdev_priv(dev);
+       bcm_enet_set_duplex(priv, priv->force_duplex_full);
+       bcm_enet_set_flow(priv, priv->pause_rx, priv->pause_tx);
++      netif_carrier_on(dev);
+       pr_info("%s: link forced UP - %d/%s - flow control %s/%s\n",
+               dev->name,
+@@ -800,21 +792,18 @@
+       struct sockaddr addr;
+       struct device *kdev;
+       struct phy_device *phydev;
+-      int irq_requested, i, ret;
++      int i, ret;
+       unsigned int size;
+-      char phy_id[BUS_ID_SIZE];
++      char phy_id[MII_BUS_ID_SIZE + 3];
+       void *p;
+       u32 val;
+       priv = netdev_priv(dev);
+-      priv->rx_desc_cpu = priv->tx_desc_cpu = NULL;
+-      priv->rx_skb = priv->tx_skb = NULL;
+-
+       kdev = &priv->pdev->dev;
+       if (priv->has_phy) {
+               /* connect to PHY */
+-              snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
++              snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+                        priv->mac_id ? "1" : "0", priv->phy_id);
+               phydev = phy_connect(dev, phy_id, &bcm_enet_adjust_phy_link, 0,
+@@ -854,23 +843,19 @@
+       enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
+       enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
+-      irq_requested = 0;
+       ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
+       if (ret)
+-              goto out;
+-      irq_requested++;
++              goto out_phy_disconnect;
+       ret = request_irq(priv->irq_rx, bcm_enet_isr_dma,
+                         IRQF_SAMPLE_RANDOM | IRQF_DISABLED, dev->name, dev);
+       if (ret)
+-              goto out;
+-      irq_requested++;
++              goto out_freeirq;
+       ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
+                         IRQF_DISABLED, dev->name, dev);
+       if (ret)
+-              goto out;
+-      irq_requested++;
++              goto out_freeirq_rx;
+       /* initialize perfect match registers */
+       for (i = 0; i < 4; i++) {
+@@ -888,7 +873,7 @@
+       if (!p) {
+               dev_err(kdev, "cannot allocate rx ring %u\n", size);
+               ret = -ENOMEM;
+-              goto out;
++              goto out_freeirq_tx;
+       }
+       memset(p, 0, size);
+@@ -901,7 +886,7 @@
+       if (!p) {
+               dev_err(kdev, "cannot allocate tx ring\n");
+               ret = -ENOMEM;
+-              goto out;
++              goto out_free_rx_ring;
+       }
+       memset(p, 0, size);
+@@ -913,7 +898,7 @@
+       if (!priv->tx_skb) {
+               dev_err(kdev, "cannot allocate rx skb queue\n");
+               ret = -ENOMEM;
+-              goto out;
++              goto out_free_tx_ring;
+       }
+       priv->tx_desc_count = priv->tx_ring_size;
+@@ -927,7 +912,7 @@
+       if (!priv->rx_skb) {
+               dev_err(kdev, "cannot allocate rx skb queue\n");
+               ret = -ENOMEM;
+-              goto out;
++              goto out_free_tx_skb;
+       }
+       priv->rx_desc_count = 0;
+@@ -1012,13 +997,6 @@
+       return 0;
+ out:
+-      phy_disconnect(priv->phydev);
+-      if (irq_requested > 2)
+-              free_irq(priv->irq_tx, dev);
+-      if (irq_requested > 1)
+-              free_irq(priv->irq_rx, dev);
+-      if (irq_requested > 0)
+-              free_irq(dev->irq, dev);
+       for (i = 0; i < priv->rx_ring_size; i++) {
+               struct bcm_enet_desc *desc;
+@@ -1030,14 +1008,31 @@
+                                DMA_FROM_DEVICE);
+               kfree_skb(priv->rx_skb[i]);
+       }
+-      if (priv->rx_desc_cpu)
+-              dma_free_coherent(kdev, priv->rx_desc_alloc_size,
+-                                priv->rx_desc_cpu, priv->rx_desc_dma);
+-      if (priv->tx_desc_cpu)
+-              dma_free_coherent(kdev, priv->tx_desc_alloc_size,
+-                                priv->tx_desc_cpu, priv->tx_desc_dma);
+       kfree(priv->rx_skb);
++
++out_free_tx_skb:
+       kfree(priv->tx_skb);
++
++out_free_tx_ring:
++      dma_free_coherent(kdev, priv->tx_desc_alloc_size,
++                        priv->tx_desc_cpu, priv->tx_desc_dma);
++
++out_free_rx_ring:
++      dma_free_coherent(kdev, priv->rx_desc_alloc_size,
++                        priv->rx_desc_cpu, priv->rx_desc_dma);
++
++out_freeirq_tx:
++      free_irq(priv->irq_tx, dev);
++
++out_freeirq_rx:
++      free_irq(priv->irq_rx, dev);
++
++out_freeirq:
++      free_irq(dev->irq, dev);
++
++out_phy_disconnect:
++      phy_disconnect(priv->phydev);
++
+       return ret;
+ }
+@@ -1606,6 +1601,20 @@
+       enet_writel(priv, val, ENET_MIBCTL_REG);
+ }
++static const struct net_device_ops bcm_enet_ops = {
++      .ndo_open               = bcm_enet_open,
++      .ndo_stop               = bcm_enet_stop,
++      .ndo_start_xmit         = bcm_enet_start_xmit,
++      .ndo_get_stats          = bcm_enet_get_stats,
++      .ndo_set_mac_address    = bcm_enet_set_mac_address,
++      .ndo_set_multicast_list = bcm_enet_set_multicast_list,
++      .ndo_do_ioctl           = bcm_enet_ioctl,
++      .ndo_change_mtu         = bcm_enet_change_mtu,
++#ifdef CONFIG_NET_POLL_CONTROLLER
++      .ndo_poll_controller = bcm_enet_netpoll,
++#endif
++};
++
+ /*
+  * allocate netdevice, request register memory and register device.
+  */
+@@ -1618,15 +1627,13 @@
+       struct mii_bus *bus;
+       const char *clk_name;
+       unsigned int iomem_size;
+-      int i, ret, mdio_registered, mem_requested;
++      int i, ret;
+       /* stop if shared driver failed, assume driver->probe will be
+        * called in the same order we register devices (correct ?) */
+       if (!bcm_enet_shared_base)
+               return -ENODEV;
+-      mdio_registered = mem_requested = 0;
+-
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+@@ -1648,14 +1655,13 @@
+       iomem_size = res_mem->end - res_mem->start + 1;
+       if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
+               ret = -EBUSY;
+-              goto err;
++              goto out;
+       }
+-      mem_requested = 1;
+       priv->base = ioremap(res_mem->start, iomem_size);
+       if (priv->base == NULL) {
+               ret = -ENOMEM;
+-              goto err;
++              goto out_release_mem;
+       }
+       dev->irq = priv->irq = res_irq->start;
+       priv->irq_rx = res_irq_rx->start;
+@@ -1676,8 +1682,7 @@
+       priv->mac_clk = clk_get(&pdev->dev, clk_name);
+       if (IS_ERR(priv->mac_clk)) {
+               ret = PTR_ERR(priv->mac_clk);
+-              priv->mac_clk = NULL;
+-              goto err;
++              goto out_unmap;
+       }
+       clk_enable(priv->mac_clk);
+@@ -1706,7 +1711,7 @@
+               if (IS_ERR(priv->phy_clk)) {
+                       ret = PTR_ERR(priv->phy_clk);
+                       priv->phy_clk = NULL;
+-                      goto err;
++                      goto out_put_clk_mac;
+               }
+               clk_enable(priv->phy_clk);
+       }
+@@ -1716,13 +1721,16 @@
+       /* MII bus registration */
+       if (priv->has_phy) {
+-              bus = &priv->mii_bus;
++
++              priv->mii_bus = mdiobus_alloc();
++              if (!priv->mii_bus) {
++                      ret = -ENOMEM;
++                      goto out_uninit_hw;
++              }
++
++              bus = priv->mii_bus;
+               bus->name = "bcm63xx_enet MII bus";
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+-              bus->dev = &pdev->dev;
+-#else
+               bus->parent = &pdev->dev;
+-#endif
+               bus->priv = priv;
+               bus->read = bcm_enet_mdio_read_phylib;
+               bus->write = bcm_enet_mdio_write_phylib;
+@@ -1736,7 +1744,7 @@
+               bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+               if (!bus->irq) {
+                       ret = -ENOMEM;
+-                      goto err;
++                      goto out_free_mdio;
+               }
+               if (priv->has_phy_interrupt)
+@@ -1747,9 +1755,8 @@
+               ret = mdiobus_register(bus);
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to register mdio bus\n");
+-                      goto err;
++                      goto out_free_mdio;
+               }
+-              mdio_registered = 1;
+       } else {
+               /* run platform code to initialize PHY device */
+@@ -1757,7 +1764,7 @@
+                   pd->mii_config(dev, 1, bcm_enet_mdio_read_mii,
+                                  bcm_enet_mdio_write_mii)) {
+                       dev_err(&pdev->dev, "unable to configure mdio bus\n");
+-                      goto err;
++                      goto out_uninit_hw;
+               }
+       }
+@@ -1777,51 +1784,50 @@
+               enet_writel(priv, 0, ENET_MIB_REG(i));
+       /* register netdevice */
+-      dev->open = bcm_enet_open;
+-      dev->stop = bcm_enet_stop;
+-      dev->hard_start_xmit = bcm_enet_start_xmit;
+-      dev->get_stats = bcm_enet_get_stats;
+-      dev->set_mac_address = bcm_enet_set_mac_address;
+-      dev->set_multicast_list = bcm_enet_set_multicast_list;
++      dev->netdev_ops = &bcm_enet_ops;
+       netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
+-      dev->do_ioctl = bcm_enet_ioctl;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-      dev->poll_controller = bcm_enet_netpoll;
+-#endif
+-      dev->change_mtu = bcm_enet_change_mtu;
+       SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
+-      SET_NETDEV_DEV(dev, &pdev->dev);
+       ret = register_netdev(dev);
+       if (ret)
+-              goto err;
++              goto out_unregister_mdio;
++      netif_carrier_off(dev);
+       platform_set_drvdata(pdev, dev);
+       priv->pdev = pdev;
+       priv->net_dev = dev;
++      SET_NETDEV_DEV(dev, &pdev->dev);
+       return 0;
+-err:
+-      if (mem_requested)
+-              release_mem_region(res_mem->start, iomem_size);
+-      if (mdio_registered)
+-              mdiobus_unregister(&priv->mii_bus);
+-      kfree(priv->mii_bus.irq);
+-      if (priv->mac_clk) {
+-              clk_disable(priv->mac_clk);
+-              clk_put(priv->mac_clk);
++out_unregister_mdio:
++      if (priv->mii_bus) {
++              mdiobus_unregister(priv->mii_bus);
++              kfree(priv->mii_bus->irq);
+       }
++
++out_free_mdio:
++      if (priv->mii_bus)
++              mdiobus_free(priv->mii_bus);
++
++out_uninit_hw:
++      /* turn off mdc clock */
++      enet_writel(priv, 0, ENET_MIISC_REG);
+       if (priv->phy_clk) {
+               clk_disable(priv->phy_clk);
+               clk_put(priv->phy_clk);
+       }
+-      if (priv->base) {
+-              /* turn off mdc clock */
+-              enet_writel(priv, 0, ENET_MIISC_REG);
+-              iounmap(priv->base);
+-      }
++
++out_put_clk_mac:
++      clk_disable(priv->mac_clk);
++      clk_put(priv->mac_clk);
++
++out_unmap:
++      iounmap(priv->base);
++
++out_release_mem:
++      release_mem_region(res_mem->start, iomem_size);
+ out:
+       free_netdev(dev);
+       return ret;
+@@ -1846,8 +1852,9 @@
+       enet_writel(priv, 0, ENET_MIISC_REG);
+       if (priv->has_phy) {
+-              mdiobus_unregister(&priv->mii_bus);
+-              kfree(priv->mii_bus.irq);
++              mdiobus_unregister(priv->mii_bus);
++              kfree(priv->mii_bus->irq);
++              mdiobus_free(priv->mii_bus);
+       } else {
+               struct bcm63xx_enet_platform_data *pd;
+@@ -1870,7 +1877,6 @@
+       clk_disable(priv->mac_clk);
+       clk_put(priv->mac_clk);
+-      platform_set_drvdata(pdev, NULL);
+       free_netdev(dev);
+       return 0;
+ }
+--- a/drivers/net/bcm63xx_enet.h       2009-06-07 11:25:51.000000000 +0200
++++ b/drivers/net/bcm63xx_enet.h       2009-08-05 10:02:28.000000000 +0200
+@@ -258,7 +258,7 @@
+       int phy_interrupt;
+       /* used when a phy is connected (phylib used) */
+-      struct mii_bus mii_bus;
++      struct mii_bus *mii_bus;
+       struct phy_device *phydev;
+       int old_link;
+       int old_duplex;