diff options
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 4309c03038f6..dedd8e4e5c6d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -993,9 +993,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
993 | 993 | ||
994 | static void usbhid_restart_queues(struct usbhid_device *usbhid) | 994 | static void usbhid_restart_queues(struct usbhid_device *usbhid) |
995 | { | 995 | { |
996 | if (usbhid->urbout) | 996 | if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) |
997 | usbhid_restart_out_queue(usbhid); | 997 | usbhid_restart_out_queue(usbhid); |
998 | usbhid_restart_ctrl_queue(usbhid); | 998 | if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) |
999 | usbhid_restart_ctrl_queue(usbhid); | ||
999 | } | 1000 | } |
1000 | 1001 | ||
1001 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 1002 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
@@ -1462,11 +1463,38 @@ void usbhid_put_power(struct hid_device *hid) | |||
1462 | 1463 | ||
1463 | 1464 | ||
1464 | #ifdef CONFIG_PM | 1465 | #ifdef CONFIG_PM |
1466 | static int hid_resume_common(struct hid_device *hid, bool driver_suspended) | ||
1467 | { | ||
1468 | struct usbhid_device *usbhid = hid->driver_data; | ||
1469 | int status; | ||
1470 | |||
1471 | spin_lock_irq(&usbhid->lock); | ||
1472 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | ||
1473 | usbhid_mark_busy(usbhid); | ||
1474 | |||
1475 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || | ||
1476 | test_bit(HID_RESET_PENDING, &usbhid->iofl)) | ||
1477 | schedule_work(&usbhid->reset_work); | ||
1478 | usbhid->retry_delay = 0; | ||
1479 | |||
1480 | usbhid_restart_queues(usbhid); | ||
1481 | spin_unlock_irq(&usbhid->lock); | ||
1482 | |||
1483 | status = hid_start_in(hid); | ||
1484 | if (status < 0) | ||
1485 | hid_io_error(hid); | ||
1486 | |||
1487 | if (driver_suspended && hid->driver && hid->driver->resume) | ||
1488 | status = hid->driver->resume(hid); | ||
1489 | return status; | ||
1490 | } | ||
1491 | |||
1465 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1492 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
1466 | { | 1493 | { |
1467 | struct hid_device *hid = usb_get_intfdata(intf); | 1494 | struct hid_device *hid = usb_get_intfdata(intf); |
1468 | struct usbhid_device *usbhid = hid->driver_data; | 1495 | struct usbhid_device *usbhid = hid->driver_data; |
1469 | int status; | 1496 | int status; |
1497 | bool driver_suspended = false; | ||
1470 | 1498 | ||
1471 | if (PMSG_IS_AUTO(message)) { | 1499 | if (PMSG_IS_AUTO(message)) { |
1472 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1500 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
@@ -1482,8 +1510,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1482 | if (hid->driver && hid->driver->suspend) { | 1510 | if (hid->driver && hid->driver->suspend) { |
1483 | status = hid->driver->suspend(hid, message); | 1511 | status = hid->driver->suspend(hid, message); |
1484 | if (status < 0) | 1512 | if (status < 0) |
1485 | return status; | 1513 | goto failed; |
1486 | } | 1514 | } |
1515 | driver_suspended = true; | ||
1487 | } else { | 1516 | } else { |
1488 | usbhid_mark_busy(usbhid); | 1517 | usbhid_mark_busy(usbhid); |
1489 | spin_unlock_irq(&usbhid->lock); | 1518 | spin_unlock_irq(&usbhid->lock); |
@@ -1496,11 +1525,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1496 | if (status < 0) | 1525 | if (status < 0) |
1497 | return status; | 1526 | return status; |
1498 | } | 1527 | } |
1528 | driver_suspended = true; | ||
1499 | spin_lock_irq(&usbhid->lock); | 1529 | spin_lock_irq(&usbhid->lock); |
1500 | set_bit(HID_SUSPENDED, &usbhid->iofl); | 1530 | set_bit(HID_SUSPENDED, &usbhid->iofl); |
1501 | spin_unlock_irq(&usbhid->lock); | 1531 | spin_unlock_irq(&usbhid->lock); |
1502 | if (usbhid_wait_io(hid) < 0) | 1532 | if (usbhid_wait_io(hid) < 0) { |
1503 | return -EIO; | 1533 | status = -EIO; |
1534 | goto failed; | ||
1535 | } | ||
1504 | } | 1536 | } |
1505 | 1537 | ||
1506 | hid_cancel_delayed_stuff(usbhid); | 1538 | hid_cancel_delayed_stuff(usbhid); |
@@ -1508,14 +1540,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1508 | 1540 | ||
1509 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { | 1541 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { |
1510 | /* lost race against keypresses */ | 1542 | /* lost race against keypresses */ |
1511 | status = hid_start_in(hid); | 1543 | status = -EBUSY; |
1512 | if (status < 0) | 1544 | goto failed; |
1513 | hid_io_error(hid); | ||
1514 | usbhid_mark_busy(usbhid); | ||
1515 | return -EBUSY; | ||
1516 | } | 1545 | } |
1517 | dev_dbg(&intf->dev, "suspend\n"); | 1546 | dev_dbg(&intf->dev, "suspend\n"); |
1518 | return 0; | 1547 | return 0; |
1548 | |||
1549 | failed: | ||
1550 | hid_resume_common(hid, driver_suspended); | ||
1551 | return status; | ||
1519 | } | 1552 | } |
1520 | 1553 | ||
1521 | static int hid_resume(struct usb_interface *intf) | 1554 | static int hid_resume(struct usb_interface *intf) |
@@ -1527,23 +1560,7 @@ static int hid_resume(struct usb_interface *intf) | |||
1527 | if (!test_bit(HID_STARTED, &usbhid->iofl)) | 1560 | if (!test_bit(HID_STARTED, &usbhid->iofl)) |
1528 | return 0; | 1561 | return 0; |
1529 | 1562 | ||
1530 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | 1563 | status = hid_resume_common(hid, true); |
1531 | usbhid_mark_busy(usbhid); | ||
1532 | |||
1533 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || | ||
1534 | test_bit(HID_RESET_PENDING, &usbhid->iofl)) | ||
1535 | schedule_work(&usbhid->reset_work); | ||
1536 | usbhid->retry_delay = 0; | ||
1537 | status = hid_start_in(hid); | ||
1538 | if (status < 0) | ||
1539 | hid_io_error(hid); | ||
1540 | usbhid_restart_queues(usbhid); | ||
1541 | |||
1542 | if (status >= 0 && hid->driver && hid->driver->resume) { | ||
1543 | int ret = hid->driver->resume(hid); | ||
1544 | if (ret < 0) | ||
1545 | status = ret; | ||
1546 | } | ||
1547 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1564 | dev_dbg(&intf->dev, "resume status %d\n", status); |
1548 | return 0; | 1565 | return 0; |
1549 | } | 1566 | } |