diff options
-rw-r--r-- | Documentation/driver-api/usb/power-management.rst | 14 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 13 | ||||
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 13 | ||||
-rw-r--r-- | include/linux/usb.h | 2 |
4 files changed, 14 insertions, 28 deletions
diff --git a/Documentation/driver-api/usb/power-management.rst b/Documentation/driver-api/usb/power-management.rst index 79beb807996b..4a74cf6f2797 100644 --- a/Documentation/driver-api/usb/power-management.rst +++ b/Documentation/driver-api/usb/power-management.rst | |||
@@ -370,11 +370,15 @@ autosuspend the interface's device. When the usage counter is = 0 | |||
370 | then the interface is considered to be idle, and the kernel may | 370 | then the interface is considered to be idle, and the kernel may |
371 | autosuspend the device. | 371 | autosuspend the device. |
372 | 372 | ||
373 | Drivers need not be concerned about balancing changes to the usage | 373 | Drivers must be careful to balance their overall changes to the usage |
374 | counter; the USB core will undo any remaining "get"s when a driver | 374 | counter. Unbalanced "get"s will remain in effect when a driver is |
375 | is unbound from its interface. As a corollary, drivers must not call | 375 | unbound from its interface, preventing the device from going into |
376 | any of the ``usb_autopm_*`` functions after their ``disconnect`` | 376 | runtime suspend should the interface be bound to a driver again. On |
377 | routine has returned. | 377 | the other hand, drivers are allowed to achieve this balance by calling |
378 | the ``usb_autopm_*`` functions even after their ``disconnect`` routine | ||
379 | has returned -- say from within a work-queue routine -- provided they | ||
380 | retain an active reference to the interface (via ``usb_get_intf`` and | ||
381 | ``usb_put_intf``). | ||
378 | 382 | ||
379 | Drivers using the async routines are responsible for their own | 383 | Drivers using the async routines are responsible for their own |
380 | synchronization and mutual exclusion. | 384 | synchronization and mutual exclusion. |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8987cec9549d..ebcadaad89d1 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -473,11 +473,6 @@ static int usb_unbind_interface(struct device *dev) | |||
473 | pm_runtime_disable(dev); | 473 | pm_runtime_disable(dev); |
474 | pm_runtime_set_suspended(dev); | 474 | pm_runtime_set_suspended(dev); |
475 | 475 | ||
476 | /* Undo any residual pm_autopm_get_interface_* calls */ | ||
477 | for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r) | ||
478 | usb_autopm_put_interface_no_suspend(intf); | ||
479 | atomic_set(&intf->pm_usage_cnt, 0); | ||
480 | |||
481 | if (!error) | 476 | if (!error) |
482 | usb_autosuspend_device(udev); | 477 | usb_autosuspend_device(udev); |
483 | 478 | ||
@@ -1633,7 +1628,6 @@ void usb_autopm_put_interface(struct usb_interface *intf) | |||
1633 | int status; | 1628 | int status; |
1634 | 1629 | ||
1635 | usb_mark_last_busy(udev); | 1630 | usb_mark_last_busy(udev); |
1636 | atomic_dec(&intf->pm_usage_cnt); | ||
1637 | status = pm_runtime_put_sync(&intf->dev); | 1631 | status = pm_runtime_put_sync(&intf->dev); |
1638 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", | 1632 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
1639 | __func__, atomic_read(&intf->dev.power.usage_count), | 1633 | __func__, atomic_read(&intf->dev.power.usage_count), |
@@ -1662,7 +1656,6 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) | |||
1662 | int status; | 1656 | int status; |
1663 | 1657 | ||
1664 | usb_mark_last_busy(udev); | 1658 | usb_mark_last_busy(udev); |
1665 | atomic_dec(&intf->pm_usage_cnt); | ||
1666 | status = pm_runtime_put(&intf->dev); | 1659 | status = pm_runtime_put(&intf->dev); |
1667 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", | 1660 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
1668 | __func__, atomic_read(&intf->dev.power.usage_count), | 1661 | __func__, atomic_read(&intf->dev.power.usage_count), |
@@ -1684,7 +1677,6 @@ void usb_autopm_put_interface_no_suspend(struct usb_interface *intf) | |||
1684 | struct usb_device *udev = interface_to_usbdev(intf); | 1677 | struct usb_device *udev = interface_to_usbdev(intf); |
1685 | 1678 | ||
1686 | usb_mark_last_busy(udev); | 1679 | usb_mark_last_busy(udev); |
1687 | atomic_dec(&intf->pm_usage_cnt); | ||
1688 | pm_runtime_put_noidle(&intf->dev); | 1680 | pm_runtime_put_noidle(&intf->dev); |
1689 | } | 1681 | } |
1690 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend); | 1682 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend); |
@@ -1715,8 +1707,6 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1715 | status = pm_runtime_get_sync(&intf->dev); | 1707 | status = pm_runtime_get_sync(&intf->dev); |
1716 | if (status < 0) | 1708 | if (status < 0) |
1717 | pm_runtime_put_sync(&intf->dev); | 1709 | pm_runtime_put_sync(&intf->dev); |
1718 | else | ||
1719 | atomic_inc(&intf->pm_usage_cnt); | ||
1720 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", | 1710 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
1721 | __func__, atomic_read(&intf->dev.power.usage_count), | 1711 | __func__, atomic_read(&intf->dev.power.usage_count), |
1722 | status); | 1712 | status); |
@@ -1750,8 +1740,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) | |||
1750 | status = pm_runtime_get(&intf->dev); | 1740 | status = pm_runtime_get(&intf->dev); |
1751 | if (status < 0 && status != -EINPROGRESS) | 1741 | if (status < 0 && status != -EINPROGRESS) |
1752 | pm_runtime_put_noidle(&intf->dev); | 1742 | pm_runtime_put_noidle(&intf->dev); |
1753 | else | ||
1754 | atomic_inc(&intf->pm_usage_cnt); | ||
1755 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", | 1743 | dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n", |
1756 | __func__, atomic_read(&intf->dev.power.usage_count), | 1744 | __func__, atomic_read(&intf->dev.power.usage_count), |
1757 | status); | 1745 | status); |
@@ -1775,7 +1763,6 @@ void usb_autopm_get_interface_no_resume(struct usb_interface *intf) | |||
1775 | struct usb_device *udev = interface_to_usbdev(intf); | 1763 | struct usb_device *udev = interface_to_usbdev(intf); |
1776 | 1764 | ||
1777 | usb_mark_last_busy(udev); | 1765 | usb_mark_last_busy(udev); |
1778 | atomic_inc(&intf->pm_usage_cnt); | ||
1779 | pm_runtime_get_noresume(&intf->dev); | 1766 | pm_runtime_get_noresume(&intf->dev); |
1780 | } | 1767 | } |
1781 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume); | 1768 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume); |
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 31b024441938..cc794e25a0b6 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c | |||
@@ -763,18 +763,16 @@ static void rts51x_suspend_timer_fn(struct timer_list *t) | |||
763 | break; | 763 | break; |
764 | case RTS51X_STAT_IDLE: | 764 | case RTS51X_STAT_IDLE: |
765 | case RTS51X_STAT_SS: | 765 | case RTS51X_STAT_SS: |
766 | usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n", | 766 | usb_stor_dbg(us, "RTS51X_STAT_SS, power.usage:%d\n", |
767 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
768 | atomic_read(&us->pusb_intf->dev.power.usage_count)); | 767 | atomic_read(&us->pusb_intf->dev.power.usage_count)); |
769 | 768 | ||
770 | if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) { | 769 | if (atomic_read(&us->pusb_intf->dev.power.usage_count) > 0) { |
771 | usb_stor_dbg(us, "Ready to enter SS state\n"); | 770 | usb_stor_dbg(us, "Ready to enter SS state\n"); |
772 | rts51x_set_stat(chip, RTS51X_STAT_SS); | 771 | rts51x_set_stat(chip, RTS51X_STAT_SS); |
773 | /* ignore mass storage interface's children */ | 772 | /* ignore mass storage interface's children */ |
774 | pm_suspend_ignore_children(&us->pusb_intf->dev, true); | 773 | pm_suspend_ignore_children(&us->pusb_intf->dev, true); |
775 | usb_autopm_put_interface_async(us->pusb_intf); | 774 | usb_autopm_put_interface_async(us->pusb_intf); |
776 | usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n", | 775 | usb_stor_dbg(us, "RTS51X_STAT_SS 01, power.usage:%d\n", |
777 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
778 | atomic_read(&us->pusb_intf->dev.power.usage_count)); | 776 | atomic_read(&us->pusb_intf->dev.power.usage_count)); |
779 | } | 777 | } |
780 | break; | 778 | break; |
@@ -807,11 +805,10 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
807 | int ret; | 805 | int ret; |
808 | 806 | ||
809 | if (working_scsi(srb)) { | 807 | if (working_scsi(srb)) { |
810 | usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n", | 808 | usb_stor_dbg(us, "working scsi, power.usage:%d\n", |
811 | atomic_read(&us->pusb_intf->pm_usage_cnt), | ||
812 | atomic_read(&us->pusb_intf->dev.power.usage_count)); | 809 | atomic_read(&us->pusb_intf->dev.power.usage_count)); |
813 | 810 | ||
814 | if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) { | 811 | if (atomic_read(&us->pusb_intf->dev.power.usage_count) <= 0) { |
815 | ret = usb_autopm_get_interface(us->pusb_intf); | 812 | ret = usb_autopm_get_interface(us->pusb_intf); |
816 | usb_stor_dbg(us, "working scsi, ret=%d\n", ret); | 813 | usb_stor_dbg(us, "working scsi, ret=%d\n", ret); |
817 | } | 814 | } |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 5e49e82c4368..ff010d1fd1c7 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -200,7 +200,6 @@ usb_find_last_int_out_endpoint(struct usb_host_interface *alt, | |||
200 | * @dev: driver model's view of this device | 200 | * @dev: driver model's view of this device |
201 | * @usb_dev: if an interface is bound to the USB major, this will point | 201 | * @usb_dev: if an interface is bound to the USB major, this will point |
202 | * to the sysfs representation for that device. | 202 | * to the sysfs representation for that device. |
203 | * @pm_usage_cnt: PM usage counter for this interface | ||
204 | * @reset_ws: Used for scheduling resets from atomic context. | 203 | * @reset_ws: Used for scheduling resets from atomic context. |
205 | * @resetting_device: USB core reset the device, so use alt setting 0 as | 204 | * @resetting_device: USB core reset the device, so use alt setting 0 as |
206 | * current; needs bandwidth alloc after reset. | 205 | * current; needs bandwidth alloc after reset. |
@@ -257,7 +256,6 @@ struct usb_interface { | |||
257 | 256 | ||
258 | struct device dev; /* interface specific device info */ | 257 | struct device dev; /* interface specific device info */ |
259 | struct device *usb_dev; | 258 | struct device *usb_dev; |
260 | atomic_t pm_usage_cnt; /* usage counter for autosuspend */ | ||
261 | struct work_struct reset_ws; /* for resets in atomic context */ | 259 | struct work_struct reset_ws; /* for resets in atomic context */ |
262 | }; | 260 | }; |
263 | #define to_usb_interface(d) container_of(d, struct usb_interface, dev) | 261 | #define to_usb_interface(d) container_of(d, struct usb_interface, dev) |