cdc_subset: deal with a device that needs reset for timeout
This device needs to be reset to recover from a timeout. Unfortunately this can be handled only at the level of the subdrivers. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								06ebb06d49
							
						
					
				
			
			
				commit
				
					
						dbcdd4d58c
					
				
			
		
					 3 changed files with 35 additions and 3 deletions
				
			
		| 
						 | 
					@ -85,14 +85,28 @@ static int always_connected (struct usbnet *dev)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------*/
 | 
					 *-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void m5632_recover(struct usbnet *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_device	*udev = dev->udev;
 | 
				
			||||||
 | 
						struct usb_interface	*intf = dev->intf;
 | 
				
			||||||
 | 
						int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r = usb_lock_device_for_reset(udev, intf);
 | 
				
			||||||
 | 
						if (r < 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_reset_device(udev);
 | 
				
			||||||
 | 
						usb_unlock_device(udev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct driver_info	ali_m5632_info = {
 | 
					static const struct driver_info	ali_m5632_info = {
 | 
				
			||||||
	.description =	"ALi M5632",
 | 
						.description =	"ALi M5632",
 | 
				
			||||||
	.flags       = FLAG_POINTTOPOINT,
 | 
						.flags       = FLAG_POINTTOPOINT,
 | 
				
			||||||
 | 
						.recover     = m5632_recover,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef	CONFIG_USB_AN2720
 | 
					#ifdef	CONFIG_USB_AN2720
 | 
				
			||||||
#define	HAVE_HARDWARE
 | 
					#define	HAVE_HARDWARE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,12 +340,23 @@ static const struct usb_device_id	products [] = {
 | 
				
			||||||
MODULE_DEVICE_TABLE(usb, products);
 | 
					MODULE_DEVICE_TABLE(usb, products);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					static int dummy_prereset(struct usb_interface *intf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dummy_postreset(struct usb_interface *intf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_driver cdc_subset_driver = {
 | 
					static struct usb_driver cdc_subset_driver = {
 | 
				
			||||||
	.name =		"cdc_subset",
 | 
						.name =		"cdc_subset",
 | 
				
			||||||
	.probe =	usbnet_probe,
 | 
						.probe =	usbnet_probe,
 | 
				
			||||||
	.suspend =	usbnet_suspend,
 | 
						.suspend =	usbnet_suspend,
 | 
				
			||||||
	.resume =	usbnet_resume,
 | 
						.resume =	usbnet_resume,
 | 
				
			||||||
 | 
						.pre_reset =	dummy_prereset,
 | 
				
			||||||
 | 
						.post_reset =	dummy_postreset,
 | 
				
			||||||
	.disconnect =	usbnet_disconnect,
 | 
						.disconnect =	usbnet_disconnect,
 | 
				
			||||||
	.id_table =	products,
 | 
						.id_table =	products,
 | 
				
			||||||
	.disable_hub_initiated_lpm = 1,
 | 
						.disable_hub_initiated_lpm = 1,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_device *net)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unlink_urbs (dev, &dev->txq);
 | 
						unlink_urbs (dev, &dev->txq);
 | 
				
			||||||
	tasklet_schedule (&dev->bh);
 | 
						tasklet_schedule (&dev->bh);
 | 
				
			||||||
 | 
						/* this needs to be handled individually because the generic layer
 | 
				
			||||||
	// FIXME: device recovery -- reset?
 | 
						 * doesn't know what is sufficient and could not restore private
 | 
				
			||||||
 | 
						 * information if a remedy of an unconditional reset were used.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (dev->driver_info->recover)
 | 
				
			||||||
 | 
							(dev->driver_info->recover)(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
 | 
					EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,6 +148,9 @@ struct driver_info {
 | 
				
			||||||
	struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
 | 
						struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
 | 
				
			||||||
				struct sk_buff *skb, gfp_t flags);
 | 
									struct sk_buff *skb, gfp_t flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* recover from timeout */
 | 
				
			||||||
 | 
						void	(*recover)(struct usbnet *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* early initialization code, can sleep. This is for minidrivers
 | 
						/* early initialization code, can sleep. This is for minidrivers
 | 
				
			||||||
	 * having 'subminidrivers' that need to do extra initialization
 | 
						 * having 'subminidrivers' that need to do extra initialization
 | 
				
			||||||
	 * right after minidriver have initialized hardware. */
 | 
						 * right after minidriver have initialized hardware. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue