mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-21 14:37:57 +00:00
e9a02ff509
SVN-Revision: 18335
449 lines
11 KiB
Diff
449 lines
11 KiB
Diff
--- 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"
|
|
@@ -91,7 +90,7 @@
|
|
if (enet_readl(priv, ENET_IR_REG) & ENET_IR_MII)
|
|
break;
|
|
udelay(1);
|
|
- } while (limit-- >= 0);
|
|
+ } while (limit-- > 0);
|
|
|
|
return (limit < 0) ? 1 : 0;
|
|
}
|
|
@@ -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;
|