mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	mcs7830: Fix link state detection
The device had an undocumented "feature": it can provide a sequence of spurious link-down status data even if the link is up all the time. A sequence of 10 was seen so update the link state only after the device reports the same link state 20 times. Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Reported-by: Michael Leun <lkml20120218@newton.leun.net> Tested-by: Michael Leun <lkml20120218@newton.leun.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									93ac0ef016
								
							
						
					
					
						commit
						dabdaf0caa
					
				
					 1 changed files with 21 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -117,6 +117,7 @@ enum {
 | 
			
		|||
struct mcs7830_data {
 | 
			
		||||
	u8 multi_filter[8];
 | 
			
		||||
	u8 config;
 | 
			
		||||
	u8 link_counter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char driver_name[] = "MOSCHIP usb-ethernet driver";
 | 
			
		||||
| 
						 | 
				
			
			@ -632,20 +633,31 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 | 
			
		|||
static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 | 
			
		||||
{
 | 
			
		||||
	u8 *buf = urb->transfer_buffer;
 | 
			
		||||
	bool link;
 | 
			
		||||
	bool link, link_changed;
 | 
			
		||||
	struct mcs7830_data *data = mcs7830_get_data(dev);
 | 
			
		||||
 | 
			
		||||
	if (urb->actual_length < 16)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	link = !(buf[1] & 0x20);
 | 
			
		||||
	if (netif_carrier_ok(dev->net) != link) {
 | 
			
		||||
		if (link) {
 | 
			
		||||
			netif_carrier_on(dev->net);
 | 
			
		||||
			usbnet_defer_kevent(dev, EVENT_LINK_RESET);
 | 
			
		||||
		} else
 | 
			
		||||
			netif_carrier_off(dev->net);
 | 
			
		||||
		netdev_dbg(dev->net, "Link Status is: %d\n", link);
 | 
			
		||||
	}
 | 
			
		||||
	link_changed = netif_carrier_ok(dev->net) != link;
 | 
			
		||||
	if (link_changed) {
 | 
			
		||||
		data->link_counter++;
 | 
			
		||||
		/*
 | 
			
		||||
		   track link state 20 times to guard against erroneous
 | 
			
		||||
		   link state changes reported sometimes by the chip
 | 
			
		||||
		 */
 | 
			
		||||
		if (data->link_counter > 20) {
 | 
			
		||||
			data->link_counter = 0;
 | 
			
		||||
			if (link) {
 | 
			
		||||
				netif_carrier_on(dev->net);
 | 
			
		||||
				usbnet_defer_kevent(dev, EVENT_LINK_RESET);
 | 
			
		||||
			} else
 | 
			
		||||
				netif_carrier_off(dev->net);
 | 
			
		||||
			netdev_dbg(dev->net, "Link Status is: %d\n", link);
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		data->link_counter = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct driver_info moschip_info = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue