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
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel