Jelajahi Sumber

ag71xx: keep the rx engine stopped while the link is not up, should hopefully fix stability issues from #9405

SVN-Revision: 27567
Felix Fietkau 14 tahun lalu
induk
melakukan
2806c75c07
1 mengubah file dengan 91 tambahan dan 91 penghapusan
  1. 91 91
      target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c

+ 91 - 91
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c

@@ -343,93 +343,6 @@ static unsigned char *ag71xx_speed_str(struct ag71xx *ag)
 	return "?";
 }
 
-void ag71xx_link_adjust(struct ag71xx *ag)
-{
-	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
-	u32 cfg2;
-	u32 ifctl;
-	u32 fifo5;
-	u32 mii_speed;
-
-	if (!ag->link) {
-		netif_carrier_off(ag->dev);
-		if (netif_msg_link(ag))
-			printk(KERN_INFO "%s: link down\n", ag->dev->name);
-		return;
-	}
-
-	cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
-	cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
-	cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;
-
-	ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
-	ifctl &= ~(MAC_IFCTL_SPEED);
-
-	fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
-	fifo5 &= ~FIFO_CFG5_BM;
-
-	switch (ag->speed) {
-	case SPEED_1000:
-		mii_speed =  MII_CTRL_SPEED_1000;
-		cfg2 |= MAC_CFG2_IF_1000;
-		fifo5 |= FIFO_CFG5_BM;
-		break;
-	case SPEED_100:
-		mii_speed = MII_CTRL_SPEED_100;
-		cfg2 |= MAC_CFG2_IF_10_100;
-		ifctl |= MAC_IFCTL_SPEED;
-		break;
-	case SPEED_10:
-		mii_speed = MII_CTRL_SPEED_10;
-		cfg2 |= MAC_CFG2_IF_10_100;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	if (pdata->is_ar91xx)
-		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
-	else if (pdata->is_ar724x)
-		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3);
-	else
-		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);
-
-	if (pdata->set_pll)
-		pdata->set_pll(ag->speed);
-
-	ag71xx_mii_ctrl_set_speed(ag, mii_speed);
-
-	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
-	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
-	ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
-
-	netif_carrier_on(ag->dev);
-	if (netif_msg_link(ag))
-		printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
-			ag->dev->name,
-			ag71xx_speed_str(ag),
-			(DUPLEX_FULL == ag->duplex) ? "Full" : "Half");
-
-	DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
-		ag->dev->name,
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));
-
-	DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
-		ag->dev->name,
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
-		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));
-
-	DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
-		ag->dev->name,
-		ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
-		ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
-		ag71xx_mii_ctrl_rr(ag));
-}
-
 static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
 {
 	u32 t;
@@ -560,10 +473,98 @@ static void ag71xx_hw_start(struct ag71xx *ag)
 
 static void ag71xx_hw_stop(struct ag71xx *ag)
 {
-	/* disable all interrupts */
+	/* disable all interrupts and stop the rx engine */
 	ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0);
+	ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
+}
 
-	ag71xx_dma_reset(ag);
+void ag71xx_link_adjust(struct ag71xx *ag)
+{
+	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
+	u32 cfg2;
+	u32 ifctl;
+	u32 fifo5;
+	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);
+		return;
+	}
+
+	cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
+	cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
+	cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;
+
+	ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
+	ifctl &= ~(MAC_IFCTL_SPEED);
+
+	fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
+	fifo5 &= ~FIFO_CFG5_BM;
+
+	switch (ag->speed) {
+	case SPEED_1000:
+		mii_speed =  MII_CTRL_SPEED_1000;
+		cfg2 |= MAC_CFG2_IF_1000;
+		fifo5 |= FIFO_CFG5_BM;
+		break;
+	case SPEED_100:
+		mii_speed = MII_CTRL_SPEED_100;
+		cfg2 |= MAC_CFG2_IF_10_100;
+		ifctl |= MAC_IFCTL_SPEED;
+		break;
+	case SPEED_10:
+		mii_speed = MII_CTRL_SPEED_10;
+		cfg2 |= MAC_CFG2_IF_10_100;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	if (pdata->is_ar91xx)
+		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
+	else if (pdata->is_ar724x)
+		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3);
+	else
+		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);
+
+	if (pdata->set_pll)
+		pdata->set_pll(ag->speed);
+
+	ag71xx_mii_ctrl_set_speed(ag, mii_speed);
+
+	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
+	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",
+			ag->dev->name,
+			ag71xx_speed_str(ag),
+			(DUPLEX_FULL == ag->duplex) ? "Full" : "Half");
+
+	DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
+		ag->dev->name,
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));
+
+	DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
+		ag->dev->name,
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
+		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));
+
+	DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
+		ag->dev->name,
+		ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
+		ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
+		ag71xx_mii_ctrl_rr(ag));
 }
 
 static int ag71xx_open(struct net_device *dev)
@@ -585,8 +586,6 @@ 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;
@@ -609,6 +608,7 @@ static int ag71xx_stop(struct net_device *dev)
 	netif_stop_queue(dev);
 
 	ag71xx_hw_stop(ag);
+	ag71xx_dma_reset(ag);
 
 	napi_disable(&ag->napi);
 	del_timer_sync(&ag->oom_timer);