On Sun, 24 Aug 2014, vichy wrote: > hi Alan: > > > > I originally tried using usb_reset_device, and it caused a deadlock: > > > > Unplug the HID device. > > > > I/O error occurs. hid_io_error schedules reset_work. > > > > The reset_work callback routine is hid_reset. It calls > > usb_reset_device. > > > > The reset fails because the device is gone. At the end of the > > reset, hid_post_reset is called. > > > > hid_post_reset returns 1 because hid_get_class_descriptor > > fails. > > > > Because the post_reset routine failed, usb_reset_device calls > > usb_unbind_and_rebind_marked_interfaces. > > "usb_unbind_and_rebind_marked_interfaces" is called if config > parameter is not null, > it seems no matter post_reset routine fail or not. Yes, that's right. I should have said: "Because the post_reset routine failed, usb_unbind_and_rebind_marked_interfaces indirectly calls usbhid_disconnect. > > That routine indirectly calls usbhid_disconnect. > > Why that routine, usb_reset_device, will call usbhid_disconnect? > No matter port reset success or fail, usbhid_disconnect should not be > called except that did happen disconnection. usbhid_disconnect gets called when the driver is unbound, regardless of whether the device was unplugged. The kernel unbinds a driver when a device is reset but the driver isn't able to handle the reset. > > usbhid_disconnect calls usbhid_close by way of > > hid_destroy_device. > > below is the content of hid_destroy and hid_remove_device, but I > cannot find where usbhid_close be called by way of hid_destroy_device. > static void hid_remove_device(struct hid_device *hdev) > { > if (hdev->status & HID_STAT_ADDED) { > device_del(&hdev->dev); > hid_debug_unregister(hdev); > hdev->status &= ~HID_STAT_ADDED; > } > kfree(hdev->dev_rdesc); > hdev->dev_rdesc = NULL; > hdev->dev_rsize = 0; > } > > void hid_destroy_device(struct hid_device *hdev) > { > hid_remove_device(hdev); > put_device(&hdev->dev); > } I don't remember the entire call chain. It was pretty long. hid_destroy_device calls hid_remove_device, which calls device_del, which calls lots of other things. If you really want to see all the details, put a dump_stack() call in usbhid_close and examine what it prints in the kernel log when you unplug an HID device. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html