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
40eea803c6
commit
20fbe3ae99
3 changed files with 36 additions and 2 deletions
|
@ -85,9 +85,34 @@ 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 int dummy_prereset(struct usb_interface *intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_postreset(struct usb_interface *intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct driver_info ali_m5632_info = {
|
||||
.description = "ALi M5632",
|
||||
.flags = FLAG_POINTTOPOINT,
|
||||
.recover = m5632_recover,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -332,6 +357,8 @@ static struct usb_driver cdc_subset_driver = {
|
|||
.probe = usbnet_probe,
|
||||
.suspend = usbnet_suspend,
|
||||
.resume = usbnet_resume,
|
||||
.pre_reset = dummy_prereset,
|
||||
.post_reset = dummy_postreset,
|
||||
.disconnect = usbnet_disconnect,
|
||||
.id_table = products,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
|
|
|
@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_device *net)
|
|||
|
||||
unlink_urbs (dev, &dev->txq);
|
||||
tasklet_schedule (&dev->bh);
|
||||
|
||||
// FIXME: device recovery -- reset?
|
||||
/* this needs to be handled individually because the generic layer
|
||||
* 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);
|
||||
|
||||
|
|
|
@ -148,6 +148,9 @@ struct driver_info {
|
|||
struct sk_buff *(*tx_fixup)(struct usbnet *dev,
|
||||
struct sk_buff *skb, gfp_t flags);
|
||||
|
||||
/* recover from timeout */
|
||||
void (*recover)(struct usbnet *dev);
|
||||
|
||||
/* early initialization code, can sleep. This is for minidrivers
|
||||
* having 'subminidrivers' that need to do extra initialization
|
||||
* right after minidriver have initialized hardware. */
|
||||
|
|
Loading…
Reference in a new issue