forked from Minki/linux
Merge branch 'acpi-cleanup'
* acpi-cleanup: (21 commits) ACPI / hotplug: Fix concurrency issues and memory leaks ACPI: Remove the use of CONFIG_ACPI_CONTAINER_MODULE ACPI / scan: Full transition to D3cold in acpi_device_unregister() ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock ACPI: Drop the container.h header file ACPI / Documentation: refer to correct file for acpi_platform_device_ids[] table ACPI / scan: Make container driver use struct acpi_scan_handler ACPI / scan: Remove useless #ifndef from acpi_eject_store() ACPI: Unbind ACPI drv when probe failed ACPI: sysfs eject support for ACPI scan handlers ACPI / scan: Follow priorities of IDs when matching scan handlers ACPI / PCI: pci_slot: replace printk(KERN_xxx) with pr_xxx() ACPI / dock: Fix acpi_bus_get_device() check in drivers/acpi/dock.c ACPI / scan: Clean up acpi_bus_get_parent() ACPI / platform: Use struct acpi_scan_handler for creating devices ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler ACPI / PCI: Make PCI root driver use struct acpi_scan_handler ACPI / scan: Introduce struct acpi_scan_handler ACPI / scan: Make scanning of fixed devices follow the general scheme ACPI: Drop device start operation that is not used ...
This commit is contained in:
commit
e8f71df723
@ -63,8 +63,8 @@ from ACPI tables.
|
||||
Currently the kernel is not able to automatically determine from which ACPI
|
||||
device it should make the corresponding platform device so we need to add
|
||||
the ACPI device explicitly to acpi_platform_device_ids list defined in
|
||||
drivers/acpi/scan.c. This limitation is only for the platform devices, SPI
|
||||
and I2C devices are created automatically as described below.
|
||||
drivers/acpi/acpi_platform.c. This limitation is only for the platform
|
||||
devices, SPI and I2C devices are created automatically as described below.
|
||||
|
||||
SPI serial bus support
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
77
Documentation/acpi/scan_handlers.txt
Normal file
77
Documentation/acpi/scan_handlers.txt
Normal file
@ -0,0 +1,77 @@
|
||||
ACPI Scan Handlers
|
||||
|
||||
Copyright (C) 2012, Intel Corporation
|
||||
Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
|
||||
During system initialization and ACPI-based device hot-add, the ACPI namespace
|
||||
is scanned in search of device objects that generally represent various pieces
|
||||
of hardware. This causes a struct acpi_device object to be created and
|
||||
registered with the driver core for every device object in the ACPI namespace
|
||||
and the hierarchy of those struct acpi_device objects reflects the namespace
|
||||
layout (i.e. parent device objects in the namespace are represented by parent
|
||||
struct acpi_device objects and analogously for their children). Those struct
|
||||
acpi_device objects are referred to as "device nodes" in what follows, but they
|
||||
should not be confused with struct device_node objects used by the Device Trees
|
||||
parsing code (although their role is analogous to the role of those objects).
|
||||
|
||||
During ACPI-based device hot-remove device nodes representing pieces of hardware
|
||||
being removed are unregistered and deleted.
|
||||
|
||||
The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
|
||||
initialization of device nodes, such as retrieving common configuration
|
||||
information from the device objects represented by them and populating them with
|
||||
appropriate data, but some of them require additional handling after they have
|
||||
been registered. For example, if the given device node represents a PCI host
|
||||
bridge, its registration should cause the PCI bus under that bridge to be
|
||||
enumerated and PCI devices on that bus to be registered with the driver core.
|
||||
Similarly, if the device node represents a PCI interrupt link, it is necessary
|
||||
to configure that link so that the kernel can use it.
|
||||
|
||||
Those additional configuration tasks usually depend on the type of the hardware
|
||||
component represented by the given device node which can be determined on the
|
||||
basis of the device node's hardware ID (HID). They are performed by objects
|
||||
called ACPI scan handlers represented by the following structure:
|
||||
|
||||
struct acpi_scan_handler {
|
||||
const struct acpi_device_id *ids;
|
||||
struct list_head list_node;
|
||||
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
|
||||
void (*detach)(struct acpi_device *dev);
|
||||
};
|
||||
|
||||
where ids is the list of IDs of device nodes the given handler is supposed to
|
||||
take care of, list_node is the hook to the global list of ACPI scan handlers
|
||||
maintained by the ACPI core and the .attach() and .detach() callbacks are
|
||||
executed, respectively, after registration of new device nodes and before
|
||||
unregistration of device nodes the handler attached to previously.
|
||||
|
||||
The namespace scanning function, acpi_bus_scan(), first registers all of the
|
||||
device nodes in the given namespace scope with the driver core. Then, it tries
|
||||
to match a scan handler against each of them using the ids arrays of the
|
||||
available scan handlers. If a matching scan handler is found, its .attach()
|
||||
callback is executed for the given device node. If that callback returns 1,
|
||||
that means that the handler has claimed the device node and is now responsible
|
||||
for carrying out any additional configuration tasks related to it. It also will
|
||||
be responsible for preparing the device node for unregistration in that case.
|
||||
The device node's handler field is then populated with the address of the scan
|
||||
handler that has claimed it.
|
||||
|
||||
If the .attach() callback returns 0, it means that the device node is not
|
||||
interesting to the given scan handler and may be matched against the next scan
|
||||
handler in the list. If it returns a (negative) error code, that means that
|
||||
the namespace scan should be terminated due to a serious error. The error code
|
||||
returned should then reflect the type of the error.
|
||||
|
||||
The namespace trimming function, acpi_bus_trim(), first executes .detach()
|
||||
callbacks from the scan handlers of all device nodes in the given namespace
|
||||
scope (if they have scan handlers). Next, it unregisters all of the device
|
||||
nodes in that scope.
|
||||
|
||||
ACPI scan handlers can be added to the list maintained by the ACPI core with the
|
||||
help of the acpi_scan_add_handler() function taking a pointer to the new scan
|
||||
handler as an argument. The order in which scan handlers are added to the list
|
||||
is the order in which they are matched against device nodes during namespace
|
||||
scans.
|
||||
|
||||
All scan handles must be added to the list before acpi_bus_scan() is run for the
|
||||
first time and they cannot be removed from it.
|
@ -191,7 +191,7 @@ static int aml_nfw_add(struct acpi_device *device)
|
||||
return aml_nfw_add_global_handler();
|
||||
}
|
||||
|
||||
static int aml_nfw_remove(struct acpi_device *device, int type)
|
||||
static int aml_nfw_remove(struct acpi_device *device)
|
||||
{
|
||||
return aml_nfw_remove_global_handler();
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ err_sysfs:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int xo15_sci_remove(struct acpi_device *device, int type)
|
||||
static int xo15_sci_remove(struct acpi_device *device)
|
||||
{
|
||||
acpi_disable_gpe(NULL, xo15_sci_gpe);
|
||||
acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
|
||||
|
@ -337,7 +337,7 @@ config X86_PM_TIMER
|
||||
systems require this timer.
|
||||
|
||||
config ACPI_CONTAINER
|
||||
tristate "Container and Module Devices (EXPERIMENTAL)"
|
||||
bool "Container and Module Devices (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
|
||||
help
|
||||
|
@ -60,7 +60,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file);
|
||||
#endif
|
||||
|
||||
static int acpi_ac_add(struct acpi_device *device);
|
||||
static int acpi_ac_remove(struct acpi_device *device, int type);
|
||||
static int acpi_ac_remove(struct acpi_device *device);
|
||||
static void acpi_ac_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id ac_device_ids[] = {
|
||||
@ -337,7 +337,7 @@ static int acpi_ac_resume(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int acpi_ac_remove(struct acpi_device *device, int type)
|
||||
static int acpi_ac_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_ac *ac = NULL;
|
||||
|
||||
|
@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
|
||||
#define MEMORY_POWER_OFF_STATE 2
|
||||
|
||||
static int acpi_memory_device_add(struct acpi_device *device);
|
||||
static int acpi_memory_device_remove(struct acpi_device *device, int type);
|
||||
static int acpi_memory_device_remove(struct acpi_device *device);
|
||||
|
||||
static const struct acpi_device_id memory_device_ids[] = {
|
||||
{ACPI_MEMORY_DEVICE_HID, 0},
|
||||
@ -153,14 +153,16 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_memory_get_device(acpi_handle handle,
|
||||
struct acpi_memory_device **mem_device)
|
||||
static int acpi_memory_get_device(acpi_handle handle,
|
||||
struct acpi_memory_device **mem_device)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
int result;
|
||||
int result = 0;
|
||||
|
||||
if (!acpi_bus_get_device(handle, &device) && device)
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
acpi_bus_get_device(handle, &device);
|
||||
if (device)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
@ -169,23 +171,28 @@ acpi_memory_get_device(acpi_handle handle,
|
||||
*/
|
||||
result = acpi_bus_scan(handle);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "Cannot add acpi bus\n");
|
||||
return -EINVAL;
|
||||
acpi_handle_warn(handle, "ACPI namespace scan failed\n");
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
result = acpi_bus_get_device(handle, &device);
|
||||
if (result) {
|
||||
acpi_handle_warn(handle, "Missing device object\n");
|
||||
return -EINVAL;
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
*mem_device = acpi_driver_data(device);
|
||||
if (!(*mem_device)) {
|
||||
dev_err(&device->dev, "driver data not found\n");
|
||||
return -ENODEV;
|
||||
result = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
|
||||
@ -305,6 +312,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
struct acpi_device *device;
|
||||
struct acpi_eject_event *ej_event = NULL;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
acpi_status status;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
@ -327,29 +335,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"\nReceived EJECT REQUEST notification for device\n"));
|
||||
|
||||
status = AE_ERROR;
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
if (acpi_bus_get_device(handle, &device)) {
|
||||
acpi_handle_err(handle, "Device doesn't exist\n");
|
||||
break;
|
||||
goto unlock;
|
||||
}
|
||||
mem_device = acpi_driver_data(device);
|
||||
if (!mem_device) {
|
||||
acpi_handle_err(handle, "Driver Data is NULL\n");
|
||||
break;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
|
||||
if (!ej_event) {
|
||||
pr_err(PREFIX "No memory, dropping EJECT\n");
|
||||
break;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
get_device(&device->dev);
|
||||
ej_event->device = device;
|
||||
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
|
||||
(void *)ej_event);
|
||||
/* The eject is carried out asynchronously. */
|
||||
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
|
||||
ej_event);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
put_device(&device->dev);
|
||||
kfree(ej_event);
|
||||
}
|
||||
|
||||
/* eject is performed asynchronously */
|
||||
return;
|
||||
unlock:
|
||||
acpi_scan_lock_release();
|
||||
if (ACPI_SUCCESS(status))
|
||||
return;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
@ -360,7 +379,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
|
||||
|
||||
/* Inform firmware that the hotplug operation has completed */
|
||||
(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
|
||||
@ -415,7 +433,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_memory_device_remove(struct acpi_device *device, int type)
|
||||
static int acpi_memory_device_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_memory_device *mem_device = NULL;
|
||||
int result;
|
||||
|
@ -482,8 +482,7 @@ static int acpi_pad_add(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pad_remove(struct acpi_device *device,
|
||||
int type)
|
||||
static int acpi_pad_remove(struct acpi_device *device)
|
||||
{
|
||||
mutex_lock(&isolated_cpus_lock);
|
||||
acpi_pad_idle_cpus(0);
|
||||
|
@ -22,6 +22,30 @@
|
||||
|
||||
ACPI_MODULE_NAME("platform");
|
||||
|
||||
/* Flags for acpi_create_platform_device */
|
||||
#define ACPI_PLATFORM_CLK BIT(0)
|
||||
|
||||
/*
|
||||
* The following ACPI IDs are known to be suitable for representing as
|
||||
* platform devices.
|
||||
*/
|
||||
static const struct acpi_device_id acpi_platform_device_ids[] = {
|
||||
|
||||
{ "PNP0D40" },
|
||||
|
||||
/* Haswell LPSS devices */
|
||||
{ "INT33C0", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C1", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C2", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C3", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C4", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C5", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C6", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C7", ACPI_PLATFORM_CLK },
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static int acpi_create_platform_clks(struct acpi_device *adev)
|
||||
{
|
||||
static struct platform_device *pdev;
|
||||
@ -39,8 +63,7 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
|
||||
/**
|
||||
* acpi_create_platform_device - Create platform device for ACPI device node
|
||||
* @adev: ACPI device node to create a platform device for.
|
||||
* @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
|
||||
* devices.
|
||||
* @id: ACPI device ID used to match @adev.
|
||||
*
|
||||
* Check if the given @adev can be represented as a platform device and, if
|
||||
* that's the case, create and register a platform device, populate its common
|
||||
@ -48,9 +71,10 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
|
||||
*
|
||||
* Name of the platform device will be the same as @adev's.
|
||||
*/
|
||||
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
unsigned long flags)
|
||||
static int acpi_create_platform_device(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
unsigned long flags = id->driver_data;
|
||||
struct platform_device *pdev = NULL;
|
||||
struct acpi_device *acpi_parent;
|
||||
struct platform_device_info pdevinfo;
|
||||
@ -59,25 +83,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
struct resource *resources;
|
||||
int count;
|
||||
|
||||
if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
|
||||
dev_err(&adev->dev, "failed to create clocks\n");
|
||||
return NULL;
|
||||
if (flags & ACPI_PLATFORM_CLK) {
|
||||
int ret = acpi_create_platform_clks(adev);
|
||||
if (ret) {
|
||||
dev_err(&adev->dev, "failed to create clocks\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the ACPI node already has a physical device attached, skip it. */
|
||||
if (adev->physical_node_count)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
|
||||
if (count <= 0)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
|
||||
if (!resources) {
|
||||
dev_err(&adev->dev, "No memory for resources\n");
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
count = 0;
|
||||
list_for_each_entry(rentry, &resource_list, node)
|
||||
@ -123,5 +150,15 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
}
|
||||
|
||||
kfree(resources);
|
||||
return pdev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler platform_handler = {
|
||||
.ids = acpi_platform_device_ids,
|
||||
.attach = acpi_create_platform_device,
|
||||
};
|
||||
|
||||
void __init acpi_platform_init(void)
|
||||
{
|
||||
acpi_scan_add_handler(&platform_handler);
|
||||
}
|
||||
|
@ -1111,7 +1111,7 @@ fail:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_battery_remove(struct acpi_device *device, int type)
|
||||
static int acpi_battery_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_battery *battery = NULL;
|
||||
|
||||
|
@ -75,7 +75,7 @@ static const struct acpi_device_id button_device_ids[] = {
|
||||
MODULE_DEVICE_TABLE(acpi, button_device_ids);
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device);
|
||||
static int acpi_button_remove(struct acpi_device *device, int type);
|
||||
static int acpi_button_remove(struct acpi_device *device);
|
||||
static void acpi_button_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -433,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int acpi_button_remove(struct acpi_device *device, int type)
|
||||
static int acpi_button_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
|
@ -34,46 +34,34 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/container.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
|
||||
#define ACPI_CONTAINER_CLASS "container"
|
||||
|
||||
#define INSTALL_NOTIFY_HANDLER 1
|
||||
#define UNINSTALL_NOTIFY_HANDLER 2
|
||||
|
||||
#define _COMPONENT ACPI_CONTAINER_COMPONENT
|
||||
ACPI_MODULE_NAME("container");
|
||||
|
||||
MODULE_AUTHOR("Anil S Keshavamurthy");
|
||||
MODULE_DESCRIPTION("ACPI container driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_container_add(struct acpi_device *device);
|
||||
static int acpi_container_remove(struct acpi_device *device, int type);
|
||||
|
||||
static const struct acpi_device_id container_device_ids[] = {
|
||||
{"ACPI0004", 0},
|
||||
{"PNP0A05", 0},
|
||||
{"PNP0A06", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, container_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_container_driver = {
|
||||
.name = "container",
|
||||
.class = ACPI_CONTAINER_CLASS,
|
||||
static int container_device_attach(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
/*
|
||||
* FIXME: This is necessary, so that acpi_eject_store() doesn't return
|
||||
* -ENODEV for containers.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler container_device_handler = {
|
||||
.ids = container_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_container_add,
|
||||
.remove = acpi_container_remove,
|
||||
},
|
||||
.attach = container_device_attach,
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
static int is_device_present(acpi_handle handle)
|
||||
{
|
||||
acpi_handle temp;
|
||||
@ -92,49 +80,6 @@ static int is_device_present(acpi_handle handle)
|
||||
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
|
||||
}
|
||||
|
||||
static bool is_container_device(const char *hid)
|
||||
{
|
||||
const struct acpi_device_id *container_id;
|
||||
|
||||
for (container_id = container_device_ids;
|
||||
container_id->id[0]; container_id++) {
|
||||
if (!strcmp((char *)container_id->id, hid))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
static int acpi_container_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_container *container;
|
||||
|
||||
container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
|
||||
if (!container)
|
||||
return -ENOMEM;
|
||||
|
||||
container->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
|
||||
device->driver_data = container;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
|
||||
acpi_device_name(device), acpi_device_bid(device)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_container_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_container *pc = NULL;
|
||||
|
||||
pc = acpi_driver_data(device);
|
||||
kfree(pc);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
@ -143,6 +88,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||
acpi_status status;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
/* Fall through */
|
||||
@ -158,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||
/* device exist and this is a remove request */
|
||||
device->flags.eject_pending = 1;
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -185,98 +132,59 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||
if (!acpi_bus_get_device(handle, &device) && device) {
|
||||
device->flags.eject_pending = 1;
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Inform firmware that the hotplug operation has completed */
|
||||
(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
|
||||
return;
|
||||
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
container_walk_namespace_cb(acpi_handle handle,
|
||||
u32 lvl, void *context, void **rv)
|
||||
static bool is_container(acpi_handle handle)
|
||||
{
|
||||
char *hid = NULL;
|
||||
struct acpi_device_info *info;
|
||||
acpi_status status;
|
||||
int *action = context;
|
||||
bool ret = false;
|
||||
|
||||
status = acpi_get_object_info(handle, &info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return AE_OK;
|
||||
if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
|
||||
return false;
|
||||
|
||||
if (info->valid & ACPI_VALID_HID) {
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
for (id = container_device_ids; id->id[0]; id++) {
|
||||
ret = !strcmp((char *)id->id, info->hardware_id.string);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->valid & ACPI_VALID_HID)
|
||||
hid = info->hardware_id.string;
|
||||
|
||||
if (hid == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!is_container_device(hid))
|
||||
goto end;
|
||||
|
||||
switch (*action) {
|
||||
case INSTALL_NOTIFY_HANDLER:
|
||||
acpi_install_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
container_notify_cb, NULL);
|
||||
break;
|
||||
case UNINSTALL_NOTIFY_HANDLER:
|
||||
acpi_remove_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
container_notify_cb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
kfree(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
|
||||
u32 lvl, void *ctxt,
|
||||
void **retv)
|
||||
{
|
||||
if (is_container(handle))
|
||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
container_notify_cb, NULL);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int __init acpi_container_init(void)
|
||||
void __init acpi_container_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
int action = INSTALL_NOTIFY_HANDLER;
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
||||
acpi_container_register_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_container_driver);
|
||||
if (result < 0) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* register notify handler to every container device */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
container_walk_namespace_cb, NULL, &action, NULL);
|
||||
|
||||
return (0);
|
||||
acpi_scan_add_handler(&container_device_handler);
|
||||
}
|
||||
|
||||
static void __exit acpi_container_exit(void)
|
||||
{
|
||||
int action = UNINSTALL_NOTIFY_HANDLER;
|
||||
|
||||
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
container_walk_namespace_cb, NULL, &action, NULL);
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_container_driver);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_container_init);
|
||||
module_exit(acpi_container_exit);
|
||||
|
@ -744,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context)
|
||||
{
|
||||
struct dock_data *data = context;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
dock_notify(data->handle, data->event, data->ds);
|
||||
acpi_scan_lock_release();
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
@ -757,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this,
|
||||
if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
|
||||
&& event != ACPI_NOTIFY_EJECT_REQUEST)
|
||||
return 0;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
list_for_each_entry(dock_station, &dock_stations, sibling) {
|
||||
if (dock_station->handle == handle) {
|
||||
struct dock_data *dd;
|
||||
acpi_status status;
|
||||
|
||||
dd = kmalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (!dd)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
dd->handle = handle;
|
||||
dd->event = event;
|
||||
dd->ds = dock_station;
|
||||
acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
|
||||
return 0 ;
|
||||
status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
|
||||
dd);
|
||||
if (ACPI_FAILURE(status))
|
||||
kfree(dd);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
acpi_scan_lock_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -825,7 +838,7 @@ static ssize_t show_docked(struct device *dev,
|
||||
|
||||
struct dock_station *dock_station = dev->platform_data;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
|
||||
if (!acpi_bus_get_device(dock_station->handle, &tmp))
|
||||
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
}
|
||||
|
@ -852,7 +852,7 @@ static int acpi_ec_add(struct acpi_device *device)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_ec_remove(struct acpi_device *device, int type)
|
||||
static int acpi_ec_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_ec *ec;
|
||||
struct acpi_ec_query_handler *handler, *tmp;
|
||||
|
@ -45,7 +45,7 @@ MODULE_DESCRIPTION("ACPI Fan Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_fan_add(struct acpi_device *device);
|
||||
static int acpi_fan_remove(struct acpi_device *device, int type);
|
||||
static int acpi_fan_remove(struct acpi_device *device);
|
||||
|
||||
static const struct acpi_device_id fan_device_ids[] = {
|
||||
{"PNP0C0B", 0},
|
||||
@ -172,7 +172,7 @@ static int acpi_fan_add(struct acpi_device *device)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_fan_remove(struct acpi_device *device, int type)
|
||||
static int acpi_fan_remove(struct acpi_device *device)
|
||||
{
|
||||
struct thermal_cooling_device *cdev = acpi_driver_data(device);
|
||||
|
||||
|
@ -70,7 +70,7 @@ static int acpi_hed_add(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_hed_remove(struct acpi_device *device, int type)
|
||||
static int acpi_hed_remove(struct acpi_device *device)
|
||||
{
|
||||
hed_handle = NULL;
|
||||
return 0;
|
||||
|
@ -25,8 +25,16 @@
|
||||
|
||||
int init_acpi_device_notify(void);
|
||||
int acpi_scan_init(void);
|
||||
void acpi_pci_root_init(void);
|
||||
void acpi_pci_link_init(void);
|
||||
void acpi_platform_init(void);
|
||||
int acpi_sysfs_init(void);
|
||||
void acpi_csrt_init(void);
|
||||
#ifdef CONFIG_ACPI_CONTAINER
|
||||
void acpi_container_init(void);
|
||||
#else
|
||||
static inline void acpi_container_init(void) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct dentry *acpi_debugfs_dir;
|
||||
@ -86,7 +94,6 @@ struct acpi_ec {
|
||||
|
||||
extern struct acpi_ec *first_ec;
|
||||
|
||||
int acpi_pci_root_init(void);
|
||||
int acpi_ec_init(void);
|
||||
int acpi_ec_ecdt_probe(void);
|
||||
int acpi_boot_ec_enable(void);
|
||||
@ -118,10 +125,4 @@ static inline void suspend_nvs_restore(void) {}
|
||||
-------------------------------------------------------------------------- */
|
||||
struct platform_device;
|
||||
|
||||
/* Flags for acpi_create_platform_device */
|
||||
#define ACPI_PLATFORM_CLK BIT(0)
|
||||
|
||||
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
unsigned long flags);
|
||||
|
||||
#endif /* _ACPI_INTERNAL_H_ */
|
||||
|
@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link");
|
||||
#define ACPI_PCI_LINK_FILE_STATUS "state"
|
||||
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
|
||||
|
||||
static int acpi_pci_link_add(struct acpi_device *device);
|
||||
static int acpi_pci_link_remove(struct acpi_device *device, int type);
|
||||
static int acpi_pci_link_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used);
|
||||
static void acpi_pci_link_remove(struct acpi_device *device);
|
||||
|
||||
static const struct acpi_device_id link_device_ids[] = {
|
||||
{"PNP0C0F", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, link_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_pci_link_driver = {
|
||||
.name = "pci_link",
|
||||
.class = ACPI_PCI_LINK_CLASS,
|
||||
static struct acpi_scan_handler pci_link_handler = {
|
||||
.ids = link_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_pci_link_add,
|
||||
.remove = acpi_pci_link_remove,
|
||||
},
|
||||
.attach = acpi_pci_link_add,
|
||||
.detach = acpi_pci_link_remove,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle handle)
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static int acpi_pci_link_add(struct acpi_device *device)
|
||||
static int acpi_pci_link_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
int result;
|
||||
struct acpi_pci_link *link;
|
||||
@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
|
||||
if (result)
|
||||
kfree(link);
|
||||
|
||||
return result;
|
||||
return result < 0 ? result : 1;
|
||||
}
|
||||
|
||||
static int acpi_pci_link_resume(struct acpi_pci_link *link)
|
||||
@ -766,7 +763,7 @@ static void irqrouter_resume(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_pci_link_remove(struct acpi_device *device, int type)
|
||||
static void acpi_pci_link_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_pci_link *link;
|
||||
|
||||
@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type)
|
||||
mutex_unlock(&acpi_link_lock);
|
||||
|
||||
kfree(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_syscore_ops = {
|
||||
.resume = irqrouter_resume,
|
||||
};
|
||||
|
||||
static int __init irqrouter_init_ops(void)
|
||||
{
|
||||
if (!acpi_disabled && !acpi_noirq)
|
||||
register_syscore_ops(&irqrouter_syscore_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(irqrouter_init_ops);
|
||||
|
||||
static int __init acpi_pci_link_init(void)
|
||||
void __init acpi_pci_link_init(void)
|
||||
{
|
||||
if (acpi_noirq)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (acpi_irq_balance == -1) {
|
||||
/* no command line switch: enable balancing in IOAPIC mode */
|
||||
@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(void)
|
||||
else
|
||||
acpi_irq_balance = 0;
|
||||
}
|
||||
|
||||
if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
register_syscore_ops(&irqrouter_syscore_ops);
|
||||
acpi_scan_add_handler(&pci_link_handler);
|
||||
}
|
||||
|
||||
subsys_initcall(acpi_pci_link_init);
|
||||
|
@ -45,8 +45,9 @@
|
||||
ACPI_MODULE_NAME("pci_root");
|
||||
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
|
||||
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
|
||||
static int acpi_pci_root_add(struct acpi_device *device);
|
||||
static int acpi_pci_root_remove(struct acpi_device *device, int type);
|
||||
static int acpi_pci_root_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used);
|
||||
static void acpi_pci_root_remove(struct acpi_device *device);
|
||||
|
||||
#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
|
||||
| OSC_ACTIVE_STATE_PWR_SUPPORT \
|
||||
@ -57,16 +58,11 @@ static const struct acpi_device_id root_device_ids[] = {
|
||||
{"PNP0A03", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, root_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_pci_root_driver = {
|
||||
.name = "pci_root",
|
||||
.class = ACPI_PCI_ROOT_CLASS,
|
||||
static struct acpi_scan_handler pci_root_handler = {
|
||||
.ids = root_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_pci_root_add,
|
||||
.remove = acpi_pci_root_remove,
|
||||
},
|
||||
.attach = acpi_pci_root_add,
|
||||
.detach = acpi_pci_root_remove,
|
||||
};
|
||||
|
||||
/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
|
||||
@ -428,7 +424,8 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_pci_osc_control_set);
|
||||
|
||||
static int acpi_pci_root_add(struct acpi_device *device)
|
||||
static int acpi_pci_root_add(struct acpi_device *device,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
unsigned long long segment, bus;
|
||||
acpi_status status;
|
||||
@ -614,7 +611,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
|
||||
pci_enable_bridges(root->bus);
|
||||
|
||||
pci_bus_add_devices(root->bus);
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
out_del_root:
|
||||
mutex_lock(&acpi_pci_root_lock);
|
||||
@ -627,7 +624,7 @@ end:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_pci_root_remove(struct acpi_device *device, int type)
|
||||
static void acpi_pci_root_remove(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
@ -655,19 +652,14 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
|
||||
list_del(&root->node);
|
||||
mutex_unlock(&acpi_pci_root_lock);
|
||||
kfree(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init acpi_pci_root_init(void)
|
||||
void __init acpi_pci_root_init(void)
|
||||
{
|
||||
acpi_hest_init();
|
||||
|
||||
if (acpi_pci_disabled)
|
||||
return 0;
|
||||
|
||||
pci_acpi_crs_quirks();
|
||||
if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
if (!acpi_pci_disabled) {
|
||||
pci_acpi_crs_quirks();
|
||||
acpi_scan_add_handler(&pci_root_handler);
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +50,12 @@ module_param(debug, bool, 0644);
|
||||
ACPI_MODULE_NAME("pci_slot");
|
||||
|
||||
#define MY_NAME "pci_slot"
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg)
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG "%s: " format, \
|
||||
MY_NAME , ## arg); \
|
||||
pr_debug("%s: " format, MY_NAME , ## arg); \
|
||||
} while (0)
|
||||
|
||||
#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */
|
||||
|
@ -81,7 +81,7 @@ MODULE_DESCRIPTION("ACPI Processor Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_processor_add(struct acpi_device *device);
|
||||
static int acpi_processor_remove(struct acpi_device *device, int type);
|
||||
static int acpi_processor_remove(struct acpi_device *device);
|
||||
static void acpi_processor_notify(struct acpi_device *device, u32 event);
|
||||
static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr);
|
||||
@ -610,7 +610,7 @@ err_free_pr:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_processor_remove(struct acpi_device *device, int type)
|
||||
static int acpi_processor_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_processor *pr = NULL;
|
||||
|
||||
@ -623,7 +623,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
|
||||
if (pr->id >= nr_cpu_ids)
|
||||
goto free;
|
||||
|
||||
if (type == ACPI_BUS_REMOVAL_EJECT) {
|
||||
if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) {
|
||||
if (acpi_processor_handle_eject(pr))
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -683,8 +683,11 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_eject_event *ej_event = NULL;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
acpi_status status;
|
||||
int result;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
@ -733,25 +736,32 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
|
||||
break;
|
||||
}
|
||||
|
||||
get_device(&device->dev);
|
||||
ej_event->device = device;
|
||||
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
|
||||
acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
|
||||
(void *)ej_event);
|
||||
|
||||
/* eject is performed asynchronously */
|
||||
return;
|
||||
/* The eject is carried out asynchronously. */
|
||||
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
|
||||
ej_event);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
put_device(&device->dev);
|
||||
kfree(ej_event);
|
||||
break;
|
||||
}
|
||||
goto out;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
|
||||
/* non-hotplug event; possibly handled by other handler */
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Inform firmware that the hotplug operation has completed */
|
||||
(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
|
||||
return;
|
||||
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
static acpi_status is_processor_device(acpi_handle handle)
|
||||
|
@ -130,7 +130,7 @@ struct acpi_sbs {
|
||||
|
||||
#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
|
||||
|
||||
static int acpi_sbs_remove(struct acpi_device *device, int type);
|
||||
static int acpi_sbs_remove(struct acpi_device *device);
|
||||
static int acpi_battery_get_state(struct acpi_battery *battery);
|
||||
|
||||
static inline int battery_scale(int log)
|
||||
@ -949,11 +949,11 @@ static int acpi_sbs_add(struct acpi_device *device)
|
||||
acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
|
||||
end:
|
||||
if (result)
|
||||
acpi_sbs_remove(device, 0);
|
||||
acpi_sbs_remove(device);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_sbs_remove(struct acpi_device *device, int type)
|
||||
static int acpi_sbs_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_sbs *sbs;
|
||||
int id;
|
||||
|
@ -33,7 +33,7 @@ struct acpi_smb_hc {
|
||||
};
|
||||
|
||||
static int acpi_smbus_hc_add(struct acpi_device *device);
|
||||
static int acpi_smbus_hc_remove(struct acpi_device *device, int type);
|
||||
static int acpi_smbus_hc_remove(struct acpi_device *device);
|
||||
|
||||
static const struct acpi_device_id sbs_device_ids[] = {
|
||||
{"ACPI0001", 0},
|
||||
@ -296,7 +296,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
|
||||
|
||||
extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
|
||||
|
||||
static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
|
||||
static int acpi_smbus_hc_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_smb_hc *hc;
|
||||
|
||||
|
@ -29,30 +29,10 @@ extern struct acpi_device *acpi_root;
|
||||
|
||||
static const char *dummy_hid = "device";
|
||||
|
||||
/*
|
||||
* The following ACPI IDs are known to be suitable for representing as
|
||||
* platform devices.
|
||||
*/
|
||||
static const struct acpi_device_id acpi_platform_device_ids[] = {
|
||||
|
||||
{ "PNP0D40" },
|
||||
|
||||
/* Haswell LPSS devices */
|
||||
{ "INT33C0", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C1", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C2", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C3", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C4", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C5", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C6", ACPI_PLATFORM_CLK },
|
||||
{ "INT33C7", ACPI_PLATFORM_CLK },
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static LIST_HEAD(acpi_device_list);
|
||||
static LIST_HEAD(acpi_bus_id_list);
|
||||
static DEFINE_MUTEX(acpi_scan_lock);
|
||||
static LIST_HEAD(acpi_scan_handlers_list);
|
||||
DEFINE_MUTEX(acpi_device_lock);
|
||||
LIST_HEAD(acpi_wakeup_device_list);
|
||||
|
||||
@ -62,6 +42,27 @@ struct acpi_device_bus_id{
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
void acpi_scan_lock_acquire(void)
|
||||
{
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire);
|
||||
|
||||
void acpi_scan_lock_release(void)
|
||||
{
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
|
||||
|
||||
int acpi_scan_add_handler(struct acpi_scan_handler *handler)
|
||||
{
|
||||
if (!handler || !handler->attach)
|
||||
return -EINVAL;
|
||||
|
||||
list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates hid/cid(s) string needed for modalias and uevent
|
||||
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
|
||||
@ -116,7 +117,7 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
|
||||
*/
|
||||
void acpi_bus_hot_remove_device(void *context)
|
||||
{
|
||||
struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
|
||||
struct acpi_eject_event *ej_event = context;
|
||||
struct acpi_device *device = ej_event->device;
|
||||
acpi_handle handle = device->handle;
|
||||
acpi_handle temp;
|
||||
@ -125,19 +126,23 @@ void acpi_bus_hot_remove_device(void *context)
|
||||
acpi_status status = AE_OK;
|
||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
/* If there is no handle, the device node has been unregistered. */
|
||||
if (!device->handle) {
|
||||
dev_dbg(&device->dev, "ACPI handle missing\n");
|
||||
put_device(&device->dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Hot-removing device %s...\n", dev_name(&device->dev)));
|
||||
|
||||
acpi_bus_trim(device);
|
||||
/* Device node has been released. */
|
||||
/* Device node has been unregistered. */
|
||||
put_device(&device->dev);
|
||||
device = NULL;
|
||||
|
||||
/* power off device */
|
||||
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Power-off device failed\n");
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
@ -157,18 +162,15 @@ void acpi_bus_hot_remove_device(void *context)
|
||||
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (status != AE_NOT_FOUND)
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Eject device failed\n");
|
||||
goto err_out;
|
||||
acpi_handle_warn(handle, "Eject failed\n");
|
||||
|
||||
/* Tell the firmware the hot-remove operation has failed. */
|
||||
acpi_evaluate_hotplug_ost(handle, ej_event->event,
|
||||
ost_code, NULL);
|
||||
}
|
||||
|
||||
kfree(context);
|
||||
return;
|
||||
|
||||
err_out:
|
||||
/* Inform firmware the hot-remove operation has completed w/ error */
|
||||
(void) acpi_evaluate_hotplug_ost(handle,
|
||||
ej_event->event, ost_code, NULL);
|
||||
out:
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
kfree(context);
|
||||
return;
|
||||
}
|
||||
@ -213,12 +215,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
if ((!count) || (buf[0] != '1')) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#ifndef FORCE_EJECT
|
||||
if (acpi_device->driver == NULL) {
|
||||
if (!acpi_device->driver && !acpi_device->handler) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
status = acpi_get_type(acpi_device->handle, &type);
|
||||
if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
|
||||
ret = -ENODEV;
|
||||
@ -231,6 +231,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
goto err;
|
||||
}
|
||||
|
||||
get_device(&acpi_device->dev);
|
||||
ej_event->device = acpi_device;
|
||||
if (acpi_device->flags.eject_pending) {
|
||||
/* event originated from ACPI eject notification */
|
||||
@ -243,7 +244,11 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
|
||||
}
|
||||
|
||||
acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event);
|
||||
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
put_device(&acpi_device->dev);
|
||||
kfree(ej_event);
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -637,8 +642,9 @@ static int acpi_device_probe(struct device * dev)
|
||||
ret = acpi_device_install_notify_handler(acpi_dev);
|
||||
if (ret) {
|
||||
if (acpi_drv->ops.remove)
|
||||
acpi_drv->ops.remove(acpi_dev,
|
||||
acpi_dev->removal_type);
|
||||
acpi_drv->ops.remove(acpi_dev);
|
||||
acpi_dev->driver = NULL;
|
||||
acpi_dev->driver_data = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -660,7 +666,7 @@ static int acpi_device_remove(struct device * dev)
|
||||
if (acpi_drv->ops.notify)
|
||||
acpi_device_remove_notify_handler(acpi_dev);
|
||||
if (acpi_drv->ops.remove)
|
||||
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
|
||||
acpi_drv->ops.remove(acpi_dev);
|
||||
}
|
||||
acpi_dev->driver = NULL;
|
||||
acpi_dev->driver_data = NULL;
|
||||
@ -792,10 +798,12 @@ static void acpi_device_unregister(struct acpi_device *device)
|
||||
|
||||
device_del(&device->dev);
|
||||
/*
|
||||
* Drop the reference counts of all power resources the device depends
|
||||
* on and turn off the ones that have no more references.
|
||||
* Transition the device to D3cold to drop the reference counts of all
|
||||
* power resources the device depends on and turn off the ones that have
|
||||
* no more references.
|
||||
*/
|
||||
acpi_power_transition(device, ACPI_STATE_D3_COLD);
|
||||
acpi_device_set_power(device, ACPI_STATE_D3_COLD);
|
||||
device->handle = NULL;
|
||||
put_device(&device->dev);
|
||||
}
|
||||
|
||||
@ -883,29 +891,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver);
|
||||
-------------------------------------------------------------------------- */
|
||||
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
struct acpi_device *device;
|
||||
|
||||
/*
|
||||
* Fixed hardware devices do not appear in the namespace and do not
|
||||
* have handles, but we fabricate acpi_devices for them, so we have
|
||||
* to deal with them specially.
|
||||
*/
|
||||
if (handle == NULL)
|
||||
if (!handle)
|
||||
return acpi_root;
|
||||
|
||||
do {
|
||||
status = acpi_get_parent(handle, &handle);
|
||||
if (status == AE_NULL_ENTRY)
|
||||
return NULL;
|
||||
if (ACPI_FAILURE(status))
|
||||
return acpi_root;
|
||||
|
||||
ret = acpi_bus_get_device(handle, &device);
|
||||
if (ret == 0)
|
||||
return device;
|
||||
} while (1);
|
||||
return status == AE_NULL_ENTRY ? NULL : acpi_root;
|
||||
} while (acpi_bus_get_device(handle, &device));
|
||||
return device;
|
||||
}
|
||||
|
||||
acpi_status
|
||||
@ -1441,19 +1443,21 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
acpi_device_get_busid(device);
|
||||
acpi_device_set_id(device);
|
||||
acpi_bus_get_flags(device);
|
||||
device->flags.match_driver = false;
|
||||
device_initialize(&device->dev);
|
||||
dev_set_uevent_suppress(&device->dev, true);
|
||||
}
|
||||
|
||||
void acpi_device_add_finalize(struct acpi_device *device)
|
||||
{
|
||||
device->flags.match_driver = true;
|
||||
dev_set_uevent_suppress(&device->dev, false);
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
|
||||
static int acpi_add_single_object(struct acpi_device **child,
|
||||
acpi_handle handle, int type,
|
||||
unsigned long long sta, bool match_driver)
|
||||
unsigned long long sta)
|
||||
{
|
||||
int result;
|
||||
struct acpi_device *device;
|
||||
@ -1469,7 +1473,6 @@ static int acpi_add_single_object(struct acpi_device **child,
|
||||
acpi_bus_get_power_flags(device);
|
||||
acpi_bus_get_wakeup_device_flags(device);
|
||||
|
||||
device->flags.match_driver = match_driver;
|
||||
result = acpi_device_add(device, acpi_device_release);
|
||||
if (result) {
|
||||
acpi_device_release(&device->dev);
|
||||
@ -1562,12 +1565,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
||||
return AE_CTRL_DEPTH;
|
||||
}
|
||||
|
||||
acpi_add_single_object(&device, handle, type, sta, false);
|
||||
acpi_add_single_object(&device, handle, type, sta);
|
||||
if (!device)
|
||||
return AE_CTRL_DEPTH;
|
||||
|
||||
device->flags.match_driver = true;
|
||||
|
||||
out:
|
||||
if (!*return_value)
|
||||
*return_value = device;
|
||||
@ -1575,33 +1576,68 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
|
||||
{
|
||||
struct acpi_scan_handler *handler;
|
||||
|
||||
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
|
||||
const struct acpi_device_id *devid;
|
||||
|
||||
for (devid = handler->ids; devid->id[0]; devid++) {
|
||||
int ret;
|
||||
|
||||
if (strcmp((char *)devid->id, id))
|
||||
continue;
|
||||
|
||||
ret = handler->attach(device, devid);
|
||||
if (ret > 0) {
|
||||
device->handler = handler;
|
||||
return ret;
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_scan_attach_handler(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_hardware_id *hwid;
|
||||
int ret = 0;
|
||||
|
||||
list_for_each_entry(hwid, &device->pnp.ids, list) {
|
||||
ret = acpi_scan_do_attach_handler(device, hwid->id);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
|
||||
void *not_used, void **ret_not_used)
|
||||
{
|
||||
const struct acpi_device_id *id;
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_device *device;
|
||||
unsigned long long sta_not_used;
|
||||
int type_not_used;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Ignore errors ignored by acpi_bus_check_add() to avoid terminating
|
||||
* namespace walks prematurely.
|
||||
*/
|
||||
if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
|
||||
if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
|
||||
return AE_OK;
|
||||
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
return AE_CTRL_DEPTH;
|
||||
|
||||
id = __acpi_match_device(device, acpi_platform_device_ids);
|
||||
if (id) {
|
||||
/* This is a known good platform device. */
|
||||
acpi_create_platform_device(device, id->driver_data);
|
||||
} else if (device_attach(&device->dev) < 0) {
|
||||
status = AE_CTRL_DEPTH;
|
||||
}
|
||||
return status;
|
||||
ret = acpi_scan_attach_handler(device);
|
||||
if (ret)
|
||||
return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
|
||||
|
||||
ret = device_attach(&device->dev);
|
||||
return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1615,14 +1651,14 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
|
||||
* there has been a real error. There just have been no suitable ACPI objects
|
||||
* in the table trunk from which the kernel could create a device and add an
|
||||
* appropriate driver.
|
||||
*
|
||||
* Must be called under acpi_scan_lock.
|
||||
*/
|
||||
int acpi_bus_scan(acpi_handle handle)
|
||||
{
|
||||
void *device = NULL;
|
||||
int error = 0;
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
|
||||
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
|
||||
acpi_bus_check_add, NULL, NULL, &device);
|
||||
@ -1633,7 +1669,6 @@ int acpi_bus_scan(acpi_handle handle)
|
||||
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
|
||||
acpi_bus_device_attach, NULL, NULL, NULL);
|
||||
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_scan);
|
||||
@ -1644,8 +1679,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
if (!acpi_bus_get_device(handle, &device)) {
|
||||
struct acpi_scan_handler *dev_handler = device->handler;
|
||||
|
||||
device->removal_type = ACPI_BUS_REMOVAL_EJECT;
|
||||
device_release_driver(&device->dev);
|
||||
if (dev_handler) {
|
||||
if (dev_handler->detach)
|
||||
dev_handler->detach(device);
|
||||
|
||||
device->handler = NULL;
|
||||
} else {
|
||||
device_release_driver(&device->dev);
|
||||
}
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
@ -1661,10 +1705,14 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_bus_trim - Remove ACPI device node and all of its descendants
|
||||
* @start: Root of the ACPI device nodes subtree to remove.
|
||||
*
|
||||
* Must be called under acpi_scan_lock.
|
||||
*/
|
||||
void acpi_bus_trim(struct acpi_device *start)
|
||||
{
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
|
||||
/*
|
||||
* Execute acpi_bus_device_detach() as a post-order callback to detach
|
||||
* all ACPI drivers from the device nodes being removed.
|
||||
@ -1679,33 +1727,45 @@ void acpi_bus_trim(struct acpi_device *start)
|
||||
acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
|
||||
acpi_bus_remove, NULL, NULL);
|
||||
acpi_bus_remove(start->handle, 0, NULL, NULL);
|
||||
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_bus_trim);
|
||||
|
||||
static int acpi_bus_scan_fixed(void)
|
||||
{
|
||||
int result = 0;
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
/*
|
||||
* Enumerate all fixed-feature devices.
|
||||
*/
|
||||
if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
result = acpi_add_single_object(&device, NULL,
|
||||
ACPI_BUS_TYPE_POWER_BUTTON,
|
||||
ACPI_STA_DEFAULT, true);
|
||||
ACPI_STA_DEFAULT);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = device_attach(&device->dev);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
device_init_wakeup(&device->dev, true);
|
||||
}
|
||||
|
||||
if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) {
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
result = acpi_add_single_object(&device, NULL,
|
||||
ACPI_BUS_TYPE_SLEEP_BUTTON,
|
||||
ACPI_STA_DEFAULT, true);
|
||||
ACPI_STA_DEFAULT);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = device_attach(&device->dev);
|
||||
}
|
||||
|
||||
return result;
|
||||
return result < 0 ? result : 0;
|
||||
}
|
||||
|
||||
int __init acpi_scan_init(void)
|
||||
@ -1719,25 +1779,32 @@ int __init acpi_scan_init(void)
|
||||
}
|
||||
|
||||
acpi_pci_root_init();
|
||||
acpi_pci_link_init();
|
||||
acpi_platform_init();
|
||||
acpi_csrt_init();
|
||||
acpi_container_init();
|
||||
|
||||
mutex_lock(&acpi_scan_lock);
|
||||
/*
|
||||
* Enumerate devices in the ACPI namespace.
|
||||
*/
|
||||
result = acpi_bus_scan(ACPI_ROOT_OBJECT);
|
||||
if (result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
|
||||
if (result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
result = acpi_bus_scan_fixed();
|
||||
if (result) {
|
||||
acpi_device_unregister(acpi_root);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acpi_update_all_gpes();
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_scan_lock);
|
||||
return result;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ module_param(psv, int, 0644);
|
||||
MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
|
||||
|
||||
static int acpi_thermal_add(struct acpi_device *device);
|
||||
static int acpi_thermal_remove(struct acpi_device *device, int type);
|
||||
static int acpi_thermal_remove(struct acpi_device *device);
|
||||
static void acpi_thermal_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id thermal_device_ids[] = {
|
||||
@ -1111,7 +1111,7 @@ end:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_thermal_remove(struct acpi_device *device, int type)
|
||||
static int acpi_thermal_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_thermal *tz = NULL;
|
||||
|
||||
|
@ -88,7 +88,7 @@ module_param(use_bios_initial_backlight, bool, 0644);
|
||||
|
||||
static int register_count = 0;
|
||||
static int acpi_video_bus_add(struct acpi_device *device);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device, int type);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device);
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id video_device_ids[] = {
|
||||
@ -1740,7 +1740,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int acpi_video_bus_remove(struct acpi_device *device, int type)
|
||||
static int acpi_video_bus_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_video_bus *video = NULL;
|
||||
|
||||
|
@ -1041,7 +1041,7 @@ static int hpet_acpi_add(struct acpi_device *device)
|
||||
return hpet_alloc(&data);
|
||||
}
|
||||
|
||||
static int hpet_acpi_remove(struct acpi_device *device, int type)
|
||||
static int hpet_acpi_remove(struct acpi_device *device)
|
||||
{
|
||||
/* XXX need to unregister clocksource, dealloc mem, etc */
|
||||
return -EINVAL;
|
||||
|
@ -1142,7 +1142,7 @@ static int sonypi_acpi_add(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sonypi_acpi_remove(struct acpi_device *device, int type)
|
||||
static int sonypi_acpi_remove(struct acpi_device *device)
|
||||
{
|
||||
sonypi_acpi_device = NULL;
|
||||
return 0;
|
||||
|
@ -911,7 +911,7 @@ exit:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int acpi_power_meter_remove(struct acpi_device *device, int type)
|
||||
static int acpi_power_meter_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_power_meter_resource *resource;
|
||||
|
||||
|
@ -190,7 +190,7 @@ struct atk_acpi_input_buf {
|
||||
};
|
||||
|
||||
static int atk_add(struct acpi_device *device);
|
||||
static int atk_remove(struct acpi_device *device, int type);
|
||||
static int atk_remove(struct acpi_device *device);
|
||||
static void atk_print_sensor(struct atk_data *data, union acpi_object *obj);
|
||||
static int atk_read_value(struct atk_sensor_data *sensor, u64 *value);
|
||||
static void atk_free_sensors(struct atk_data *data);
|
||||
@ -1416,7 +1416,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atk_remove(struct acpi_device *device, int type)
|
||||
static int atk_remove(struct acpi_device *device)
|
||||
{
|
||||
struct atk_data *data = device->driver_data;
|
||||
dev_dbg(&device->dev, "removing...\n");
|
||||
|
@ -406,7 +406,7 @@ err:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int acpi_smbus_cmi_remove(struct acpi_device *device, int type)
|
||||
static int acpi_smbus_cmi_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device);
|
||||
|
||||
|
@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atlas_acpi_button_remove(struct acpi_device *device, int type)
|
||||
static int atlas_acpi_button_remove(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
@ -1218,6 +1218,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
|
||||
handle = hp_work->handle;
|
||||
type = hp_work->type;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
if (acpi_bus_get_device(handle, &device)) {
|
||||
/* This bridge must have just been physically inserted */
|
||||
handle_bridge_insertion(handle, type);
|
||||
@ -1295,6 +1297,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
|
||||
}
|
||||
|
||||
out:
|
||||
acpi_scan_lock_release();
|
||||
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
|
||||
}
|
||||
|
||||
@ -1341,6 +1344,8 @@ static void _handle_hotplug_event_func(struct work_struct *work)
|
||||
|
||||
func = (struct acpiphp_func *)context;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
/* bus re-enumerate */
|
||||
@ -1371,6 +1376,7 @@ static void _handle_hotplug_event_func(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
acpi_scan_lock_release();
|
||||
kfree(hp_work); /* allocated in handle_hotplug_event_func */
|
||||
}
|
||||
|
||||
|
@ -425,6 +425,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
pdevice = NULL;
|
||||
}
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
/*
|
||||
* Walk the rootbus node's immediate children looking for
|
||||
* the slot's device node(s). There can be more than
|
||||
@ -458,6 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
/* Call the driver for the new device */
|
||||
@ -508,6 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
/* Get the rootbus node pointer */
|
||||
phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
|
||||
|
||||
acpi_scan_lock_acquire();
|
||||
/*
|
||||
* Walk the rootbus node's immediate children looking for
|
||||
* the slot's device node(s). There can be more than
|
||||
@ -538,7 +541,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
acpi_bus_trim(device);
|
||||
}
|
||||
}
|
||||
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
/* Free the SN resources assigned to the Linux device.*/
|
||||
|
@ -1910,7 +1910,7 @@ fail_platform:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int asus_acpi_remove(struct acpi_device *device, int type)
|
||||
static int asus_acpi_remove(struct acpi_device *device)
|
||||
{
|
||||
struct asus_laptop *asus = acpi_driver_data(device);
|
||||
|
||||
|
@ -432,7 +432,7 @@ failed_sensitivity:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type)
|
||||
static int cmpc_accel_remove_v4(struct acpi_device *acpi)
|
||||
{
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
@ -668,7 +668,7 @@ failed_file:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmpc_accel_remove(struct acpi_device *acpi, int type)
|
||||
static int cmpc_accel_remove(struct acpi_device *acpi)
|
||||
{
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
@ -753,7 +753,7 @@ static int cmpc_tablet_add(struct acpi_device *acpi)
|
||||
cmpc_tablet_idev_init);
|
||||
}
|
||||
|
||||
static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
|
||||
static int cmpc_tablet_remove(struct acpi_device *acpi)
|
||||
{
|
||||
return cmpc_remove_acpi_notify_device(acpi);
|
||||
}
|
||||
@ -1000,7 +1000,7 @@ out_bd:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cmpc_ipml_remove(struct acpi_device *acpi, int type)
|
||||
static int cmpc_ipml_remove(struct acpi_device *acpi)
|
||||
{
|
||||
struct ipml200_dev *ipml;
|
||||
|
||||
@ -1079,7 +1079,7 @@ static int cmpc_keys_add(struct acpi_device *acpi)
|
||||
cmpc_keys_idev_init);
|
||||
}
|
||||
|
||||
static int cmpc_keys_remove(struct acpi_device *acpi, int type)
|
||||
static int cmpc_keys_remove(struct acpi_device *acpi)
|
||||
{
|
||||
return cmpc_remove_acpi_notify_device(acpi);
|
||||
}
|
||||
|
@ -1501,7 +1501,7 @@ fail_platform:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int eeepc_acpi_remove(struct acpi_device *device, int type)
|
||||
static int eeepc_acpi_remove(struct acpi_device *device)
|
||||
{
|
||||
struct eeepc_laptop *eeepc = acpi_driver_data(device);
|
||||
|
||||
|
@ -733,7 +733,7 @@ err_stop:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_fujitsu_remove(struct acpi_device *device, int type)
|
||||
static int acpi_fujitsu_remove(struct acpi_device *device)
|
||||
{
|
||||
struct fujitsu_t *fujitsu = acpi_driver_data(device);
|
||||
struct input_dev *input = fujitsu->input;
|
||||
@ -938,7 +938,7 @@ err_stop:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
|
||||
static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)
|
||||
{
|
||||
struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
|
||||
struct input_dev *input = fujitsu_hotkey->input;
|
||||
|
@ -431,7 +431,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_fujitsu_remove(struct acpi_device *adev, int type)
|
||||
static int acpi_fujitsu_remove(struct acpi_device *adev)
|
||||
{
|
||||
free_irq(fujitsu.irq, fujitsu_interrupt);
|
||||
release_region(fujitsu.io_base, fujitsu.io_length);
|
||||
|
@ -337,7 +337,7 @@ static int lis3lv02d_add(struct acpi_device *device)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lis3lv02d_remove(struct acpi_device *device, int type)
|
||||
static int lis3lv02d_remove(struct acpi_device *device)
|
||||
{
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
@ -834,7 +834,7 @@ platform_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
|
||||
static int ideapad_acpi_remove(struct acpi_device *adevice)
|
||||
{
|
||||
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
|
||||
int i;
|
||||
|
@ -200,7 +200,7 @@ static int intel_menlow_memory_add(struct acpi_device *device)
|
||||
|
||||
}
|
||||
|
||||
static int intel_menlow_memory_remove(struct acpi_device *device, int type)
|
||||
static int intel_menlow_memory_remove(struct acpi_device *device)
|
||||
{
|
||||
struct thermal_cooling_device *cdev = acpi_driver_data(device);
|
||||
|
||||
|
@ -176,7 +176,7 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
|
||||
/* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
|
||||
|
||||
static int acpi_pcc_hotkey_add(struct acpi_device *device);
|
||||
static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
|
||||
static int acpi_pcc_hotkey_remove(struct acpi_device *device);
|
||||
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id pcc_device_ids[] = {
|
||||
@ -663,7 +663,7 @@ static int __init acpi_pcc_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
|
||||
static int acpi_pcc_hotkey_remove(struct acpi_device *device)
|
||||
{
|
||||
struct pcc_acpi *pcc = acpi_driver_data(device);
|
||||
|
||||
|
@ -2740,7 +2740,7 @@ outwalk:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sony_nc_remove(struct acpi_device *device, int type)
|
||||
static int sony_nc_remove(struct acpi_device *device)
|
||||
{
|
||||
struct sony_nc_value *item;
|
||||
|
||||
@ -4111,7 +4111,7 @@ found:
|
||||
* ACPI driver
|
||||
*
|
||||
*****************/
|
||||
static int sony_pic_remove(struct acpi_device *device, int type)
|
||||
static int sony_pic_remove(struct acpi_device *device)
|
||||
{
|
||||
struct sony_pic_ioport *io, *tmp_io;
|
||||
struct sony_pic_irq *irq, *tmp_irq;
|
||||
|
@ -157,7 +157,7 @@ add_err:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int acpi_topstar_remove(struct acpi_device *device, int type)
|
||||
static int acpi_topstar_remove(struct acpi_device *device)
|
||||
{
|
||||
struct topstar_hkey *tps_hkey = acpi_driver_data(device);
|
||||
|
||||
|
@ -1118,7 +1118,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
|
||||
static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
|
||||
{
|
||||
struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
|
||||
|
||||
@ -1250,7 +1250,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
toshiba_acpi_remove(acpi_dev, 0);
|
||||
toshiba_acpi_remove(acpi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
static int toshiba_bt_rfkill_add(struct acpi_device *device);
|
||||
static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
|
||||
static int toshiba_bt_rfkill_remove(struct acpi_device *device);
|
||||
static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id bt_device_ids[] = {
|
||||
@ -122,7 +122,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
|
||||
static int toshiba_bt_rfkill_remove(struct acpi_device *device)
|
||||
{
|
||||
/* clean up */
|
||||
return 0;
|
||||
|
@ -92,7 +92,7 @@ module_param(debug_dump_wdg, bool, 0444);
|
||||
MODULE_PARM_DESC(debug_dump_wdg,
|
||||
"Dump available WMI interfaces [0/1]");
|
||||
|
||||
static int acpi_wmi_remove(struct acpi_device *device, int type);
|
||||
static int acpi_wmi_remove(struct acpi_device *device);
|
||||
static int acpi_wmi_add(struct acpi_device *device);
|
||||
static void acpi_wmi_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
@ -917,7 +917,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_wmi_remove(struct acpi_device *device, int type)
|
||||
static int acpi_wmi_remove(struct acpi_device *device)
|
||||
{
|
||||
acpi_remove_address_space_handler(device->handle,
|
||||
ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
|
||||
|
@ -150,7 +150,7 @@ static int ebook_switch_add(struct acpi_device *device)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ebook_switch_remove(struct acpi_device *device, int type)
|
||||
static int ebook_switch_remove(struct acpi_device *device)
|
||||
{
|
||||
struct ebook_switch *button = acpi_driver_data(device);
|
||||
|
||||
|
@ -296,7 +296,7 @@ fail_config:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int quickstart_acpi_remove(struct acpi_device *device, int type)
|
||||
static int quickstart_acpi_remove(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
struct quickstart_acpi *quickstart;
|
||||
|
@ -196,7 +196,7 @@ static int apple_bl_add(struct acpi_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apple_bl_remove(struct acpi_device *dev, int type)
|
||||
static int apple_bl_remove(struct acpi_device *dev)
|
||||
{
|
||||
backlight_device_unregister(apple_backlight_device);
|
||||
|
||||
|
@ -140,8 +140,7 @@ static int acpi_pad_add(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pad_remove(struct acpi_device *device,
|
||||
int type)
|
||||
static int acpi_pad_remove(struct acpi_device *device)
|
||||
{
|
||||
mutex_lock(&xen_cpu_lock);
|
||||
xen_acpi_pad_idle_cpus(0);
|
||||
|
@ -83,20 +83,30 @@ enum acpi_bus_device_type {
|
||||
struct acpi_driver;
|
||||
struct acpi_device;
|
||||
|
||||
/*
|
||||
* ACPI Scan Handler
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
struct acpi_scan_handler {
|
||||
const struct acpi_device_id *ids;
|
||||
struct list_head list_node;
|
||||
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
|
||||
void (*detach)(struct acpi_device *dev);
|
||||
};
|
||||
|
||||
/*
|
||||
* ACPI Driver
|
||||
* -----------
|
||||
*/
|
||||
|
||||
typedef int (*acpi_op_add) (struct acpi_device * device);
|
||||
typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
|
||||
typedef int (*acpi_op_start) (struct acpi_device * device);
|
||||
typedef int (*acpi_op_remove) (struct acpi_device * device);
|
||||
typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
|
||||
|
||||
struct acpi_device_ops {
|
||||
acpi_op_add add;
|
||||
acpi_op_remove remove;
|
||||
acpi_op_start start;
|
||||
acpi_op_notify notify;
|
||||
};
|
||||
|
||||
@ -271,6 +281,7 @@ struct acpi_device {
|
||||
struct acpi_device_wakeup wakeup;
|
||||
struct acpi_device_perf performance;
|
||||
struct acpi_device_dir dir;
|
||||
struct acpi_scan_handler *handler;
|
||||
struct acpi_driver *driver;
|
||||
void *driver_data;
|
||||
struct device dev;
|
||||
@ -384,6 +395,10 @@ int acpi_bus_receive_event(struct acpi_bus_event *event);
|
||||
static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
|
||||
{ return 0; }
|
||||
#endif
|
||||
|
||||
void acpi_scan_lock_acquire(void);
|
||||
void acpi_scan_lock_release(void);
|
||||
int acpi_scan_add_handler(struct acpi_scan_handler *handler);
|
||||
int acpi_bus_register_driver(struct acpi_driver *driver);
|
||||
void acpi_bus_unregister_driver(struct acpi_driver *driver);
|
||||
int acpi_bus_scan(acpi_handle handle);
|
||||
|
@ -1,12 +0,0 @@
|
||||
#ifndef __ACPI_CONTAINER_H
|
||||
#define __ACPI_CONTAINER_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
struct acpi_container {
|
||||
acpi_handle handle;
|
||||
unsigned long sun;
|
||||
int state;
|
||||
};
|
||||
|
||||
#endif /* __ACPI_CONTAINER_H */
|
@ -363,8 +363,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
|
||||
#if defined(CONFIG_ACPI_HOTPLUG_CPU) && \
|
||||
(defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
|
||||
defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) && \
|
||||
(defined(CONFIG_ACPI_CONTAINER) || \
|
||||
defined(CONFIG_ACPI_CONTAINER_MODULE))
|
||||
defined(CONFIG_ACPI_CONTAINER)
|
||||
#define ACPI_HOTPLUG_OST
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user