Commit 20fbe3ae authored by Oliver Neukum's avatar Oliver Neukum Committed by David S. Miller

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: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 40eea803
...@@ -85,9 +85,34 @@ static int always_connected (struct usbnet *dev) ...@@ -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 = { 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
...@@ -332,6 +357,8 @@ static struct usb_driver cdc_subset_driver = { ...@@ -332,6 +357,8 @@ static struct usb_driver cdc_subset_driver = {
.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) ...@@ -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 { ...@@ -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. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment