|
@@ -1546,8 +1546,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
|
|
|
|
|
|
/*
|
|
/*
|
|
* Reset management
|
|
* Reset management
|
|
- * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
|
|
|
|
- * XXX Make usb_sync_reset asynchronous.
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
static void ub_reset_enter(struct ub_dev *sc, int try)
|
|
static void ub_reset_enter(struct ub_dev *sc, int try)
|
|
@@ -1632,6 +1630,22 @@ static void ub_reset_task(struct work_struct *work)
|
|
spin_unlock_irqrestore(sc->lock, flags);
|
|
spin_unlock_irqrestore(sc->lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * XXX Reset brackets are too much hassle to implement, so just stub them
|
|
|
|
+ * in order to prevent forced unbinding (which deadlocks solid when our
|
|
|
|
+ * ->disconnect method waits for the reset to complete and this kills keventd).
|
|
|
|
+ *
|
|
|
|
+ * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device,
|
|
|
|
+ * or else the post_reset is invoked, and restats I/O on a locked device.
|
|
|
|
+ */
|
|
|
|
+static int ub_pre_reset(struct usb_interface *iface) {
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int ub_post_reset(struct usb_interface *iface) {
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This is called from a process context.
|
|
* This is called from a process context.
|
|
*/
|
|
*/
|
|
@@ -2446,6 +2460,8 @@ static struct usb_driver ub_driver = {
|
|
.probe = ub_probe,
|
|
.probe = ub_probe,
|
|
.disconnect = ub_disconnect,
|
|
.disconnect = ub_disconnect,
|
|
.id_table = ub_usb_ids,
|
|
.id_table = ub_usb_ids,
|
|
|
|
+ .pre_reset = ub_pre_reset,
|
|
|
|
+ .post_reset = ub_post_reset,
|
|
};
|
|
};
|
|
|
|
|
|
static int __init ub_init(void)
|
|
static int __init ub_init(void)
|