u8 usb_gone;
        struct work_struct async_get_intf;
        struct work_struct async_put_intf;
+       struct work_struct reset_device;
 
        struct usb_device *usb;
        struct usb_interface *interface;
 /* Helper functions */
 static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int,
                                   struct usb_device *usb, gfp_t gfp);
-static void log_usb_status(int status, const char *function);
+static void handle_usb_error(int status, const char *function,
+                            struct hso_device *hso_dev);
 static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf,
                                                  int type, int dir);
 static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports);
 static int hso_put_activity(struct hso_device *hso_dev);
 static int hso_get_activity(struct hso_device *hso_dev);
 static void tiocmget_intr_callback(struct urb *urb);
+static void reset_device(struct work_struct *data);
 /*****************************************************************************/
 /* Helping functions                                                         */
 /*****************************************************************************/
        spin_unlock_irqrestore(&serial_table_lock, flags);
 }
 
-/* log a meaningful explanation of an USB status */
-static void log_usb_status(int status, const char *function)
+static void handle_usb_error(int status, const char *function,
+                            struct hso_device *hso_dev)
 {
        char *explanation;
 
        case -EMSGSIZE:
                explanation = "internal error";
                break;
+       case -EILSEQ:
+       case -EPROTO:
+       case -ETIME:
+       case -ETIMEDOUT:
+               explanation = "protocol error";
+               if (hso_dev)
+                       schedule_work(&hso_dev->reset_device);
+               break;
        default:
                explanation = "unknown status";
                break;
        }
+
+       /* log a meaningful explanation of an USB status */
        D1("%s: received USB status - %s (%d)", function, explanation, status);
 }
 
        /* log status, but don't act on it, we don't need to resubmit anything
         * anyhow */
        if (status)
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, odev->parent);
 
        hso_put_activity(odev->parent);
 
 
        /* is al ok?  (Filip: Who's Al ?) */
        if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, odev->parent);
                return;
        }
 
                D1("serial == NULL");
                return;
        } else if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, serial->parent);
                return;
        }
 
        if (!serial)
                return;
        if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, serial->parent);
                return;
        }
        tiocmget = serial->tiocmget;
 
        /* status check */
        if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, NULL);
                return;
        }
        D4("\n--- Got intr callback 0x%02X ---", status);
        tty = tty_kref_get(serial->tty);
        spin_unlock(&serial->serial_lock);
        if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, serial->parent);
                tty_kref_put(tty);
                return;
        }
        tty = tty_kref_get(serial->tty);
        spin_unlock(&serial->serial_lock);
        if (status) {
-               log_usb_status(status, __func__);
+               handle_usb_error(status, __func__, serial->parent);
                tty_kref_put(tty);
                return;
        }
 
        INIT_WORK(&hso_dev->async_get_intf, async_get_intf);
        INIT_WORK(&hso_dev->async_put_intf, async_put_intf);
+       INIT_WORK(&hso_dev->reset_device, reset_device);
 
        return hso_dev;
 }
        return result;
 }
 
+static void reset_device(struct work_struct *data)
+{
+       struct hso_device *hso_dev =
+           container_of(data, struct hso_device, reset_device);
+       struct usb_device *usb = hso_dev->usb;
+       int result;
+
+       if (hso_dev->usb_gone) {
+               D1("No reset during disconnect\n");
+       } else {
+               result = usb_lock_device_for_reset(usb, hso_dev->interface);
+               if (result < 0)
+                       D1("unable to lock device for reset: %d\n", result);
+               else {
+                       usb_reset_device(usb);
+                       usb_unlock_device(usb);
+               }
+       }
+}
+
 static void hso_serial_ref_free(struct kref *ref)
 {
        struct hso_device *hso_dev = container_of(ref, struct hso_device, ref);