mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 08:31:55 +00:00
8ab17fc92e
Commit46394fd01
(ACPI / hotplug: Move container-specific code out of the core) removed the generation of "online" uevents for containers, because "add" uevents are now generated for them automatically when container system devices are registered. However, there are user space tools that need to be notified when the container and all of its children have been enumerated, which doesn't happen any more. For this reason, add a mechanism allowing "online" uevents to be generated for ACPI containers after enumerating the container along with all of its children. Fixes:46394fd01
(ACPI / hotplug: Move container-specific code out of the core) Reported-and-tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: 3.14+ <stable@vger.kernel.org> # 3.14+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
137 lines
3.5 KiB
C
137 lines
3.5 KiB
C
/*
|
|
* container.c - ACPI Generic Container Driver
|
|
*
|
|
* Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
|
|
* Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
|
|
* Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
|
|
* Copyright (C) 2004 FUJITSU LIMITED
|
|
* Copyright (C) 2004, 2013 Intel Corp.
|
|
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
|
*
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
*/
|
|
#include <linux/acpi.h>
|
|
#include <linux/container.h>
|
|
|
|
#include "internal.h"
|
|
|
|
#define _COMPONENT ACPI_CONTAINER_COMPONENT
|
|
ACPI_MODULE_NAME("container");
|
|
|
|
static const struct acpi_device_id container_device_ids[] = {
|
|
{"ACPI0004", 0},
|
|
{"PNP0A05", 0},
|
|
{"PNP0A06", 0},
|
|
{"", 0},
|
|
};
|
|
|
|
#ifdef CONFIG_ACPI_CONTAINER
|
|
|
|
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)
|
|
{
|
|
struct container_dev *cdev;
|
|
struct device *dev;
|
|
int ret;
|
|
|
|
if (adev->flags.is_dock_station)
|
|
return 0;
|
|
|
|
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) {
|
|
put_device(dev);
|
|
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 void container_device_online(struct acpi_device *adev)
|
|
{
|
|
struct device *dev = acpi_driver_data(adev);
|
|
|
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
|
}
|
|
|
|
static struct acpi_scan_handler container_handler = {
|
|
.ids = container_device_ids,
|
|
.attach = container_device_attach,
|
|
.detach = container_device_detach,
|
|
.hotplug = {
|
|
.enabled = true,
|
|
.demand_offline = true,
|
|
.notify_online = container_device_online,
|
|
},
|
|
};
|
|
|
|
void __init acpi_container_init(void)
|
|
{
|
|
acpi_scan_add_handler(&container_handler);
|
|
}
|
|
|
|
#else
|
|
|
|
static struct acpi_scan_handler container_handler = {
|
|
.ids = container_device_ids,
|
|
};
|
|
|
|
void __init acpi_container_init(void)
|
|
{
|
|
acpi_scan_add_handler_with_hotplug(&container_handler, "container");
|
|
}
|
|
|
|
#endif /* CONFIG_ACPI_CONTAINER */
|