aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/files/drivers/net/ag71xx
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-06-01 18:15:43 +0000
committerFelix Fietkau <nbd@openwrt.org>2011-06-01 18:15:43 +0000
commit31dd60689e00e674c1767665e14d4eb841b11137 (patch)
treee5451677cd406b6ec2ed3917e0d6ccf9dde1a1ac /target/linux/ar71xx/files/drivers/net/ag71xx
parent9acb81d9af4cef2679f0475bd2b0f18963c795de (diff)
downloadupstream-31dd60689e00e674c1767665e14d4eb841b11137.tar.gz
upstream-31dd60689e00e674c1767665e14d4eb841b11137.tar.bz2
upstream-31dd60689e00e674c1767665e14d4eb841b11137.zip
Revert "ar71xx: only enable the rx engine after the link is up..."
It messes up the DMA state when the link goes down SVN-Revision: 27088
Diffstat (limited to 'target/linux/ar71xx/files/drivers/net/ag71xx')
-rw-r--r--target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c135
1 files changed, 67 insertions, 68 deletions
diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c
index f1eb0716a0..6bc4fd3560 100644
--- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c
+++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c
@@ -343,71 +343,6 @@ static unsigned char *ag71xx_speed_str(struct ag71xx *ag)
return "?";
}
-static void ag71xx_dma_reset(struct ag71xx *ag)
-{
- u32 val;
- int i;
-
- ag71xx_dump_dma_regs(ag);
-
- /* stop RX and TX */
- ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
- ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
-
- /*
- * give the hardware some time to really stop all rx/tx activity
- * clearing the descriptors too early causes random memory corruption
- */
- mdelay(1);
-
- /* clear descriptor addresses */
- ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0);
- ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0);
-
- /* clear pending RX/TX interrupts */
- for (i = 0; i < 256; i++) {
- ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR);
- ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
- }
-
- /* clear pending errors */
- ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF);
- ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR);
-
- val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS);
- if (val)
- printk(KERN_ALERT "%s: unable to clear DMA Rx status: %08x\n",
- ag->dev->name, val);
-
- val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS);
-
- /* mask out reserved bits */
- val &= ~0xff000000;
-
- if (val)
- printk(KERN_ALERT "%s: unable to clear DMA Tx status: %08x\n",
- ag->dev->name, val);
-
- ag71xx_dump_dma_regs(ag);
-}
-
-static void ag71xx_hw_start(struct ag71xx *ag)
-{
- /* start RX engine */
- ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
-
- /* enable interrupts */
- ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, AG71XX_INT_INIT);
-}
-
-static void ag71xx_hw_stop(struct ag71xx *ag)
-{
- /* disable all interrupts */
- ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0);
-
- ag71xx_dma_reset(ag);
-}
-
void ag71xx_link_adjust(struct ag71xx *ag)
{
struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
@@ -417,7 +352,6 @@ void ag71xx_link_adjust(struct ag71xx *ag)
u32 mii_speed;
if (!ag->link) {
- ag71xx_hw_stop(ag);
netif_carrier_off(ag->dev);
if (netif_msg_link(ag))
printk(KERN_INFO "%s: link down\n", ag->dev->name);
@@ -470,8 +404,6 @@ void ag71xx_link_adjust(struct ag71xx *ag)
ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
- ag71xx_hw_start(ag);
-
netif_carrier_on(ag->dev);
if (netif_msg_link(ag))
printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
@@ -511,6 +443,54 @@ static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
ag71xx_wr(ag, AG71XX_REG_MAC_ADDR2, t);
}
+static void ag71xx_dma_reset(struct ag71xx *ag)
+{
+ u32 val;
+ int i;
+
+ ag71xx_dump_dma_regs(ag);
+
+ /* stop RX and TX */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
+ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
+
+ /*
+ * give the hardware some time to really stop all rx/tx activity
+ * clearing the descriptors too early causes random memory corruption
+ */
+ mdelay(1);
+
+ /* clear descriptor addresses */
+ ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0);
+ ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0);
+
+ /* clear pending RX/TX interrupts */
+ for (i = 0; i < 256; i++) {
+ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR);
+ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
+ }
+
+ /* clear pending errors */
+ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF);
+ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR);
+
+ val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS);
+ if (val)
+ printk(KERN_ALERT "%s: unable to clear DMA Rx status: %08x\n",
+ ag->dev->name, val);
+
+ val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS);
+
+ /* mask out reserved bits */
+ val &= ~0xff000000;
+
+ if (val)
+ printk(KERN_ALERT "%s: unable to clear DMA Tx status: %08x\n",
+ ag->dev->name, val);
+
+ ag71xx_dump_dma_regs(ag);
+}
+
#define MAC_CFG1_INIT (MAC_CFG1_RXE | MAC_CFG1_TXE | \
MAC_CFG1_SRX | MAC_CFG1_STX)
@@ -569,6 +549,23 @@ static void ag71xx_hw_init(struct ag71xx *ag)
ag71xx_dma_reset(ag);
}
+static void ag71xx_hw_start(struct ag71xx *ag)
+{
+ /* start RX engine */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
+
+ /* enable interrupts */
+ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, AG71XX_INT_INIT);
+}
+
+static void ag71xx_hw_stop(struct ag71xx *ag)
+{
+ /* disable all interrupts */
+ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0);
+
+ ag71xx_dma_reset(ag);
+}
+
static int ag71xx_open(struct net_device *dev)
{
struct ag71xx *ag = netdev_priv(dev);
@@ -588,6 +585,8 @@ static int ag71xx_open(struct net_device *dev)
ag71xx_hw_set_macaddr(ag, dev->dev_addr);
+ ag71xx_hw_start(ag);
+
netif_start_queue(dev);
return 0;