mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-05 13:25:20 +02:00
Revert "driver core: shut down devices asynchronously"
This reverts commit 8064952c65
.
The series is being reverted before -rc1 as there are still reports of
lockups on shutdown, so it's not quite ready for "prime time."
Reported-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
Link: https://lore.kernel.org/r/ZvMkkhyJrohaajuk@skv.local
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Jeffery <djeffery@redhat.com>
Cc: Keith Busch <kbusch@kernel.org>
Cc: Laurence Oberman <loberman@redhat.com>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: Stuart Hayes <stuart.w.hayes@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ec1fcbae19
commit
2efddb5575
|
@ -10,7 +10,6 @@
|
||||||
* shared outside of the drivers/base/ directory.
|
* shared outside of the drivers/base/ directory.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <linux/async.h>
|
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,8 +97,6 @@ struct driver_private {
|
||||||
* the device; typically because it depends on another driver getting
|
* the device; typically because it depends on another driver getting
|
||||||
* probed first.
|
* probed first.
|
||||||
* @async_driver - pointer to device driver awaiting probe via async_probe
|
* @async_driver - pointer to device driver awaiting probe via async_probe
|
||||||
* @shutdown_after - used during device shutdown to ensure correct shutdown
|
|
||||||
* ordering.
|
|
||||||
* @device - pointer back to the struct device that this structure is
|
* @device - pointer back to the struct device that this structure is
|
||||||
* associated with.
|
* associated with.
|
||||||
* @dead - This device is currently either in the process of or has been
|
* @dead - This device is currently either in the process of or has been
|
||||||
|
@ -117,7 +114,6 @@ struct device_private {
|
||||||
struct list_head deferred_probe;
|
struct list_head deferred_probe;
|
||||||
const struct device_driver *async_driver;
|
const struct device_driver *async_driver;
|
||||||
char *deferred_probe_reason;
|
char *deferred_probe_reason;
|
||||||
async_cookie_t shutdown_after;
|
|
||||||
struct device *device;
|
struct device *device;
|
||||||
u8 dead:1;
|
u8 dead:1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/async.h>
|
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/cleanup.h>
|
#include <linux/cleanup.h>
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
|
@ -3525,7 +3524,6 @@ static int device_private_init(struct device *dev)
|
||||||
klist_init(&dev->p->klist_children, klist_children_get,
|
klist_init(&dev->p->klist_children, klist_children_get,
|
||||||
klist_children_put);
|
klist_children_put);
|
||||||
INIT_LIST_HEAD(&dev->p->deferred_probe);
|
INIT_LIST_HEAD(&dev->p->deferred_probe);
|
||||||
dev->p->shutdown_after = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4781,8 +4779,6 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_change_owner);
|
EXPORT_SYMBOL_GPL(device_change_owner);
|
||||||
|
|
||||||
static ASYNC_DOMAIN(sd_domain);
|
|
||||||
|
|
||||||
static void shutdown_one_device(struct device *dev)
|
static void shutdown_one_device(struct device *dev)
|
||||||
{
|
{
|
||||||
/* hold lock to avoid race with probe/release */
|
/* hold lock to avoid race with probe/release */
|
||||||
|
@ -4818,34 +4814,12 @@ static void shutdown_one_device(struct device *dev)
|
||||||
put_device(dev->parent);
|
put_device(dev->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* shutdown_one_device_async
|
|
||||||
* @data: the pointer to the struct device to be shutdown
|
|
||||||
* @cookie: not used
|
|
||||||
*
|
|
||||||
* Shuts down one device, after waiting for shutdown_after to complete.
|
|
||||||
* shutdown_after should be set to the cookie of the last child or consumer
|
|
||||||
* of this device to be shutdown (if any), or to the cookie of the previous
|
|
||||||
* device to be shut down for devices that don't enable asynchronous shutdown.
|
|
||||||
*/
|
|
||||||
static void shutdown_one_device_async(void *data, async_cookie_t cookie)
|
|
||||||
{
|
|
||||||
struct device *dev = data;
|
|
||||||
|
|
||||||
async_synchronize_cookie_domain(dev->p->shutdown_after + 1, &sd_domain);
|
|
||||||
|
|
||||||
shutdown_one_device(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_shutdown - call ->shutdown() on each device to shutdown.
|
* device_shutdown - call ->shutdown() on each device to shutdown.
|
||||||
*/
|
*/
|
||||||
void device_shutdown(void)
|
void device_shutdown(void)
|
||||||
{
|
{
|
||||||
struct device *dev, *parent;
|
struct device *dev, *parent;
|
||||||
async_cookie_t cookie = 0;
|
|
||||||
struct device_link *link;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
wait_for_device_probe();
|
wait_for_device_probe();
|
||||||
device_block_probing();
|
device_block_probing();
|
||||||
|
@ -4876,37 +4850,11 @@ void device_shutdown(void)
|
||||||
list_del_init(&dev->kobj.entry);
|
list_del_init(&dev->kobj.entry);
|
||||||
spin_unlock(&devices_kset->list_lock);
|
spin_unlock(&devices_kset->list_lock);
|
||||||
|
|
||||||
|
shutdown_one_device(dev);
|
||||||
/*
|
|
||||||
* Set cookie for devices that will be shut down synchronously
|
|
||||||
*/
|
|
||||||
if (!dev->driver || !dev->driver->async_shutdown_enable)
|
|
||||||
dev->p->shutdown_after = cookie;
|
|
||||||
|
|
||||||
get_device(dev);
|
|
||||||
get_device(parent);
|
|
||||||
|
|
||||||
cookie = async_schedule_domain(shutdown_one_device_async,
|
|
||||||
dev, &sd_domain);
|
|
||||||
/*
|
|
||||||
* Ensure parent & suppliers wait for this device to shut down
|
|
||||||
*/
|
|
||||||
if (parent) {
|
|
||||||
parent->p->shutdown_after = cookie;
|
|
||||||
put_device(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = device_links_read_lock();
|
|
||||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
|
|
||||||
device_links_read_lock_held())
|
|
||||||
link->supplier->p->shutdown_after = cookie;
|
|
||||||
device_links_read_unlock(idx);
|
|
||||||
put_device(dev);
|
|
||||||
|
|
||||||
spin_lock(&devices_kset->list_lock);
|
spin_lock(&devices_kset->list_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&devices_kset->list_lock);
|
spin_unlock(&devices_kset->list_lock);
|
||||||
async_synchronize_full_domain(&sd_domain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -56,7 +56,6 @@ enum probe_type {
|
||||||
* @mod_name: Used for built-in modules.
|
* @mod_name: Used for built-in modules.
|
||||||
* @suppress_bind_attrs: Disables bind/unbind via sysfs.
|
* @suppress_bind_attrs: Disables bind/unbind via sysfs.
|
||||||
* @probe_type: Type of the probe (synchronous or asynchronous) to use.
|
* @probe_type: Type of the probe (synchronous or asynchronous) to use.
|
||||||
* @async_shutdown_enable: Enables devices to be shutdown asynchronously.
|
|
||||||
* @of_match_table: The open firmware table.
|
* @of_match_table: The open firmware table.
|
||||||
* @acpi_match_table: The ACPI match table.
|
* @acpi_match_table: The ACPI match table.
|
||||||
* @probe: Called to query the existence of a specific device,
|
* @probe: Called to query the existence of a specific device,
|
||||||
|
@ -103,7 +102,6 @@ struct device_driver {
|
||||||
|
|
||||||
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
|
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
|
||||||
enum probe_type probe_type;
|
enum probe_type probe_type;
|
||||||
bool async_shutdown_enable;
|
|
||||||
|
|
||||||
const struct of_device_id *of_match_table;
|
const struct of_device_id *of_match_table;
|
||||||
const struct acpi_device_id *acpi_match_table;
|
const struct acpi_device_id *acpi_match_table;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user