Merge tag 'driver-core-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH: "Here is the big driver core patchset for 5.1-rc1 More patches than "normal" here this merge window, due to some work in the driver core by Alexander Duyck to rework the async probe functionality to work better for a number of devices, and independant work from Rafael for the device link functionality to make it work "correctly". Also in here is: - lots of BUS_ATTR() removals, the macro is about to go away - firmware test fixups - ihex fixups and simplification - component additions (also includes i915 patches) - lots of minor coding style fixups and cleanups. All of these have been in linux-next for a while with no reported issues" * tag 'driver-core-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (65 commits) driver core: platform: remove misleading err_alloc label platform: set of_node in platform_device_register_full() firmware: hardcode the debug message for -ENOENT driver core: Add missing description of new struct device_link field driver core: Fix PM-runtime for links added during consumer probe drivers/component: kerneldoc polish async: Add cmdline option to specify drivers to be async probed driver core: Fix possible supplier PM-usage counter imbalance PM-runtime: Fix __pm_runtime_set_status() race with runtime resume driver: platform: Support parsing GpioInt 0 in platform_get_irq() selftests: firmware: fix verify_reqs() return value Revert "selftests: firmware: remove use of non-standard diff -Z option" Revert "selftests: firmware: add CONFIG_FW_LOADER_USER_HELPER_FALLBACK to config" device: Fix comment for driver_data in struct device kernfs: Allocating memory for kernfs_iattrs with kmem_cache. sysfs: remove unused include of kernfs-internal.h driver core: Postpone DMA tear-down until after devres release driver core: Document limitation related to DL_FLAG_RPM_ACTIVE PM-runtime: Take suppliers into account in __pm_runtime_set_status() device.h: Add __cold to dev_<level> logging functions ...
This commit is contained in:
@@ -734,7 +734,7 @@ void dpm_noirq_resume_devices(pm_message_t state)
|
||||
reinit_completion(&dev->power.completion);
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_resume_noirq, dev);
|
||||
async_schedule_dev(async_resume_noirq, dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,7 +891,7 @@ void dpm_resume_early(pm_message_t state)
|
||||
reinit_completion(&dev->power.completion);
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_resume_early, dev);
|
||||
async_schedule_dev(async_resume_early, dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1055,7 +1055,7 @@ void dpm_resume(pm_message_t state)
|
||||
reinit_completion(&dev->power.completion);
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_resume, dev);
|
||||
async_schedule_dev(async_resume, dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1375,7 +1375,7 @@ static int device_suspend_noirq(struct device *dev)
|
||||
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_suspend_noirq, dev);
|
||||
async_schedule_dev(async_suspend_noirq, dev);
|
||||
return 0;
|
||||
}
|
||||
return __device_suspend_noirq(dev, pm_transition, false);
|
||||
@@ -1578,7 +1578,7 @@ static int device_suspend_late(struct device *dev)
|
||||
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_suspend_late, dev);
|
||||
async_schedule_dev(async_suspend_late, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1844,7 +1844,7 @@ static int device_suspend(struct device *dev)
|
||||
|
||||
if (is_async(dev)) {
|
||||
get_device(dev);
|
||||
async_schedule(async_suspend, dev);
|
||||
async_schedule_dev(async_suspend, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -282,11 +282,8 @@ static int rpm_get_suppliers(struct device *dev)
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
|
||||
int retval;
|
||||
|
||||
if (!(link->flags & DL_FLAG_PM_RUNTIME))
|
||||
continue;
|
||||
|
||||
if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND ||
|
||||
link->rpm_active)
|
||||
if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
|
||||
READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
|
||||
continue;
|
||||
|
||||
retval = pm_runtime_get_sync(link->supplier);
|
||||
@@ -295,7 +292,7 @@ static int rpm_get_suppliers(struct device *dev)
|
||||
pm_runtime_put_noidle(link->supplier);
|
||||
return retval;
|
||||
}
|
||||
link->rpm_active = true;
|
||||
refcount_inc(&link->rpm_active);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -304,12 +301,13 @@ static void rpm_put_suppliers(struct device *dev)
|
||||
{
|
||||
struct device_link *link;
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
|
||||
if (link->rpm_active &&
|
||||
READ_ONCE(link->status) != DL_STATE_SUPPLIER_UNBIND) {
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
|
||||
if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
|
||||
continue;
|
||||
|
||||
while (refcount_dec_not_one(&link->rpm_active))
|
||||
pm_runtime_put(link->supplier);
|
||||
link->rpm_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1114,24 +1112,57 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
|
||||
* and the device parent's counter of unsuspended children is modified to
|
||||
* reflect the new status. If the new status is RPM_SUSPENDED, an idle
|
||||
* notification request for the parent is submitted.
|
||||
*
|
||||
* If @dev has any suppliers (as reflected by device links to them), and @status
|
||||
* is RPM_ACTIVE, they will be activated upfront and if the activation of one
|
||||
* of them fails, the status of @dev will be changed to RPM_SUSPENDED (instead
|
||||
* of the @status value) and the suppliers will be deacticated on exit. The
|
||||
* error returned by the failing supplier activation will be returned in that
|
||||
* case.
|
||||
*/
|
||||
int __pm_runtime_set_status(struct device *dev, unsigned int status)
|
||||
{
|
||||
struct device *parent = dev->parent;
|
||||
unsigned long flags;
|
||||
bool notify_parent = false;
|
||||
int error = 0;
|
||||
|
||||
if (status != RPM_ACTIVE && status != RPM_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev->power.lock, flags);
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
|
||||
if (!dev->power.runtime_error && !dev->power.disable_depth) {
|
||||
/*
|
||||
* Prevent PM-runtime from being enabled for the device or return an
|
||||
* error if it is enabled already and working.
|
||||
*/
|
||||
if (dev->power.runtime_error || dev->power.disable_depth)
|
||||
dev->power.disable_depth++;
|
||||
else
|
||||
error = -EAGAIN;
|
||||
goto out;
|
||||
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If the new status is RPM_ACTIVE, the suppliers can be activated
|
||||
* upfront regardless of the current status, because next time
|
||||
* rpm_put_suppliers() runs, the rpm_active refcounts of the links
|
||||
* involved will be dropped down to one anyway.
|
||||
*/
|
||||
if (status == RPM_ACTIVE) {
|
||||
int idx = device_links_read_lock();
|
||||
|
||||
error = rpm_get_suppliers(dev);
|
||||
if (error)
|
||||
status = RPM_SUSPENDED;
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
}
|
||||
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
|
||||
if (dev->power.runtime_status == status || !parent)
|
||||
goto out_set;
|
||||
|
||||
@@ -1159,19 +1190,33 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
|
||||
|
||||
spin_unlock(&parent->power.lock);
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
status = RPM_SUSPENDED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out_set:
|
||||
__update_runtime_status(dev, status);
|
||||
dev->power.runtime_error = 0;
|
||||
if (!error)
|
||||
dev->power.runtime_error = 0;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
|
||||
if (notify_parent)
|
||||
pm_request_idle(parent);
|
||||
|
||||
if (status == RPM_SUSPENDED) {
|
||||
int idx = device_links_read_lock();
|
||||
|
||||
rpm_put_suppliers(dev);
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
|
||||
@@ -1569,7 +1614,7 @@ void pm_runtime_remove(struct device *dev)
|
||||
*
|
||||
* Check links from this device to any consumers and if any of them have active
|
||||
* runtime PM references to the device, drop the usage counter of the device
|
||||
* (once per link).
|
||||
* (as many times as needed).
|
||||
*
|
||||
* Links with the DL_FLAG_STATELESS flag set are ignored.
|
||||
*
|
||||
@@ -1591,10 +1636,8 @@ void pm_runtime_clean_up_links(struct device *dev)
|
||||
if (link->flags & DL_FLAG_STATELESS)
|
||||
continue;
|
||||
|
||||
if (link->rpm_active) {
|
||||
while (refcount_dec_not_one(&link->rpm_active))
|
||||
pm_runtime_put_noidle(dev);
|
||||
link->rpm_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
@@ -1612,8 +1655,11 @@ void pm_runtime_get_suppliers(struct device *dev)
|
||||
idx = device_links_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
|
||||
if (link->flags & DL_FLAG_PM_RUNTIME)
|
||||
if (link->flags & DL_FLAG_PM_RUNTIME) {
|
||||
link->supplier_preactivated = true;
|
||||
refcount_inc(&link->rpm_active);
|
||||
pm_runtime_get_sync(link->supplier);
|
||||
}
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
}
|
||||
@@ -1630,8 +1676,11 @@ void pm_runtime_put_suppliers(struct device *dev)
|
||||
idx = device_links_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
|
||||
if (link->flags & DL_FLAG_PM_RUNTIME)
|
||||
pm_runtime_put(link->supplier);
|
||||
if (link->supplier_preactivated) {
|
||||
link->supplier_preactivated = false;
|
||||
if (refcount_dec_not_one(&link->rpm_active))
|
||||
pm_runtime_put(link->supplier);
|
||||
}
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
}
|
||||
@@ -1645,8 +1694,6 @@ void pm_runtime_new_link(struct device *dev)
|
||||
|
||||
void pm_runtime_drop_link(struct device *dev)
|
||||
{
|
||||
rpm_put_suppliers(dev);
|
||||
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
WARN_ON(dev->power.links_count == 0);
|
||||
dev->power.links_count--;
|
||||
|
Reference in New Issue
Block a user