diff options
3 files changed, 32 insertions, 3 deletions
| diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index 342d12186..30caaff02 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h +++ b/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 diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c index 1bc7f58c1..d84cc81ae 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c +++ b/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;  } diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c index d0bae03b1..75500277f 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c +++ b/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);  	} | 
