1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
368a67f6cSRafael J. Wysocki * container.c - ACPI Generic Container Driver
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
61da177e4SLinus Torvalds * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
71da177e4SLinus Torvalds * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
81da177e4SLinus Torvalds * Copyright (C) 2004 FUJITSU LIMITED
968a67f6cSRafael J. Wysocki * Copyright (C) 2004, 2013 Intel Corp.
1068a67f6cSRafael J. Wysocki * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds #include <linux/acpi.h>
13caa73ea1SRafael J. Wysocki #include <linux/container.h>
141da177e4SLinus Torvalds
152f9b06fcSAndy Shevchenko #include "internal.h"
162f9b06fcSAndy Shevchenko
171ba90e3aSThomas Renninger static const struct acpi_device_id container_device_ids[] = {
181ba90e3aSThomas Renninger {"ACPI0004", 0},
191ba90e3aSThomas Renninger {"PNP0A05", 0},
201ba90e3aSThomas Renninger {"PNP0A06", 0},
211ba90e3aSThomas Renninger {"", 0},
221ba90e3aSThomas Renninger };
231ba90e3aSThomas Renninger
24a1ec6572SRafael J. Wysocki #ifdef CONFIG_ACPI_CONTAINER
25a1ec6572SRafael J. Wysocki
check_offline(struct acpi_device * adev,void * not_used)26*abda0af4SRafael J. Wysocki static int check_offline(struct acpi_device *adev, void *not_used)
27*abda0af4SRafael J. Wysocki {
28*abda0af4SRafael J. Wysocki if (acpi_scan_is_offline(adev, false))
29*abda0af4SRafael J. Wysocki return 0;
30*abda0af4SRafael J. Wysocki
31*abda0af4SRafael J. Wysocki return -EBUSY;
32*abda0af4SRafael J. Wysocki }
33*abda0af4SRafael J. Wysocki
acpi_container_offline(struct container_dev * cdev)34caa73ea1SRafael J. Wysocki static int acpi_container_offline(struct container_dev *cdev)
35caa73ea1SRafael J. Wysocki {
36caa73ea1SRafael J. Wysocki /* Check all of the dependent devices' physical companions. */
37*abda0af4SRafael J. Wysocki return acpi_dev_for_each_child(ACPI_COMPANION(&cdev->dev), check_offline, NULL);
38caa73ea1SRafael J. Wysocki }
39caa73ea1SRafael J. Wysocki
acpi_container_release(struct device * dev)40caa73ea1SRafael J. Wysocki static void acpi_container_release(struct device *dev)
41caa73ea1SRafael J. Wysocki {
42caa73ea1SRafael J. Wysocki kfree(to_container_dev(dev));
43caa73ea1SRafael J. Wysocki }
44caa73ea1SRafael J. Wysocki
container_device_attach(struct acpi_device * adev,const struct acpi_device_id * not_used)4546394fd0SRafael J. Wysocki static int container_device_attach(struct acpi_device *adev,
46737f1a9fSRafael J. Wysocki const struct acpi_device_id *not_used)
47737f1a9fSRafael J. Wysocki {
48caa73ea1SRafael J. Wysocki struct container_dev *cdev;
49caa73ea1SRafael J. Wysocki struct device *dev;
50caa73ea1SRafael J. Wysocki int ret;
51caa73ea1SRafael J. Wysocki
521e2380cdSRafael J. Wysocki if (adev->flags.is_dock_station)
531e2380cdSRafael J. Wysocki return 0;
541e2380cdSRafael J. Wysocki
55caa73ea1SRafael J. Wysocki cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
56caa73ea1SRafael J. Wysocki if (!cdev)
57caa73ea1SRafael J. Wysocki return -ENOMEM;
58caa73ea1SRafael J. Wysocki
59caa73ea1SRafael J. Wysocki cdev->offline = acpi_container_offline;
60caa73ea1SRafael J. Wysocki dev = &cdev->dev;
61caa73ea1SRafael J. Wysocki dev->bus = &container_subsys;
62caa73ea1SRafael J. Wysocki dev_set_name(dev, "%s", dev_name(&adev->dev));
63caa73ea1SRafael J. Wysocki ACPI_COMPANION_SET(dev, adev);
64caa73ea1SRafael J. Wysocki dev->release = acpi_container_release;
65caa73ea1SRafael J. Wysocki ret = device_register(dev);
660f6aa09eSRafael J. Wysocki if (ret) {
670f6aa09eSRafael J. Wysocki put_device(dev);
68caa73ea1SRafael J. Wysocki return ret;
690f6aa09eSRafael J. Wysocki }
70caa73ea1SRafael J. Wysocki adev->driver_data = dev;
71737f1a9fSRafael J. Wysocki return 1;
72737f1a9fSRafael J. Wysocki }
73737f1a9fSRafael J. Wysocki
container_device_detach(struct acpi_device * adev)7446394fd0SRafael J. Wysocki static void container_device_detach(struct acpi_device *adev)
7546394fd0SRafael J. Wysocki {
76caa73ea1SRafael J. Wysocki struct device *dev = acpi_driver_data(adev);
77caa73ea1SRafael J. Wysocki
78caa73ea1SRafael J. Wysocki adev->driver_data = NULL;
79caa73ea1SRafael J. Wysocki if (dev)
80caa73ea1SRafael J. Wysocki device_unregister(dev);
8146394fd0SRafael J. Wysocki }
8246394fd0SRafael J. Wysocki
container_device_online(struct acpi_device * adev)838ab17fc9SRafael J. Wysocki static void container_device_online(struct acpi_device *adev)
848ab17fc9SRafael J. Wysocki {
858ab17fc9SRafael J. Wysocki struct device *dev = acpi_driver_data(adev);
868ab17fc9SRafael J. Wysocki
878ab17fc9SRafael J. Wysocki kobject_uevent(&dev->kobj, KOBJ_ONLINE);
888ab17fc9SRafael J. Wysocki }
898ab17fc9SRafael J. Wysocki
9079917f34SRafael J. Wysocki static struct acpi_scan_handler container_handler = {
911ba90e3aSThomas Renninger .ids = container_device_ids,
92737f1a9fSRafael J. Wysocki .attach = container_device_attach,
9346394fd0SRafael J. Wysocki .detach = container_device_detach,
9468a67f6cSRafael J. Wysocki .hotplug = {
9568a67f6cSRafael J. Wysocki .enabled = true,
96caa73ea1SRafael J. Wysocki .demand_offline = true,
978ab17fc9SRafael J. Wysocki .notify_online = container_device_online,
9868a67f6cSRafael J. Wysocki },
991da177e4SLinus Torvalds };
1001da177e4SLinus Torvalds
acpi_container_init(void)101737f1a9fSRafael J. Wysocki void __init acpi_container_init(void)
1021da177e4SLinus Torvalds {
103a1ec6572SRafael J. Wysocki acpi_scan_add_handler(&container_handler);
104a1ec6572SRafael J. Wysocki }
105a1ec6572SRafael J. Wysocki
106a1ec6572SRafael J. Wysocki #else
107a1ec6572SRafael J. Wysocki
108a1ec6572SRafael J. Wysocki static struct acpi_scan_handler container_handler = {
109a1ec6572SRafael J. Wysocki .ids = container_device_ids,
110a1ec6572SRafael J. Wysocki };
111a1ec6572SRafael J. Wysocki
acpi_container_init(void)112a1ec6572SRafael J. Wysocki void __init acpi_container_init(void)
113a1ec6572SRafael J. Wysocki {
11479917f34SRafael J. Wysocki acpi_scan_add_handler_with_hotplug(&container_handler, "container");
1151da177e4SLinus Torvalds }
116a1ec6572SRafael J. Wysocki
117a1ec6572SRafael J. Wysocki #endif /* CONFIG_ACPI_CONTAINER */
118