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

Commit 929c6dd4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-hotplug'

* acpi-hotplug:
  ACPI / memhotplug: Remove info->failed bit
  ACPI / memhotplug: set info->enabled for memory present at boot time
  ACPI: Verify device status after eject
  acpi: remove reference to ACPI_HOTPLUG_IO
  ACPI: Update _OST handling for notify
  ACPI: Update PNPID match handling for notify
  ACPI: Update PNPID set/free interfaces
  ACPI: Remove acpi_device dependency in acpi_device_set_id()
  ACPI / hotplug: Make acpi_hotplug_profile_ktype static
  ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler
  ACPI / container: Use hotplug profile user space interface
  ACPI / hotplug: Introduce user space interface for hotplug profiles
  ACPI / scan: Introduce acpi_scan_handler_matching()
  ACPI / container: Use common hotplug code
  ACPI / scan: Introduce common code for ACPI-based device hotplug
  ACPI / scan: Introduce acpi_scan_match_handler()
parents 60d509fa fd4655c2
Loading
Loading
Loading
Loading
+26 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,32 @@ Description:
		yoffset: The number of pixels between the top of the screen
		yoffset: The number of pixels between the top of the screen
			 and the top edge of the image.
			 and the top edge of the image.


What:		/sys/firmware/acpi/hotplug/
Date:		February 2013
Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Description:
		There are separate hotplug profiles for different classes of
		devices supported by ACPI, such as containers, memory modules,
		processors, PCI root bridges etc.  A hotplug profile for a given
		class of devices is a collection of settings defining the way
		that class of devices will be handled by the ACPI core hotplug
		code.  Those profiles are represented in sysfs as subdirectories
		of /sys/firmware/acpi/hotplug/.

		The following setting is available to user space for each
		hotplug profile:

		enabled: If set, the ACPI core will handle notifications of
			hotplug events associated with the given class of
			devices and will allow those devices to be ejected with
			the help of the _EJ0 control method.  Unsetting it
			effectively disables hotplug for the correspoinding
			class of devices.

		The value of the above attribute is an integer number: 1 (set)
		or 0 (unset).  Attempts to write any other values to it will
		cause -EINVAL to be returned.

What:		/sys/firmware/acpi/interrupts/
What:		/sys/firmware/acpi/interrupts/
Date:		February 2008
Date:		February 2008
Contact:	Len Brown <lenb@kernel.org>
Contact:	Len Brown <lenb@kernel.org>
+2 −3
Original line number Original line Diff line number Diff line
@@ -334,7 +334,7 @@ config X86_PM_TIMER


config ACPI_CONTAINER
config ACPI_CONTAINER
	bool "Container and Module Devices"
	bool "Container and Module Devices"
	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU)
	help
	help
	  This driver supports ACPI Container and Module devices (IDs
	  This driver supports ACPI Container and Module devices (IDs
	  ACPI0004, PNP0A05, and PNP0A06).
	  ACPI0004, PNP0A05, and PNP0A06).
@@ -345,9 +345,8 @@ config ACPI_CONTAINER
	  the module will be called container.
	  the module will be called container.


config ACPI_HOTPLUG_MEMORY
config ACPI_HOTPLUG_MEMORY
	tristate "Memory Hotplug"
	bool "Memory Hotplug"
	depends on MEMORY_HOTPLUG
	depends on MEMORY_HOTPLUG
	default n
	help
	help
	  This driver supports ACPI memory hotplug.  The driver
	  This driver supports ACPI memory hotplug.  The driver
	  fields notifications on ACPI memory devices (PNP0C80),
	  fields notifications on ACPI memory devices (PNP0C80),
+42 −286
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
 * Copyright (C) 2004, 2013 Intel Corporation
 * Author: Naveen B S <naveen.b.s@intel.com>
 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 *
 *
 * All rights reserved.
 * All rights reserved.
 *
 *
@@ -25,14 +27,10 @@
 * ranges.
 * ranges.
 */
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/memory_hotplug.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <acpi/acpi_drivers.h>
#include <linux/memory_hotplug.h>

#include "internal.h"


#define ACPI_MEMORY_DEVICE_CLASS		"memory"
#define ACPI_MEMORY_DEVICE_CLASS		"memory"
#define ACPI_MEMORY_DEVICE_HID			"PNP0C80"
#define ACPI_MEMORY_DEVICE_HID			"PNP0C80"
@@ -44,31 +42,27 @@
#define 	PREFIX		"ACPI:memory_hp:"
#define 	PREFIX		"ACPI:memory_hp:"


ACPI_MODULE_NAME("acpi_memhotplug");
ACPI_MODULE_NAME("acpi_memhotplug");
MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
MODULE_DESCRIPTION("Hotplug Mem Driver");
MODULE_LICENSE("GPL");


/* Memory Device States */
/* Memory Device States */
#define MEMORY_INVALID_STATE	0
#define MEMORY_INVALID_STATE	0
#define MEMORY_POWER_ON_STATE	1
#define MEMORY_POWER_ON_STATE	1
#define MEMORY_POWER_OFF_STATE	2
#define MEMORY_POWER_OFF_STATE	2


static int acpi_memory_device_add(struct acpi_device *device);
static int acpi_memory_device_add(struct acpi_device *device,
static int acpi_memory_device_remove(struct acpi_device *device);
				  const struct acpi_device_id *not_used);
static void acpi_memory_device_remove(struct acpi_device *device);


static const struct acpi_device_id memory_device_ids[] = {
static const struct acpi_device_id memory_device_ids[] = {
	{ACPI_MEMORY_DEVICE_HID, 0},
	{ACPI_MEMORY_DEVICE_HID, 0},
	{"", 0},
	{"", 0},
};
};
MODULE_DEVICE_TABLE(acpi, memory_device_ids);


static struct acpi_driver acpi_memory_device_driver = {
static struct acpi_scan_handler memory_device_handler = {
	.name = "acpi_memhotplug",
	.class = ACPI_MEMORY_DEVICE_CLASS,
	.ids = memory_device_ids,
	.ids = memory_device_ids,
	.ops = {
	.attach = acpi_memory_device_add,
		.add = acpi_memory_device_add,
	.detach = acpi_memory_device_remove,
		.remove = acpi_memory_device_remove,
	.hotplug = {
		.enabled = true,
	},
	},
};
};


@@ -79,7 +73,6 @@ struct acpi_memory_info {
	unsigned short caching;	/* memory cache attribute */
	unsigned short caching;	/* memory cache attribute */
	unsigned short write_protect;	/* memory read/write attribute */
	unsigned short write_protect;	/* memory read/write attribute */
	unsigned int enabled:1;
	unsigned int enabled:1;
	unsigned int failed:1;
};
};


struct acpi_memory_device {
struct acpi_memory_device {
@@ -153,48 +146,6 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
	return 0;
	return 0;
}
}


static int acpi_memory_get_device(acpi_handle handle,
				  struct acpi_memory_device **mem_device)
{
	struct acpi_device *device = NULL;
	int result = 0;

	acpi_scan_lock_acquire();

	acpi_bus_get_device(handle, &device);
	if (device)
		goto end;

	/*
	 * Now add the notified device.  This creates the acpi_device
	 * and invokes .add function
	 */
	result = acpi_bus_scan(handle);
	if (result) {
		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");
		result = -EINVAL;
		goto out;
	}

 end:
	*mem_device = acpi_driver_data(device);
	if (!(*mem_device)) {
		dev_err(&device->dev, "driver data not found\n");
		result = -ENODEV;
		goto out;
	}

 out:
	acpi_scan_lock_release();
	return result;
}

static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
{
	unsigned long long current_status;
	unsigned long long current_status;
@@ -249,13 +200,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
		 * returns -EEXIST. If add_memory() returns the other error, it
		 * returns -EEXIST. If add_memory() returns the other error, it
		 * means that this memory block is not used by the kernel.
		 * means that this memory block is not used by the kernel.
		 */
		 */
		if (result && result != -EEXIST) {
		if (result && result != -EEXIST)
			info->failed = 1;
			continue;
			continue;
		}


		if (!result)
		info->enabled = 1;
		info->enabled = 1;

		/*
		/*
		 * Add num_enable even if add_memory() returns -EEXIST, so the
		 * Add num_enable even if add_memory() returns -EEXIST, so the
		 * device is bound to this driver.
		 * device is bound to this driver.
@@ -286,16 +235,8 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
	nid = acpi_get_node(mem_device->device->handle);
	nid = acpi_get_node(mem_device->device->handle);


	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
		if (info->failed)
			/* The kernel does not use this memory block */
			continue;

		if (!info->enabled)
		if (!info->enabled)
			/*
			continue;
			 * The kernel uses this memory block, but it may be not
			 * managed by us.
			 */
			return -EBUSY;


		if (nid < 0)
		if (nid < 0)
			nid = memory_add_physaddr_to_nid(info->start_addr);
			nid = memory_add_physaddr_to_nid(info->start_addr);
@@ -310,95 +251,21 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
	return result;
	return result;
}
}


static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
{
	struct acpi_memory_device *mem_device;
	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:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "\nReceived BUS CHECK notification for device\n"));
		/* Fall Through */
	case ACPI_NOTIFY_DEVICE_CHECK:
		if (event == ACPI_NOTIFY_DEVICE_CHECK)
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "\nReceived DEVICE CHECK notification for device\n"));
		if (acpi_memory_get_device(handle, &mem_device)) {
			acpi_handle_err(handle, "Cannot find driver data\n");
			break;
		}

		ost_code = ACPI_OST_SC_SUCCESS;
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		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");
			goto unlock;
		}
		mem_device = acpi_driver_data(device);
		if (!mem_device) {
			acpi_handle_err(handle, "Driver Data is NULL\n");
			goto unlock;
		}

		ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
		if (!ej_event) {
			pr_err(PREFIX "No memory, dropping EJECT\n");
			goto unlock;
		}

		get_device(&device->dev);
		ej_event->device = device;
		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
		/* 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);
		}

 unlock:
		acpi_scan_lock_release();
		if (ACPI_SUCCESS(status))
			return;
	default:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));

		/* non-hotplug event; possibly handled by other handler */
		return;
	}

	/* Inform firmware that the hotplug operation has completed */
	(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
}

static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
{
{
	if (!mem_device)
	if (!mem_device)
		return;
		return;


	acpi_memory_free_device_resources(mem_device);
	acpi_memory_free_device_resources(mem_device);
	mem_device->device->driver_data = NULL;
	kfree(mem_device);
	kfree(mem_device);
}
}


static int acpi_memory_device_add(struct acpi_device *device)
static int acpi_memory_device_add(struct acpi_device *device,
				  const struct acpi_device_id *not_used)
{
{
	struct acpi_memory_device *mem_device;
	int result;
	int result;
	struct acpi_memory_device *mem_device = NULL;



	if (!device)
	if (!device)
		return -EINVAL;
		return -EINVAL;
@@ -423,147 +290,36 @@ static int acpi_memory_device_add(struct acpi_device *device)
	/* Set the device state */
	/* Set the device state */
	mem_device->state = MEMORY_POWER_ON_STATE;
	mem_device->state = MEMORY_POWER_ON_STATE;


	pr_debug("%s\n", acpi_device_name(device));
	result = acpi_memory_check_device(mem_device);
	if (result) {
		acpi_memory_device_free(mem_device);
		return 0;
	}


	if (!acpi_memory_check_device(mem_device)) {
		/* call add_memory func */
	result = acpi_memory_enable_device(mem_device);
	result = acpi_memory_enable_device(mem_device);
	if (result) {
	if (result) {
			dev_err(&device->dev,
		dev_err(&device->dev, "acpi_memory_enable_device() error\n");
				"Error in acpi_memory_enable_device\n");
		acpi_memory_device_free(mem_device);
		acpi_memory_device_free(mem_device);
		return -ENODEV;
	}
	}
	}

	return result;
	dev_dbg(&device->dev, "Memory device configured by ACPI\n");
	return 1;
}
}


static int acpi_memory_device_remove(struct acpi_device *device)
static void acpi_memory_device_remove(struct acpi_device *device)
{
{
	struct acpi_memory_device *mem_device = NULL;
	struct acpi_memory_device *mem_device;
	int result;


	if (!device || !acpi_driver_data(device))
	if (!device || !acpi_driver_data(device))
		return -EINVAL;
		return;


	mem_device = acpi_driver_data(device);
	mem_device = acpi_driver_data(device);

	acpi_memory_remove_memory(mem_device);
	result = acpi_memory_remove_memory(mem_device);
	if (result)
		return result;

	acpi_memory_device_free(mem_device);
	acpi_memory_device_free(mem_device);

	return 0;
}
}


/*
void __init acpi_memory_hotplug_init(void)
 * Helper function to check for memory device
 */
static acpi_status is_memory_device(acpi_handle handle)
{
{
	char *hardware_id;
	acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
	acpi_status status;
	struct acpi_device_info *info;

	status = acpi_get_object_info(handle, &info);
	if (ACPI_FAILURE(status))
		return status;

	if (!(info->valid & ACPI_VALID_HID)) {
		kfree(info);
		return AE_ERROR;
}
}

	hardware_id = info->hardware_id.string;
	if ((hardware_id == NULL) ||
	    (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
		status = AE_ERROR;

	kfree(info);
	return status;
}

static acpi_status
acpi_memory_register_notify_handler(acpi_handle handle,
				    u32 level, void *ctxt, void **retv)
{
	acpi_status status;


	status = is_memory_device(handle);
	if (ACPI_FAILURE(status))
		return AE_OK;	/* continue */

	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
					     acpi_memory_device_notify, NULL);
	/* continue */
	return AE_OK;
}

static acpi_status
acpi_memory_deregister_notify_handler(acpi_handle handle,
				      u32 level, void *ctxt, void **retv)
{
	acpi_status status;


	status = is_memory_device(handle);
	if (ACPI_FAILURE(status))
		return AE_OK;	/* continue */

	status = acpi_remove_notify_handler(handle,
					    ACPI_SYSTEM_NOTIFY,
					    acpi_memory_device_notify);

	return AE_OK;	/* continue */
}

static int __init acpi_memory_device_init(void)
{
	int result;
	acpi_status status;


	result = acpi_bus_register_driver(&acpi_memory_device_driver);

	if (result < 0)
		return -ENODEV;

	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
				     ACPI_UINT32_MAX,
				     acpi_memory_register_notify_handler, NULL,
				     NULL, NULL);

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
		acpi_bus_unregister_driver(&acpi_memory_device_driver);
		return -ENODEV;
	}

	return 0;
}

static void __exit acpi_memory_device_exit(void)
{
	acpi_status status;


	/*
	 * Adding this to un-install notification handlers for all the device
	 * handles.
	 */
	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
				     ACPI_UINT32_MAX,
				     acpi_memory_deregister_notify_handler, NULL,
				     NULL, NULL);

	if (ACPI_FAILURE(status))
		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));

	acpi_bus_unregister_driver(&acpi_memory_device_driver);

	return;
}

module_init(acpi_memory_device_init);
module_exit(acpi_memory_device_exit);
+12 −138
Original line number Original line Diff line number Diff line
/*
/*
 * acpi_container.c  - ACPI Generic Container Driver
 * container.c  - ACPI Generic Container Driver
 * ($Revision: )
 *
 *
 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
 * Copyright (C) 2004 Intel Corp.
 * Copyright (C) 2004 FUJITSU LIMITED
 * Copyright (C) 2004 FUJITSU LIMITED
 * Copyright (C) 2004, 2013 Intel Corp.
 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 *
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *
@@ -26,14 +26,9 @@
 *
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>

#include <acpi/acpi_drivers.h>
#include "internal.h"


#define PREFIX "ACPI: "
#define PREFIX "ACPI: "


@@ -50,141 +45,20 @@ static const struct acpi_device_id container_device_ids[] = {
static int container_device_attach(struct acpi_device *device,
static int container_device_attach(struct acpi_device *device,
				   const struct acpi_device_id *not_used)
				   const struct acpi_device_id *not_used)
{
{
	/*
	/* This is necessary for container hotplug to work. */
	 * FIXME: This is necessary, so that acpi_eject_store() doesn't return
	 * -ENODEV for containers.
	 */
	return 1;
	return 1;
}
}


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


static int is_device_present(acpi_handle handle)
{
	acpi_handle temp;
	acpi_status status;
	unsigned long long sta;


	status = acpi_get_handle(handle, "_STA", &temp);
	if (ACPI_FAILURE(status))
		return 1;	/* _STA not found, assume device present */

	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
	if (ACPI_FAILURE(status))
		return 0;	/* Firmware error */

	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}

static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
	struct acpi_device *device = NULL;
	int result;
	int present;
	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 */
	case ACPI_NOTIFY_DEVICE_CHECK:
		pr_debug("Container driver received %s event\n",
		       (type == ACPI_NOTIFY_BUS_CHECK) ?
		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");

		present = is_device_present(handle);
		status = acpi_bus_get_device(handle, &device);
		if (!present) {
			if (ACPI_SUCCESS(status)) {
				/* device exist and this is a remove request */
				device->flags.eject_pending = 1;
				kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
				goto out;
			}
			break;
		}

		if (!ACPI_FAILURE(status) || device)
			break;

		result = acpi_bus_scan(handle);
		if (result) {
			acpi_handle_warn(handle, "Failed to add container\n");
			break;
		}
		result = acpi_bus_get_device(handle, &device);
		if (result) {
			acpi_handle_warn(handle, "Missing device object\n");
			break;
		}

		kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
		ost_code = ACPI_OST_SC_SUCCESS;
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		if (!acpi_bus_get_device(handle, &device) && device) {
			device->flags.eject_pending = 1;
			kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
			goto out;
		}
		break;

	default:
		/* non-hotplug event; possibly handled by other handler */
		goto out;
	}

	/* Inform firmware that the hotplug operation has completed */
	(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);

 out:
	acpi_scan_lock_release();
}

static bool is_container(acpi_handle handle)
{
	struct acpi_device_info *info;
	bool ret = false;

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

void __init acpi_container_init(void)
void __init acpi_container_init(void)
{
{
	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
	acpi_scan_add_handler_with_hotplug(&container_handler, "container");
			    acpi_container_register_notify_handler, NULL,
			    NULL, NULL);

	acpi_scan_add_handler(&container_device_handler);
}
}
+12 −1
Original line number Original line Diff line number Diff line
@@ -41,6 +41,17 @@ void acpi_container_init(void);
#else
#else
static inline void acpi_container_init(void) {}
static inline void acpi_container_init(void) {}
#endif
#endif
#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
void acpi_memory_hotplug_init(void);
#else
static inline void acpi_memory_hotplug_init(void) {}
#endif

void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
				    const char *name);
int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
				       const char *hotplug_profile_name);
void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);


#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
extern struct dentry *acpi_debugfs_dir;
extern struct dentry *acpi_debugfs_dir;
@@ -60,7 +71,7 @@ int acpi_device_add(struct acpi_device *device,
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
			     int type, unsigned long long sta);
			     int type, unsigned long long sta);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_ids(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);


/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
                                  Power Resource
                                  Power Resource
Loading