ソースを参照

ar71xx: detect link on LAN ports

SVN-Revision: 26922
Matteo Croce 15 年 前
コミット
4deecea26b

+ 1 - 0
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h

@@ -162,6 +162,7 @@ struct ag71xx {
 	int			duplex;
 
 	struct work_struct	restart_work;
+	struct delayed_work	link_work;
 	struct timer_list	oom_timer;
 
 #ifdef CONFIG_AG71XX_DEBUG_FS

+ 29 - 1
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c

@@ -828,6 +828,30 @@ static struct ar7240sw *ar7240_probe(struct ag71xx *ag)
 	return as;
 }
 
+static void link_function(struct work_struct *work) {
+	struct ag71xx *ag = container_of(work, struct ag71xx, link_work.work);
+	unsigned long flags;
+	int i;
+	int status = 0;
+
+	for (i = 0; i < 4; i++) {
+		int link = ar7240sw_phy_read(ag->mii_bus, i, MII_BMSR);
+		if(link & BMSR_LSTATUS) {
+			status = 1;
+			break;
+		}
+	}
+
+	spin_lock_irqsave(&ag->lock, flags);
+	if(status != ag->link) {
+		ag->link = status;
+		ag71xx_link_adjust(ag);
+	}
+	spin_unlock_irqrestore(&ag->lock, flags);
+
+	schedule_delayed_work(&ag->link_work, HZ / 2);
+}
+
 void ag71xx_ar7240_start(struct ag71xx *ag)
 {
 	struct ar7240sw *as = ag->phy_priv;
@@ -836,15 +860,17 @@ void ag71xx_ar7240_start(struct ag71xx *ag)
 	ar7240sw_setup(as);
 
 	ag->speed = SPEED_1000;
-	ag->link = 1;
 	ag->duplex = 1;
 
 	ar7240_set_addr(as, ag->dev->dev_addr);
 	ar7240_hw_apply(&as->swdev);
+
+	schedule_delayed_work(&ag->link_work, HZ / 10);
 }
 
 void ag71xx_ar7240_stop(struct ag71xx *ag)
 {
+	cancel_delayed_work_sync(&ag->link_work);
 }
 
 int __devinit ag71xx_ar7240_init(struct ag71xx *ag)
@@ -858,6 +884,8 @@ int __devinit ag71xx_ar7240_init(struct ag71xx *ag)
 	ag->phy_priv = as;
 	ar7240sw_reset(as);
 
+	INIT_DELAYED_WORK(&ag->link_work, link_function);
+
 	return 0;
 }
 

+ 2 - 2
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c

@@ -48,9 +48,9 @@ void ag71xx_phy_start(struct ag71xx *ag)
 
 	if (ag->phy_dev) {
 		phy_start(ag->phy_dev);
+	} else if (pdata->has_ar7240_switch) {
+		ag71xx_ar7240_start(ag);
 	} else {
-		if (pdata->has_ar7240_switch)
-			ag71xx_ar7240_start(ag);
 		ag->link = 1;
 		ag71xx_link_adjust(ag);
 	}