Skip to content

Commit

Permalink
Merge branch 'acpi-hotplug'
Browse files Browse the repository at this point in the history
* acpi-hotplug:
  ACPI / scan: ACPI device object sysfs attribute for _STA evaluation
  ACPI / hotplug / driver core: Handle containers in a special way
  ACPI / hotplug: Add demand_offline hotplug profile flag
  ACPI / bind: Move acpi_get_child() to drivers/ide/ide-acpi.c
  ACPI / bind: Pass struct acpi_device pointer to acpi_bind_one()
  ACPI / bind: Rework struct acpi_bus_type
  ACPI / bind: Redefine acpi_preset_companion()
  ACPI / bind: Redefine acpi_get_child()
  PCI / ACPI: Use acpi_find_child_device() for child devices lookup
  ACPI / bind: Simplify child device lookups
  ACPI / scan: Use direct recurrence for device hierarchy walks
  ACPI: Introduce acpi_set_device_status()
  ACPI / hotplug: Drop unfinished global notification handling routines
  ACPI / hotplug: Rework generic code to handle suprise removals
  ACPI / hotplug: Move container-specific code out of the core
  ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code
  ACPI / hotplug: Introduce common hotplug function acpi_device_hotplug()
  ACPI / hotplug: Do not fail bus and device checks for disabled hotplug
  ACPI / scan: Add acpi_device objects for all device nodes in the namespace
  ACPI / scan: Define non-empty device removal handler
  • Loading branch information
Rafael J. Wysocki committed Jan 12, 2014
2 parents 98feb7c + c713cd7 commit 25d412d
Show file tree
Hide file tree
Showing 28 changed files with 654 additions and 629 deletions.
9 changes: 1 addition & 8 deletions Documentation/acpi/namespace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,6 @@ Wysocki <rafael.j.wysocki@intel.com>.
named object's type in the second column). In that case the object's
directory in sysfs will contain the 'path' attribute whose value is
the full path to the node from the namespace root.
struct acpi_device objects are created for the ACPI namespace nodes
whose _STA control methods return PRESENT or FUNCTIONING. The power
resource nodes or nodes without _STA are assumed to be both PRESENT
and FUNCTIONING.
F:
The struct acpi_device object is created for a fixed hardware
feature (as indicated by the fixed feature flag's name in the second
Expand Down Expand Up @@ -340,7 +336,7 @@ Wysocki <rafael.j.wysocki@intel.com>.
| +-------------+-------+----------------+
| |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| +-| * PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
| +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| |
| | +------------+------------+-----------------------+
Expand Down Expand Up @@ -390,6 +386,3 @@ Wysocki <rafael.j.wysocki@intel.com>.
attribute (as described earlier in this document).
NOTE: N/A indicates the device object does not have the 'path' or the
'modalias' attribute.
NOTE: The PNP0C0D device listed above is highlighted (marked by "*")
to indicate it will be created only when its _STA methods return
PRESENT or FUNCTIONING.
15 changes: 7 additions & 8 deletions drivers/acpi/acpi_memhotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info)

static int acpi_bind_memblk(struct memory_block *mem, void *arg)
{
return acpi_bind_one(&mem->dev, (acpi_handle)arg);
return acpi_bind_one(&mem->dev, arg);
}

static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
acpi_handle handle)
struct acpi_device *adev)
{
return walk_memory_range(acpi_meminfo_start_pfn(info),
acpi_meminfo_end_pfn(info), (void *)handle,
acpi_meminfo_end_pfn(info), adev,
acpi_bind_memblk);
}

Expand All @@ -197,8 +197,7 @@ static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
return 0;
}

static void acpi_unbind_memory_blocks(struct acpi_memory_info *info,
acpi_handle handle)
static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
{
walk_memory_range(acpi_meminfo_start_pfn(info),
acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk);
Expand Down Expand Up @@ -242,9 +241,9 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
if (result && result != -EEXIST)
continue;

result = acpi_bind_memory_blocks(info, handle);
result = acpi_bind_memory_blocks(info, mem_device->device);
if (result) {
acpi_unbind_memory_blocks(info, handle);
acpi_unbind_memory_blocks(info);
return -ENODEV;
}

Expand Down Expand Up @@ -285,7 +284,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
if (nid == NUMA_NO_NODE)
nid = memory_add_physaddr_to_nid(info->start_addr);

acpi_unbind_memory_blocks(info, handle);
acpi_unbind_memory_blocks(info);
remove_memory(nid, info->start_addr, info->length);
list_del(&info->list);
kfree(info);
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/acpi_processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ static int acpi_processor_add(struct acpi_device *device,
goto err;
}

result = acpi_bind_one(dev, pr->handle);
result = acpi_bind_one(dev, device);
if (result)
goto err;

Expand Down
75 changes: 5 additions & 70 deletions drivers/acpi/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ struct acpi_device *acpi_root;
struct proc_dir_entry *acpi_root_dir;
EXPORT_SYMBOL(acpi_root_dir);

#define STRUCT_TO_INT(s) (*((int*)&s))


#ifdef CONFIG_X86
static int set_copy_dsdt(const struct dmi_system_id *id)
{
Expand Down Expand Up @@ -113,18 +110,16 @@ int acpi_bus_get_status(struct acpi_device *device)
if (ACPI_FAILURE(status))
return -ENODEV;

STRUCT_TO_INT(device->status) = (int) sta;
acpi_set_device_status(device, sta);

if (device->status.functional && !device->status.present) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
"functional but not present;\n",
device->pnp.bus_id,
(u32) STRUCT_TO_INT(device->status)));
device->pnp.bus_id, (u32)sta));
}

ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
device->pnp.bus_id,
(u32) STRUCT_TO_INT(device->status)));
device->pnp.bus_id, (u32)sta));
return 0;
}
EXPORT_SYMBOL(acpi_bus_get_status);
Expand Down Expand Up @@ -337,58 +332,6 @@ static void acpi_bus_osc_support(void)
Notification Handling
-------------------------------------------------------------------------- */

static void acpi_bus_check_device(acpi_handle handle)
{
struct acpi_device *device;
acpi_status status;
struct acpi_device_status old_status;

if (acpi_bus_get_device(handle, &device))
return;
if (!device)
return;

old_status = device->status;

/*
* Make sure this device's parent is present before we go about
* messing with the device.
*/
if (device->parent && !device->parent->status.present) {
device->status = device->parent->status;
return;
}

status = acpi_bus_get_status(device);
if (ACPI_FAILURE(status))
return;

if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
return;

/*
* Device Insertion/Removal
*/
if ((device->status.present) && !(old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
/* TBD: Handle device insertion */
} else if (!(device->status.present) && (old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
/* TBD: Handle device removal */
}
}

static void acpi_bus_check_scope(acpi_handle handle)
{
/* Status Change? */
acpi_bus_check_device(handle);

/*
* TBD: Enumerate child devices within this device's scope and
* run acpi_bus_check_device()'s on them.
*/
}

/**
* acpi_bus_notify
* ---------------
Expand All @@ -405,19 +348,11 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
switch (type) {

case ACPI_NOTIFY_BUS_CHECK:
acpi_bus_check_scope(handle);
/*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
/* TBD */
break;

case ACPI_NOTIFY_DEVICE_CHECK:
acpi_bus_check_device(handle);
/*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
/* TBD */
break;

case ACPI_NOTIFY_DEVICE_WAKE:
Expand Down
55 changes: 50 additions & 5 deletions drivers/acpi/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/acpi.h>

#include "internal.h"
#include <linux/container.h>

#include "internal.h"

Expand All @@ -44,19 +43,65 @@ static const struct acpi_device_id container_device_ids[] = {
{"", 0},
};

static int container_device_attach(struct acpi_device *device,
static int acpi_container_offline(struct container_dev *cdev)
{
struct acpi_device *adev = ACPI_COMPANION(&cdev->dev);
struct acpi_device *child;

/* Check all of the dependent devices' physical companions. */
list_for_each_entry(child, &adev->children, node)
if (!acpi_scan_is_offline(child, false))
return -EBUSY;

return 0;
}

static void acpi_container_release(struct device *dev)
{
kfree(to_container_dev(dev));
}

static int container_device_attach(struct acpi_device *adev,
const struct acpi_device_id *not_used)
{
/* This is necessary for container hotplug to work. */
struct container_dev *cdev;
struct device *dev;
int ret;

cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return -ENOMEM;

cdev->offline = acpi_container_offline;
dev = &cdev->dev;
dev->bus = &container_subsys;
dev_set_name(dev, "%s", dev_name(&adev->dev));
ACPI_COMPANION_SET(dev, adev);
dev->release = acpi_container_release;
ret = device_register(dev);
if (ret)
return ret;

adev->driver_data = dev;
return 1;
}

static void container_device_detach(struct acpi_device *adev)
{
struct device *dev = acpi_driver_data(adev);

adev->driver_data = NULL;
if (dev)
device_unregister(dev);
}

static struct acpi_scan_handler container_handler = {
.ids = container_device_ids,
.attach = container_device_attach,
.detach = container_device_detach,
.hotplug = {
.enabled = true,
.mode = AHM_CONTAINER,
.demand_offline = true,
},
};

Expand Down
22 changes: 18 additions & 4 deletions drivers/acpi/device_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device)
return -EINVAL;

device->power.state = ACPI_STATE_UNKNOWN;
if (!acpi_device_is_present(device))
return 0;

result = acpi_device_get_power(device, &state);
if (result)
Expand Down Expand Up @@ -302,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device)
return ret;
}

int acpi_bus_update_power(acpi_handle handle, int *state_p)
int acpi_device_update_power(struct acpi_device *device, int *state_p)
{
struct acpi_device *device;
int state;
int result;

result = acpi_bus_get_device(handle, &device);
if (result)
if (device->power.state == ACPI_STATE_UNKNOWN) {
result = acpi_bus_init_power(device);
if (!result && state_p)
*state_p = device->power.state;

return result;
}

result = acpi_device_get_power(device, &state);
if (result)
Expand Down Expand Up @@ -338,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)

return 0;
}

int acpi_bus_update_power(acpi_handle handle, int *state_p)
{
struct acpi_device *device;
int result;

result = acpi_bus_get_device(handle, &device);
return result ? result : acpi_device_update_power(device, state_p);
}
EXPORT_SYMBOL_GPL(acpi_bus_update_power);

bool acpi_bus_power_manageable(acpi_handle handle)
Expand Down
9 changes: 3 additions & 6 deletions drivers/acpi/dock.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,11 @@ static int dock_present(struct dock_station *ds)
*/
static void dock_create_acpi_device(acpi_handle handle)
{
struct acpi_device *device;
struct acpi_device *device = NULL;
int ret;

if (acpi_bus_get_device(handle, &device)) {
/*
* no device created for this object,
* so we should create one.
*/
acpi_bus_get_device(handle, &device);
if (!acpi_device_enumerated(device)) {
ret = acpi_bus_scan(handle);
if (ret)
pr_debug("error adding bus, %x\n", -ret);
Expand Down
Loading

0 comments on commit 25d412d

Please sign in to comment.