Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25d412d9 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-hotplug'

* 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
parents 98feb7cc c713cd7f
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -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
@@ -340,7 +336,7 @@ Wysocki <rafael.j.wysocki@intel.com>.
     | +-------------+-------+----------------+
     |   |
     |   | +- - - - - - - +- - - - - - +- - - - - - - -+
     |   +-| * PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
     |   +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
     |   | +- - - - - - - +- - - - - - +- - - - - - - -+
     |   |
     |   | +------------+------------+-----------------------+
@@ -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.
+7 −8
Original line number Diff line number Diff line
@@ -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);
}

@@ -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);
@@ -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;
		}

@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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;

+5 −70
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);
@@ -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
 * ---------------
@@ -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:
+50 −5
Original line number Diff line number Diff line
@@ -27,8 +27,7 @@
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
#include <linux/acpi.h>

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

#include "internal.h"

@@ -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,
	},
};

Loading