From 8a73b0bc86366113e13d079b3de76df6e94a4a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 21:34:31 +0100 Subject: [PATCH 01/14] net/fec: no need to cast arguments for memcpy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memcpy takes a const void * as 2nd argument. So the argument is converted automatically to void * anyhow. Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 2a71373719ae..3e6e923ca59b 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -284,7 +284,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { unsigned int index; index = bdp - fep->tx_bd_base; - memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); + memcpy(fep->tx_bounce[index], skb->data, skb->len); bufaddr = fep->tx_bounce[index]; } From 28e2188efc614c714c69dd5c3f063e066e80d3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 21:44:18 +0100 Subject: [PATCH 02/14] net/fec: release mem_region requested in probe in error path and remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 3e6e923ca59b..b079826586ef 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1377,8 +1377,10 @@ fec_probe(struct platform_device *pdev) /* Init network device */ ndev = alloc_etherdev(sizeof(struct fec_enet_private)); - if (!ndev) - return -ENOMEM; + if (!ndev) { + ret = -ENOMEM; + goto failed_alloc_etherdev; + } SET_NETDEV_DEV(ndev, &pdev->dev); @@ -1456,6 +1458,8 @@ failed_irq: iounmap((void __iomem *)ndev->base_addr); failed_ioremap: free_netdev(ndev); +failed_alloc_etherdev: + release_mem_region(r->start, resource_size(r)); return ret; } @@ -1465,6 +1469,7 @@ fec_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); + struct resource *r; platform_set_drvdata(pdev, NULL); @@ -1475,6 +1480,11 @@ fec_drv_remove(struct platform_device *pdev) iounmap((void __iomem *)ndev->base_addr); unregister_netdev(ndev); free_netdev(ndev); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + BUG_ON(!r); + release_mem_region(r->start, resource_size(r)); + return 0; } From b2b09ad63cc09448e49f6a4addae6e078c0e5e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 21:49:05 +0100 Subject: [PATCH 03/14] net/fec: don't free an irq that failed to be requested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b079826586ef..aa1db8e637cd 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1409,10 +1409,9 @@ fec_probe(struct platform_device *pdev) break; ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); if (ret) { - while (i >= 0) { + while (--i >= 0) { irq = platform_get_irq(pdev, i); free_irq(irq, ndev); - i--; } goto failed_irq; } From 04e5216d44e173fab619d03e2f746f444ea21ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 21:53:40 +0100 Subject: [PATCH 04/14] net/fec: no need to check for validity of ndev in suspend and resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_set_drvdata is called unconditionally in the probe function and so it cannot be NULL. Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index aa1db8e637cd..8026a16f6b6c 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1492,16 +1492,14 @@ static int fec_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep; + struct fec_enet_private *fep = netdev_priv(ndev); - if (ndev) { - fep = netdev_priv(ndev); - if (netif_running(ndev)) { - fec_stop(ndev); - netif_device_detach(ndev); - } - clk_disable(fep->clk); + if (netif_running(ndev)) { + fec_stop(ndev); + netif_device_detach(ndev); } + clk_disable(fep->clk); + return 0; } @@ -1509,16 +1507,14 @@ static int fec_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep; + struct fec_enet_private *fep = netdev_priv(ndev); - if (ndev) { - fep = netdev_priv(ndev); - clk_enable(fep->clk); - if (netif_running(ndev)) { - fec_restart(ndev, fep->full_duplex); - netif_device_attach(ndev); - } + clk_enable(fep->clk); + if (netif_running(ndev)) { + fec_restart(ndev, fep->full_duplex); + netif_device_attach(ndev); } + return 0; } From 8b06dc2b1cdc33f6426bc4b0d58b357146d739f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 21:56:14 +0100 Subject: [PATCH 05/14] net/fec: no need to memzero private data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alloc_etherdev internally uses kzalloc, so the private data is already zerod out. Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 8026a16f6b6c..9a25e1e0a2e0 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1386,7 +1386,6 @@ fec_probe(struct platform_device *pdev) /* setup board info structure */ fep = netdev_priv(ndev); - memset(fep, 0, sizeof(*fep)); ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); fep->pdev = pdev; From 24e531b401752995493fa36ee8d8f10c45038e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 13 Jan 2011 22:29:05 +0100 Subject: [PATCH 06/14] net/fec: put the ioremap cookie immediately into a void __iomem pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Saving it first into struct net_device->base_addr (which is an unsigned long) is pointless and only needs to use more casts than necessary. Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9a25e1e0a2e0..14eb6604a7f5 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1170,7 +1170,6 @@ static int fec_enet_init(struct net_device *dev) spin_lock_init(&fep->hw_lock); - fep->hwp = (void __iomem *)dev->base_addr; fep->netdev = dev; /* Get the Ethernet address */ @@ -1387,10 +1386,10 @@ fec_probe(struct platform_device *pdev) /* setup board info structure */ fep = netdev_priv(ndev); - ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); + fep->hwp = ioremap(r->start, resource_size(r)); fep->pdev = pdev; - if (!ndev->base_addr) { + if (!fep->hwp) { ret = -ENOMEM; goto failed_ioremap; } @@ -1453,7 +1452,7 @@ failed_clk: free_irq(irq, ndev); } failed_irq: - iounmap((void __iomem *)ndev->base_addr); + iounmap(fep->hwp); failed_ioremap: free_netdev(ndev); failed_alloc_etherdev: @@ -1475,7 +1474,7 @@ fec_drv_remove(struct platform_device *pdev) fec_enet_mii_remove(fep); clk_disable(fep->clk); clk_put(fep->clk); - iounmap((void __iomem *)ndev->base_addr); + iounmap(fep->hwp); unregister_netdev(ndev); free_netdev(ndev); From 085e79ed88351d2f3cbf257ff4fc00394792da18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Jan 2011 09:52:18 +0100 Subject: [PATCH 07/14] net/fec: consolidate all i.MX options to CONFIG_ARM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moreover stop listing all i.MX platforms featuring a FEC, and use the platform's config symbol that selects registration of a fec device instead. This might make it easier to add new platforms. Set default = y for ARMs having a fec to reduce defconfig sizes. Signed-off-by: Uwe Kleine-König --- drivers/net/Kconfig | 3 ++- drivers/net/fec.c | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 03823327db25..65027a72ca93 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1944,7 +1944,8 @@ config 68360_ENET config FEC bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" depends on M523x || M527x || M5272 || M528x || M520x || M532x || \ - MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28 + IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC + default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM select PHYLIB help Say Y here if you want to use the built-in 10/100 Fast ethernet diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 14eb6604a7f5..dd4e580c7f35 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -54,7 +54,7 @@ #include "fec.h" -#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) +#if defined(CONFIG_ARM) #define FEC_ALIGNMENT 0xf #else #define FEC_ALIGNMENT 0x3 @@ -147,8 +147,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); * account when setting it. */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ - defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 From e497ba825b60727f02d8bc21869f445c5aad34e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Jan 2011 20:04:23 +0100 Subject: [PATCH 08/14] net/fec: add phy_stop to fec_enet_close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This undoes the effects of phy_start in fec_enet_open. Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index dd4e580c7f35..d3dbff514d67 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1029,8 +1029,10 @@ fec_enet_close(struct net_device *dev) netif_stop_queue(dev); fec_stop(dev); - if (fep->phy_dev) + if (fep->phy_dev) { + phy_stop(fep->phy_dev); phy_disconnect(fep->phy_dev); + } fec_enet_free_buffers(dev); From c556167f819160e157b4d73937885de8754ea53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 19 Jan 2011 11:58:12 +0100 Subject: [PATCH 09/14] net/fec: consistenly name struct net_device pointers "ndev" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A variable named "dev" usually (usually subjective) points to a struct device. Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 242 +++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d3dbff514d67..c70503a065bb 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -206,11 +206,11 @@ struct fec_enet_private { }; static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); -static void fec_enet_tx(struct net_device *dev); -static void fec_enet_rx(struct net_device *dev); -static int fec_enet_close(struct net_device *dev); -static void fec_restart(struct net_device *dev, int duplex); -static void fec_stop(struct net_device *dev); +static void fec_enet_tx(struct net_device *ndev); +static void fec_enet_rx(struct net_device *ndev); +static int fec_enet_close(struct net_device *ndev); +static void fec_restart(struct net_device *ndev, int duplex); +static void fec_stop(struct net_device *ndev); /* FEC MII MMFR bits definition */ #define FEC_MMFR_ST (1 << 30) @@ -238,9 +238,9 @@ static void *swap_buffer(void *bufaddr, int len) } static netdev_tx_t -fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) +fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); struct bufdesc *bdp; @@ -261,9 +261,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (status & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since dev->tbusy should be set. + * This should not happen, since ndev->tbusy should be set. */ - printk("%s: tx queue full!.\n", dev->name); + printk("%s: tx queue full!.\n", ndev->name); spin_unlock_irqrestore(&fep->hw_lock, flags); return NETDEV_TX_BUSY; } @@ -298,13 +298,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Save skb pointer */ fep->tx_skbuff[fep->skb_cur] = skb; - dev->stats.tx_bytes += skb->len; + ndev->stats.tx_bytes += skb->len; fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; /* Push the data cache so the CPM does not get stale memory * data. */ - bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr, + bdp->cbd_bufaddr = dma_map_single(&ndev->dev, bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, @@ -325,7 +325,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bdp == fep->dirty_tx) { fep->tx_full = 1; - netif_stop_queue(dev); + netif_stop_queue(ndev); } fep->cur_tx = bdp; @@ -336,22 +336,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) } static void -fec_timeout(struct net_device *dev) +fec_timeout(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); - dev->stats.tx_errors++; + ndev->stats.tx_errors++; - fec_restart(dev, fep->full_duplex); - netif_wake_queue(dev); + fec_restart(ndev, fep->full_duplex); + netif_wake_queue(ndev); } static irqreturn_t -fec_enet_interrupt(int irq, void * dev_id) +fec_enet_interrupt(int irq, void *dev_id) { - struct net_device *dev = dev_id; - struct fec_enet_private *fep = netdev_priv(dev); - uint int_events; + struct net_device *ndev = dev_id; + struct fec_enet_private *fep = netdev_priv(ndev); + uint int_events; irqreturn_t ret = IRQ_NONE; do { @@ -360,7 +360,7 @@ fec_enet_interrupt(int irq, void * dev_id) if (int_events & FEC_ENET_RXF) { ret = IRQ_HANDLED; - fec_enet_rx(dev); + fec_enet_rx(ndev); } /* Transmit OK, or non-fatal error. Update the buffer @@ -369,7 +369,7 @@ fec_enet_interrupt(int irq, void * dev_id) */ if (int_events & FEC_ENET_TXF) { ret = IRQ_HANDLED; - fec_enet_tx(dev); + fec_enet_tx(ndev); } if (int_events & FEC_ENET_MII) { @@ -383,14 +383,14 @@ fec_enet_interrupt(int irq, void * dev_id) static void -fec_enet_tx(struct net_device *dev) +fec_enet_tx(struct net_device *ndev) { struct fec_enet_private *fep; struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; - fep = netdev_priv(dev); + fep = netdev_priv(ndev); spin_lock(&fep->hw_lock); bdp = fep->dirty_tx; @@ -398,7 +398,7 @@ fec_enet_tx(struct net_device *dev) if (bdp == fep->cur_tx && fep->tx_full == 0) break; - dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); + dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); bdp->cbd_bufaddr = 0; skb = fep->tx_skbuff[fep->skb_dirty]; @@ -406,19 +406,19 @@ fec_enet_tx(struct net_device *dev) if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) { - dev->stats.tx_errors++; + ndev->stats.tx_errors++; if (status & BD_ENET_TX_HB) /* No heartbeat */ - dev->stats.tx_heartbeat_errors++; + ndev->stats.tx_heartbeat_errors++; if (status & BD_ENET_TX_LC) /* Late collision */ - dev->stats.tx_window_errors++; + ndev->stats.tx_window_errors++; if (status & BD_ENET_TX_RL) /* Retrans limit */ - dev->stats.tx_aborted_errors++; + ndev->stats.tx_aborted_errors++; if (status & BD_ENET_TX_UN) /* Underrun */ - dev->stats.tx_fifo_errors++; + ndev->stats.tx_fifo_errors++; if (status & BD_ENET_TX_CSL) /* Carrier lost */ - dev->stats.tx_carrier_errors++; + ndev->stats.tx_carrier_errors++; } else { - dev->stats.tx_packets++; + ndev->stats.tx_packets++; } if (status & BD_ENET_TX_READY) @@ -428,7 +428,7 @@ fec_enet_tx(struct net_device *dev) * but we eventually sent the packet OK. */ if (status & BD_ENET_TX_DEF) - dev->stats.collisions++; + ndev->stats.collisions++; /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); @@ -445,8 +445,8 @@ fec_enet_tx(struct net_device *dev) */ if (fep->tx_full) { fep->tx_full = 0; - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); } } fep->dirty_tx = bdp; @@ -460,9 +460,9 @@ fec_enet_tx(struct net_device *dev) * effectively tossing the packet. */ static void -fec_enet_rx(struct net_device *dev) +fec_enet_rx(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); struct bufdesc *bdp; @@ -496,17 +496,17 @@ fec_enet_rx(struct net_device *dev) /* Check for errors. */ if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - dev->stats.rx_errors++; + ndev->stats.rx_errors++; if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { /* Frame too long or too short. */ - dev->stats.rx_length_errors++; + ndev->stats.rx_length_errors++; } if (status & BD_ENET_RX_NO) /* Frame alignment */ - dev->stats.rx_frame_errors++; + ndev->stats.rx_frame_errors++; if (status & BD_ENET_RX_CR) /* CRC Error */ - dev->stats.rx_crc_errors++; + ndev->stats.rx_crc_errors++; if (status & BD_ENET_RX_OV) /* FIFO overrun */ - dev->stats.rx_fifo_errors++; + ndev->stats.rx_fifo_errors++; } /* Report late collisions as a frame error. @@ -514,15 +514,15 @@ fec_enet_rx(struct net_device *dev) * have in the buffer. So, just drop this frame on the floor. */ if (status & BD_ENET_RX_CL) { - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; + ndev->stats.rx_errors++; + ndev->stats.rx_frame_errors++; goto rx_processing_done; } /* Process the incoming frame. */ - dev->stats.rx_packets++; + ndev->stats.rx_packets++; pkt_len = bdp->cbd_datlen; - dev->stats.rx_bytes += pkt_len; + ndev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, @@ -540,13 +540,13 @@ fec_enet_rx(struct net_device *dev) if (unlikely(!skb)) { printk("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; + ndev->name); + ndev->stats.rx_dropped++; } else { skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len - 4); /* Make room */ skb_copy_to_linear_data(skb, data, pkt_len - 4); - skb->protocol = eth_type_trans(skb, dev); + skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); } @@ -577,9 +577,9 @@ rx_processing_done: } /* ------------------------------------------------------------------------- */ -static void __inline__ fec_get_mac(struct net_device *dev) +static void __inline__ fec_get_mac(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct fec_platform_data *pdata = fep->pdev->dev.platform_data; unsigned char *iap, tmpaddr[ETH_ALEN]; @@ -615,11 +615,11 @@ static void __inline__ fec_get_mac(struct net_device *dev) iap = &tmpaddr[0]; } - memcpy(dev->dev_addr, iap, ETH_ALEN); + memcpy(ndev->dev_addr, iap, ETH_ALEN); /* Adjust MAC if using macaddr */ if (iap == macaddr) - dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; + ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; } /* ------------------------------------------------------------------------- */ @@ -627,9 +627,9 @@ static void __inline__ fec_get_mac(struct net_device *dev) /* * Phy section */ -static void fec_enet_adjust_link(struct net_device *dev) +static void fec_enet_adjust_link(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phy_dev = fep->phy_dev; unsigned long flags; @@ -646,7 +646,7 @@ static void fec_enet_adjust_link(struct net_device *dev) /* Duplex link change */ if (phy_dev->link) { if (fep->full_duplex != phy_dev->duplex) { - fec_restart(dev, phy_dev->duplex); + fec_restart(ndev, phy_dev->duplex); status_change = 1; } } @@ -655,9 +655,9 @@ static void fec_enet_adjust_link(struct net_device *dev) if (phy_dev->link != fep->link) { fep->link = phy_dev->link; if (phy_dev->link) - fec_restart(dev, phy_dev->duplex); + fec_restart(ndev, phy_dev->duplex); else - fec_stop(dev); + fec_stop(ndev); status_change = 1; } @@ -726,9 +726,9 @@ static int fec_enet_mdio_reset(struct mii_bus *bus) return 0; } -static int fec_enet_mii_probe(struct net_device *dev) +static int fec_enet_mii_probe(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phy_dev = NULL; char mdio_bus_id[MII_BUS_ID_SIZE]; char phy_name[MII_BUS_ID_SIZE + 3]; @@ -753,16 +753,16 @@ static int fec_enet_mii_probe(struct net_device *dev) if (phy_id >= PHY_MAX_ADDR) { printk(KERN_INFO "%s: no PHY, assuming direct connection " - "to switch\n", dev->name); + "to switch\n", ndev->name); strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); phy_id = 0; } snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); - phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0, + phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phy_dev)) { - printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); + printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name); return PTR_ERR(phy_dev); } @@ -775,7 +775,7 @@ static int fec_enet_mii_probe(struct net_device *dev) fep->full_duplex = 0; printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), fep->phy_dev->irq); @@ -785,8 +785,8 @@ static int fec_enet_mii_probe(struct net_device *dev) static int fec_enet_mii_init(struct platform_device *pdev) { static struct mii_bus *fec0_mii_bus; - struct net_device *dev = platform_get_drvdata(pdev); - struct fec_enet_private *fep = netdev_priv(dev); + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); int err = -ENXIO, i; @@ -844,7 +844,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) for (i = 0; i < PHY_MAX_ADDR; i++) fep->mii_bus->irq[i] = PHY_POLL; - platform_set_drvdata(dev, fep->mii_bus); + platform_set_drvdata(ndev, fep->mii_bus); if (mdiobus_register(fep->mii_bus)) goto err_out_free_mdio_irq; @@ -872,10 +872,10 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep) mdiobus_free(fep->mii_bus); } -static int fec_enet_get_settings(struct net_device *dev, +static int fec_enet_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; if (!phydev) @@ -884,10 +884,10 @@ static int fec_enet_get_settings(struct net_device *dev, return phy_ethtool_gset(phydev, cmd); } -static int fec_enet_set_settings(struct net_device *dev, +static int fec_enet_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; if (!phydev) @@ -896,14 +896,14 @@ static int fec_enet_set_settings(struct net_device *dev, return phy_ethtool_sset(phydev, cmd); } -static void fec_enet_get_drvinfo(struct net_device *dev, +static void fec_enet_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); strcpy(info->driver, fep->pdev->dev.driver->name); strcpy(info->version, "Revision: 1.0"); - strcpy(info->bus_info, dev_name(&dev->dev)); + strcpy(info->bus_info, dev_name(&ndev->dev)); } static struct ethtool_ops fec_enet_ethtool_ops = { @@ -913,12 +913,12 @@ static struct ethtool_ops fec_enet_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; - if (!netif_running(dev)) + if (!netif_running(ndev)) return -EINVAL; if (!phydev) @@ -927,9 +927,9 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return phy_mii_ioctl(phydev, rq, cmd); } -static void fec_enet_free_buffers(struct net_device *dev) +static void fec_enet_free_buffers(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); int i; struct sk_buff *skb; struct bufdesc *bdp; @@ -939,7 +939,7 @@ static void fec_enet_free_buffers(struct net_device *dev) skb = fep->rx_skbuff[i]; if (bdp->cbd_bufaddr) - dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, + dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); if (skb) dev_kfree_skb(skb); @@ -951,9 +951,9 @@ static void fec_enet_free_buffers(struct net_device *dev) kfree(fep->tx_bounce[i]); } -static int fec_enet_alloc_buffers(struct net_device *dev) +static int fec_enet_alloc_buffers(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); int i; struct sk_buff *skb; struct bufdesc *bdp; @@ -962,12 +962,12 @@ static int fec_enet_alloc_buffers(struct net_device *dev) for (i = 0; i < RX_RING_SIZE; i++) { skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE); if (!skb) { - fec_enet_free_buffers(dev); + fec_enet_free_buffers(ndev); return -ENOMEM; } fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + bdp->cbd_bufaddr = dma_map_single(&ndev->dev, skb->data, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); bdp->cbd_sc = BD_ENET_RX_EMPTY; bdp++; @@ -994,47 +994,47 @@ static int fec_enet_alloc_buffers(struct net_device *dev) } static int -fec_enet_open(struct net_device *dev) +fec_enet_open(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); int ret; /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ - ret = fec_enet_alloc_buffers(dev); + ret = fec_enet_alloc_buffers(ndev); if (ret) return ret; /* Probe and connect to PHY when open the interface */ - ret = fec_enet_mii_probe(dev); + ret = fec_enet_mii_probe(ndev); if (ret) { - fec_enet_free_buffers(dev); + fec_enet_free_buffers(ndev); return ret; } phy_start(fep->phy_dev); - netif_start_queue(dev); + netif_start_queue(ndev); fep->opened = 1; return 0; } static int -fec_enet_close(struct net_device *dev) +fec_enet_close(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); /* Don't know what to do yet. */ fep->opened = 0; - netif_stop_queue(dev); - fec_stop(dev); + netif_stop_queue(ndev); + fec_stop(ndev); if (fep->phy_dev) { phy_stop(fep->phy_dev); phy_disconnect(fep->phy_dev); } - fec_enet_free_buffers(dev); + fec_enet_free_buffers(ndev); return 0; } @@ -1052,14 +1052,14 @@ fec_enet_close(struct net_device *dev) #define HASH_BITS 6 /* #bits in hash */ #define CRC32_POLY 0xEDB88320 -static void set_multicast_list(struct net_device *dev) +static void set_multicast_list(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct netdev_hw_addr *ha; unsigned int i, bit, data, crc, tmp; unsigned char hash; - if (dev->flags & IFF_PROMISC) { + if (ndev->flags & IFF_PROMISC) { tmp = readl(fep->hwp + FEC_R_CNTRL); tmp |= 0x8; writel(tmp, fep->hwp + FEC_R_CNTRL); @@ -1070,7 +1070,7 @@ static void set_multicast_list(struct net_device *dev) tmp &= ~0x8; writel(tmp, fep->hwp + FEC_R_CNTRL); - if (dev->flags & IFF_ALLMULTI) { + if (ndev->flags & IFF_ALLMULTI) { /* Catch all multicast addresses, so set the * filter to all 1's */ @@ -1085,7 +1085,7 @@ static void set_multicast_list(struct net_device *dev) writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - netdev_for_each_mc_addr(ha, dev) { + netdev_for_each_mc_addr(ha, ndev) { /* Only support group multicast for now */ if (!(ha->addr[0] & 1)) continue; @@ -1093,7 +1093,7 @@ static void set_multicast_list(struct net_device *dev) /* calculate crc32 value of mac address */ crc = 0xffffffff; - for (i = 0; i < dev->addr_len; i++) { + for (i = 0; i < ndev->addr_len; i++) { data = ha->addr[i]; for (bit = 0; bit < 8; bit++, data >>= 1) { crc = (crc >> 1) ^ @@ -1120,20 +1120,20 @@ static void set_multicast_list(struct net_device *dev) /* Set a MAC change in hardware. */ static int -fec_set_mac_address(struct net_device *dev, void *p) +fec_set_mac_address(struct net_device *ndev, void *p) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); - writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) | - (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), + writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) | + (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24), fep->hwp + FEC_ADDR_LOW); - writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), + writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24), fep->hwp + FEC_ADDR_HIGH); return 0; } @@ -1154,9 +1154,9 @@ static const struct net_device_ops fec_netdev_ops = { * XXX: We need to clean up on failure exits here. * */ -static int fec_enet_init(struct net_device *dev) +static int fec_enet_init(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); struct bufdesc *cbd_base; struct bufdesc *bdp; int i; @@ -1171,19 +1171,19 @@ static int fec_enet_init(struct net_device *dev) spin_lock_init(&fep->hw_lock); - fep->netdev = dev; + fep->netdev = ndev; /* Get the Ethernet address */ - fec_get_mac(dev); + fec_get_mac(ndev); /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; fep->tx_bd_base = cbd_base + RX_RING_SIZE; /* The FEC Ethernet specific entries in the device structure */ - dev->watchdog_timeo = TX_TIMEOUT; - dev->netdev_ops = &fec_netdev_ops; - dev->ethtool_ops = &fec_enet_ethtool_ops; + ndev->watchdog_timeo = TX_TIMEOUT; + ndev->netdev_ops = &fec_netdev_ops; + ndev->ethtool_ops = &fec_enet_ethtool_ops; /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; @@ -1212,7 +1212,7 @@ static int fec_enet_init(struct net_device *dev) bdp--; bdp->cbd_sc |= BD_SC_WRAP; - fec_restart(dev, 0); + fec_restart(ndev, 0); return 0; } @@ -1222,9 +1222,9 @@ static int fec_enet_init(struct net_device *dev) * duplex. */ static void -fec_restart(struct net_device *dev, int duplex) +fec_restart(struct net_device *ndev, int duplex) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); int i; @@ -1239,7 +1239,7 @@ fec_restart(struct net_device *dev, int duplex) * so need to reconfigure it. */ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - memcpy(&temp_mac, dev->dev_addr, ETH_ALEN); + memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); } @@ -1339,9 +1339,9 @@ fec_restart(struct net_device *dev, int duplex) } static void -fec_stop(struct net_device *dev) +fec_stop(struct net_device *ndev) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = netdev_priv(ndev); /* We cannot expect a graceful transmit stop without link !!! */ if (fep->link) { From db8880bc92657559320ba8384acb2547d4255521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 19 Jan 2011 20:26:39 +0100 Subject: [PATCH 10/14] net/fec: some whitespace cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few of these were found and reported by Lothar Waßmann. Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index c70503a065bb..4c888f1825a3 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -182,7 +182,7 @@ struct fec_enet_private { struct bufdesc *rx_bd_base; struct bufdesc *tx_bd_base; /* The next free ring entry */ - struct bufdesc *cur_rx, *cur_tx; + struct bufdesc *cur_rx, *cur_tx; /* The ring entries to be free()ed */ struct bufdesc *dirty_tx; @@ -190,15 +190,15 @@ struct fec_enet_private { /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ spinlock_t hw_lock; - struct platform_device *pdev; + struct platform_device *pdev; int opened; /* Phylib and MDIO interface */ - struct mii_bus *mii_bus; - struct phy_device *phy_dev; - int mii_timeout; - uint phy_speed; + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + int mii_timeout; + uint phy_speed; phy_interface_t phy_interface; int link; int full_duplex; @@ -525,8 +525,8 @@ fec_enet_rx(struct net_device *ndev) ndev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); - dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, - DMA_FROM_DEVICE); + dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, + DMA_FROM_DEVICE); if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); @@ -550,7 +550,7 @@ fec_enet_rx(struct net_device *ndev) netif_rx(skb); } - bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen, + bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen, DMA_FROM_DEVICE); rx_processing_done: /* Clear the status flags for this buffer */ @@ -1034,7 +1034,7 @@ fec_enet_close(struct net_device *ndev) phy_disconnect(fep->phy_dev); } - fec_enet_free_buffers(ndev); + fec_enet_free_buffers(ndev); return 0; } @@ -1147,7 +1147,7 @@ static const struct net_device_ops fec_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = fec_timeout, .ndo_set_mac_address = fec_set_mac_address, - .ndo_do_ioctl = fec_enet_ioctl, + .ndo_do_ioctl = fec_enet_ioctl, }; /* From 45993653bd5935dbf975bc26a834f2ff23c9f914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 19 Jan 2011 20:47:04 +0100 Subject: [PATCH 11/14] net/fec: reorder functions a bit allows removing forward declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 363 +++++++++++++++++++++++----------------------- 1 file changed, 179 insertions(+), 184 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 4c888f1825a3..3f5dfe2e41ac 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -205,13 +205,6 @@ struct fec_enet_private { struct completion mdio_done; }; -static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); -static void fec_enet_tx(struct net_device *ndev); -static void fec_enet_rx(struct net_device *ndev); -static int fec_enet_close(struct net_device *ndev); -static void fec_restart(struct net_device *ndev, int duplex); -static void fec_stop(struct net_device *ndev); - /* FEC MII MMFR bits definition */ #define FEC_MMFR_ST (1 << 30) #define FEC_MMFR_OP_READ (2 << 28) @@ -335,6 +328,148 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +/* This function is called to start or restart the FEC during a link + * change. This only happens when switching between half and full + * duplex. + */ +static void +fec_restart(struct net_device *ndev, int duplex) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + const struct platform_device_id *id_entry = + platform_get_device_id(fep->pdev); + int i; + u32 val, temp_mac[2]; + + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); + udelay(10); + + /* + * enet-mac reset will reset mac address registers too, + * so need to reconfigure it. + */ + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); + writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); + writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); + } + + /* Clear any outstanding interrupt. */ + writel(0xffc00000, fep->hwp + FEC_IEVENT); + + /* Reset all multicast. */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); +#ifndef CONFIG_M5272 + writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +#endif + + /* Set maximum receive buffer size. */ + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); + + /* Set receive and transmit descriptor base. */ + writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); + writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, + fep->hwp + FEC_X_DES_START); + + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->cur_rx = fep->rx_bd_base; + + /* Reset SKB transmit buffers. */ + fep->skb_cur = fep->skb_dirty = 0; + for (i = 0; i <= TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i]) { + dev_kfree_skb_any(fep->tx_skbuff[i]); + fep->tx_skbuff[i] = NULL; + } + } + + /* Enable MII mode */ + if (duplex) { + /* MII enable / FD enable */ + writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); + writel(0x04, fep->hwp + FEC_X_CNTRL); + } else { + /* MII enable / No Rcv on Xmit */ + writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL); + writel(0x0, fep->hwp + FEC_X_CNTRL); + } + fep->full_duplex = duplex; + + /* Set MII speed */ + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + + /* + * The phy interface and speed need to get configured + * differently on enet-mac. + */ + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + val = readl(fep->hwp + FEC_R_CNTRL); + + /* MII or RMII */ + if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) + val |= (1 << 8); + else + val &= ~(1 << 8); + + /* 10M or 100M */ + if (fep->phy_dev && fep->phy_dev->speed == SPEED_100) + val &= ~(1 << 9); + else + val |= (1 << 9); + + writel(val, fep->hwp + FEC_R_CNTRL); + } else { +#ifdef FEC_MIIGSK_ENR + if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { + /* disable the gasket and wait */ + writel(0, fep->hwp + FEC_MIIGSK_ENR); + while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) + udelay(1); + + /* + * configure the gasket: + * RMII, 50 MHz, no loopback, no echo + */ + writel(1, fep->hwp + FEC_MIIGSK_CFGR); + + /* re-enable the gasket */ + writel(2, fep->hwp + FEC_MIIGSK_ENR); + } +#endif + } + + /* And last, enable the transmit and receive processing */ + writel(2, fep->hwp + FEC_ECNTRL); + writel(0, fep->hwp + FEC_R_DES_ACTIVE); + + /* Enable interrupts we wish to service */ + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); +} + +static void +fec_stop(struct net_device *ndev) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + /* We cannot expect a graceful transmit stop without link !!! */ + if (fep->link) { + writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ + udelay(10); + if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) + printk("fec_stop : Graceful transmit stop did not complete !\n"); + } + + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); + udelay(10); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); +} + + static void fec_timeout(struct net_device *ndev) { @@ -346,42 +481,6 @@ fec_timeout(struct net_device *ndev) netif_wake_queue(ndev); } -static irqreturn_t -fec_enet_interrupt(int irq, void *dev_id) -{ - struct net_device *ndev = dev_id; - struct fec_enet_private *fep = netdev_priv(ndev); - uint int_events; - irqreturn_t ret = IRQ_NONE; - - do { - int_events = readl(fep->hwp + FEC_IEVENT); - writel(int_events, fep->hwp + FEC_IEVENT); - - if (int_events & FEC_ENET_RXF) { - ret = IRQ_HANDLED; - fec_enet_rx(ndev); - } - - /* Transmit OK, or non-fatal error. Update the buffer - * descriptors. FEC handles all errors, we just discover - * them as part of the transmit process. - */ - if (int_events & FEC_ENET_TXF) { - ret = IRQ_HANDLED; - fec_enet_tx(ndev); - } - - if (int_events & FEC_ENET_MII) { - ret = IRQ_HANDLED; - complete(&fep->mdio_done); - } - } while (int_events); - - return ret; -} - - static void fec_enet_tx(struct net_device *ndev) { @@ -576,6 +675,43 @@ rx_processing_done: spin_unlock(&fep->hw_lock); } +static irqreturn_t +fec_enet_interrupt(int irq, void *dev_id) +{ + struct net_device *ndev = dev_id; + struct fec_enet_private *fep = netdev_priv(ndev); + uint int_events; + irqreturn_t ret = IRQ_NONE; + + do { + int_events = readl(fep->hwp + FEC_IEVENT); + writel(int_events, fep->hwp + FEC_IEVENT); + + if (int_events & FEC_ENET_RXF) { + ret = IRQ_HANDLED; + fec_enet_rx(ndev); + } + + /* Transmit OK, or non-fatal error. Update the buffer + * descriptors. FEC handles all errors, we just discover + * them as part of the transmit process. + */ + if (int_events & FEC_ENET_TXF) { + ret = IRQ_HANDLED; + fec_enet_tx(ndev); + } + + if (int_events & FEC_ENET_MII) { + ret = IRQ_HANDLED; + complete(&fep->mdio_done); + } + } while (int_events); + + return ret; +} + + + /* ------------------------------------------------------------------------- */ static void __inline__ fec_get_mac(struct net_device *ndev) { @@ -1217,147 +1353,6 @@ static int fec_enet_init(struct net_device *ndev) return 0; } -/* This function is called to start or restart the FEC during a link - * change. This only happens when switching between half and full - * duplex. - */ -static void -fec_restart(struct net_device *ndev, int duplex) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - int i; - u32 val, temp_mac[2]; - - /* Whack a reset. We should wait for this. */ - writel(1, fep->hwp + FEC_ECNTRL); - udelay(10); - - /* - * enet-mac reset will reset mac address registers too, - * so need to reconfigure it. - */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); - writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); - writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); - } - - /* Clear any outstanding interrupt. */ - writel(0xffc00000, fep->hwp + FEC_IEVENT); - - /* Reset all multicast. */ - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); -#ifndef CONFIG_M5272 - writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -#endif - - /* Set maximum receive buffer size. */ - writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - - /* Set receive and transmit descriptor base. */ - writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); - writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, - fep->hwp + FEC_X_DES_START); - - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->cur_rx = fep->rx_bd_base; - - /* Reset SKB transmit buffers. */ - fep->skb_cur = fep->skb_dirty = 0; - for (i = 0; i <= TX_RING_MOD_MASK; i++) { - if (fep->tx_skbuff[i]) { - dev_kfree_skb_any(fep->tx_skbuff[i]); - fep->tx_skbuff[i] = NULL; - } - } - - /* Enable MII mode */ - if (duplex) { - /* MII enable / FD enable */ - writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); - writel(0x04, fep->hwp + FEC_X_CNTRL); - } else { - /* MII enable / No Rcv on Xmit */ - writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL); - writel(0x0, fep->hwp + FEC_X_CNTRL); - } - fep->full_duplex = duplex; - - /* Set MII speed */ - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - - /* - * The phy interface and speed need to get configured - * differently on enet-mac. - */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - val = readl(fep->hwp + FEC_R_CNTRL); - - /* MII or RMII */ - if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) - val |= (1 << 8); - else - val &= ~(1 << 8); - - /* 10M or 100M */ - if (fep->phy_dev && fep->phy_dev->speed == SPEED_100) - val &= ~(1 << 9); - else - val |= (1 << 9); - - writel(val, fep->hwp + FEC_R_CNTRL); - } else { -#ifdef FEC_MIIGSK_ENR - if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { - /* disable the gasket and wait */ - writel(0, fep->hwp + FEC_MIIGSK_ENR); - while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) - udelay(1); - - /* - * configure the gasket: - * RMII, 50 MHz, no loopback, no echo - */ - writel(1, fep->hwp + FEC_MIIGSK_CFGR); - - /* re-enable the gasket */ - writel(2, fep->hwp + FEC_MIIGSK_ENR); - } -#endif - } - - /* And last, enable the transmit and receive processing */ - writel(2, fep->hwp + FEC_ECNTRL); - writel(0, fep->hwp + FEC_R_DES_ACTIVE); - - /* Enable interrupts we wish to service */ - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); -} - -static void -fec_stop(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - /* We cannot expect a graceful transmit stop without link !!! */ - if (fep->link) { - writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ - udelay(10); - if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) - printk("fec_stop : Graceful transmit stop did not complete !\n"); - } - - /* Whack a reset. We should wait for this. */ - writel(1, fep->hwp + FEC_ECNTRL); - udelay(10); - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); -} - static int __devinit fec_probe(struct platform_device *pdev) { From d1ab1f54a1b0fb0ae6479fad6e26983f09fd263a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 20 Jan 2011 09:26:38 +0100 Subject: [PATCH 12/14] net/fec: provide device for dma functions and matching sizes for map and unmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes warnings when CONFIG_DMA_API_DEBUG=y: NULL NULL: DMA-API: device driver tries to free DMA memory it has not allocated [device address=0x000000004781a020] [size=64 bytes] net eth0: DMA-API: device driver frees DMA memory with different size [device address=0x000000004781a020] [map size=2048 bytes] [unmap size=64 bytes] Moreover pass the platform device to dma_{,un}map_single which makes more sense because the logical network device doesn't know anything about dma. Passing the platform device was a suggestion by Lothar Waßmann. Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 3f5dfe2e41ac..0c984d6b25f6 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -297,7 +297,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* Push the data cache so the CPM does not get stale memory * data. */ - bdp->cbd_bufaddr = dma_map_single(&ndev->dev, bufaddr, + bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, @@ -497,7 +497,8 @@ fec_enet_tx(struct net_device *ndev) if (bdp == fep->cur_tx && fep->tx_full == 0) break; - dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); bdp->cbd_bufaddr = 0; skb = fep->tx_skbuff[fep->skb_dirty]; @@ -624,8 +625,8 @@ fec_enet_rx(struct net_device *ndev) ndev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); - dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, - DMA_FROM_DEVICE); + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); @@ -649,8 +650,8 @@ fec_enet_rx(struct net_device *ndev) netif_rx(skb); } - bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen, - DMA_FROM_DEVICE); + bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data, + FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); rx_processing_done: /* Clear the status flags for this buffer */ status &= ~BD_ENET_RX_STATS; @@ -1075,7 +1076,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) skb = fep->rx_skbuff[i]; if (bdp->cbd_bufaddr) - dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr, + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); if (skb) dev_kfree_skb(skb); @@ -1103,7 +1104,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) } fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = dma_map_single(&ndev->dev, skb->data, + bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); bdp->cbd_sc = BD_ENET_RX_EMPTY; bdp++; From b3cde36cf1e19f696cb302ea426b5cf6ab4afb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 25 Jan 2011 18:03:37 +0100 Subject: [PATCH 13/14] net/fec: postpone unsetting driver data until the hardware is stopped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Lothar Waßmann Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 0c984d6b25f6..c3229713b1e2 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1465,8 +1465,6 @@ fec_drv_remove(struct platform_device *pdev) struct fec_enet_private *fep = netdev_priv(ndev); struct resource *r; - platform_set_drvdata(pdev, NULL); - fec_stop(ndev); fec_enet_mii_remove(fep); clk_disable(fep->clk); @@ -1479,6 +1477,8 @@ fec_drv_remove(struct platform_device *pdev) BUG_ON(!r); release_mem_region(r->start, resource_size(r)); + platform_set_drvdata(pdev, NULL); + return 0; } From cd1f402c18cf31b38bb304bc0c320669762ac50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 25 Jan 2011 22:11:25 +0100 Subject: [PATCH 14/14] net/fec: enable flow control and length check on enet-mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also optimize not to reread the value written to FEC_R_CNTRL. Signed-off-by: Uwe Kleine-König --- drivers/net/fec.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index c3229713b1e2..74798bee672e 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -339,7 +339,8 @@ fec_restart(struct net_device *ndev, int duplex) const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); int i; - u32 val, temp_mac[2]; + u32 temp_mac[2]; + u32 rcntl = OPT_FRAME_SIZE | 0x04; /* Whack a reset. We should wait for this. */ writel(1, fep->hwp + FEC_ECNTRL); @@ -388,14 +389,14 @@ fec_restart(struct net_device *ndev, int duplex) /* Enable MII mode */ if (duplex) { - /* MII enable / FD enable */ - writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); + /* FD enable */ writel(0x04, fep->hwp + FEC_X_CNTRL); } else { - /* MII enable / No Rcv on Xmit */ - writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL); + /* No Rcv on Xmit */ + rcntl |= 0x02; writel(0x0, fep->hwp + FEC_X_CNTRL); } + fep->full_duplex = duplex; /* Set MII speed */ @@ -406,21 +407,21 @@ fec_restart(struct net_device *ndev, int duplex) * differently on enet-mac. */ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - val = readl(fep->hwp + FEC_R_CNTRL); + /* Enable flow control and length check */ + rcntl |= 0x40000000 | 0x00000020; /* MII or RMII */ if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) - val |= (1 << 8); + rcntl |= (1 << 8); else - val &= ~(1 << 8); + rcntl &= ~(1 << 8); /* 10M or 100M */ if (fep->phy_dev && fep->phy_dev->speed == SPEED_100) - val &= ~(1 << 9); + rcntl &= ~(1 << 9); else - val |= (1 << 9); + rcntl |= (1 << 9); - writel(val, fep->hwp + FEC_R_CNTRL); } else { #ifdef FEC_MIIGSK_ENR if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { @@ -440,6 +441,7 @@ fec_restart(struct net_device *ndev, int duplex) } #endif } + writel(rcntl, fep->hwp + FEC_R_CNTRL); /* And last, enable the transmit and receive processing */ writel(2, fep->hwp + FEC_ECNTRL);