--- x/drivers/hid/hid-core.c +++ y/drivers/hid/hid-core.c @@ -2404,8 +2404,8 @@ EXPORT_SYMBOL_GPL(hid_hw_start); */ void hid_hw_stop(struct hid_device *hdev) { - hid_disconnect(hdev); hdev->ll_driver->stop(hdev); + hid_disconnect(hdev); } EXPORT_SYMBOL_GPL(hid_hw_stop); --- x/drivers/hid/usbhid/hid-core.c +++ y/drivers/hid/usbhid/hid-core.c @@ -279,6 +279,8 @@ static void hid_irq_in(struct urb *urb) switch (urb->status) { case 0: /* success */ usbhid->retry_delay = 0; + if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) + return; if (!test_bit(HID_OPENED, &usbhid->iofl)) break; usbhid_mark_busy(usbhid); @@ -1278,6 +1280,15 @@ static int usbhid_power(struct hid_devic struct usbhid_device *usbhid = hid->driver_data; int r = 0; + mutex_lock(&usbhid->mutex); + + r = -ENODEV; + if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) + goto out; + if (!test_bit(HID_STARTED, &usbhid->iofl)) + goto out; + + r = 0; switch (lvl) { case PM_HINT_FULLON: r = usb_autopm_get_interface(usbhid->intf); @@ -1287,6 +1298,8 @@ static int usbhid_power(struct hid_devic usb_autopm_put_interface(usbhid->intf); break; } +out: + mutex_unlock(&usbhid->mutex); return r; }