*
  *-------------------------------------------------------------------------*/
 
+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
        .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,
 
 
        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);
 
 
        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. */