2012.08.25. 16:51 keltezéssel, Mark Mentovai írta:
> Is there a way to make the link state drop on an ag71xx interface, so that 
> it appears to whatever equipment is connected to the port that the cable 
> has been disconnected?
> 
> I've got a WNDR3700-family device and I need to make it appear to the 
> equipment connected to its eth1 interface that the cable has been 
> disconnected. "ifconfig eth1 down" doesn't alter the link state at all. 
> It'd be OK if the state just dropped momentarily and then returned. So 
> far, the best I've been able to do is reboot the entire WNDR3700. That's a 
> more drastic approach than I'd like to use, as there are other things 
> happening on the system that I'd rather not interrupt.
> 
> I'm very open to the possibility of ag71xx driver changes to make this 
> work (either as a local change or something for wider distribution) but I 
> haven't found any data sheets for this device, so I'd basically be 
> starting by stabbing around in the dark.
> 
> Does anyone have any pointers?
> 

The problem is that PHYLIB in Linux does not fully stops the PHY device when a
driver issues a phy_stop call.

Copy the attached patches into 'target/linux/ar71xx/patches-3.3', then do a
'make target/linux/clean world'. With these patches, the PHY of the WAN port
will be powered down after 'ifconfig eth1 down' (on the WNDR3700 at least).

Regards,
Gabor
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -510,6 +510,18 @@ static inline int phy_read_status(struct
 	return phydev->drv->read_status(phydev);
 }
 
+static inline void phy_suspend(struct phy_device *phydev)
+{
+	if (phydev->drv->suspend)
+		phydev->drv->suspend(phydev);
+}
+
+static inline void phy_resume(struct phy_device *phydev)
+{
+	if (phydev->drv->resume)
+		phydev->drv->resume(phydev);
+}
+
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_config_aneg(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
--- a/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c
+++ b/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c
@@ -47,6 +47,7 @@ void ag71xx_phy_start(struct ag71xx *ag)
 	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
 
 	if (ag->phy_dev) {
+		phy_resume(ag->phy_dev);
 		phy_start(ag->phy_dev);
 	} else if (pdata->switch_data) {
 		ag71xx_ar7240_start(ag);
@@ -61,10 +62,12 @@ void ag71xx_phy_stop(struct ag71xx *ag)
 	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
 	unsigned long flags;
 
-	if (ag->phy_dev)
+	if (ag->phy_dev) {
 		phy_stop(ag->phy_dev);
-	else if (pdata->switch_data)
+		phy_suspend(ag->phy_dev);
+	} else if (pdata->switch_data) {
 		ag71xx_ar7240_stop(ag);
+	}
 
 	spin_lock_irqsave(&ag->lock, flags);
 	if (ag->link) {
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to