Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * container.c  - ACPI Generic Container Driver
0004  *
0005  * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
0006  * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
0007  * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
0008  * Copyright (C) 2004 FUJITSU LIMITED
0009  * Copyright (C) 2004, 2013 Intel Corp.
0010  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
0011  */
0012 #include <linux/acpi.h>
0013 #include <linux/container.h>
0014 
0015 #include "internal.h"
0016 
0017 static const struct acpi_device_id container_device_ids[] = {
0018     {"ACPI0004", 0},
0019     {"PNP0A05", 0},
0020     {"PNP0A06", 0},
0021     {"", 0},
0022 };
0023 
0024 #ifdef CONFIG_ACPI_CONTAINER
0025 
0026 static int check_offline(struct acpi_device *adev, void *not_used)
0027 {
0028     if (acpi_scan_is_offline(adev, false))
0029         return 0;
0030 
0031     return -EBUSY;
0032 }
0033 
0034 static int acpi_container_offline(struct container_dev *cdev)
0035 {
0036     /* Check all of the dependent devices' physical companions. */
0037     return acpi_dev_for_each_child(ACPI_COMPANION(&cdev->dev), check_offline, NULL);
0038 }
0039 
0040 static void acpi_container_release(struct device *dev)
0041 {
0042     kfree(to_container_dev(dev));
0043 }
0044 
0045 static int container_device_attach(struct acpi_device *adev,
0046                    const struct acpi_device_id *not_used)
0047 {
0048     struct container_dev *cdev;
0049     struct device *dev;
0050     int ret;
0051 
0052     if (adev->flags.is_dock_station)
0053         return 0;
0054 
0055     cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
0056     if (!cdev)
0057         return -ENOMEM;
0058 
0059     cdev->offline = acpi_container_offline;
0060     dev = &cdev->dev;
0061     dev->bus = &container_subsys;
0062     dev_set_name(dev, "%s", dev_name(&adev->dev));
0063     ACPI_COMPANION_SET(dev, adev);
0064     dev->release = acpi_container_release;
0065     ret = device_register(dev);
0066     if (ret) {
0067         put_device(dev);
0068         return ret;
0069     }
0070     adev->driver_data = dev;
0071     return 1;
0072 }
0073 
0074 static void container_device_detach(struct acpi_device *adev)
0075 {
0076     struct device *dev = acpi_driver_data(adev);
0077 
0078     adev->driver_data = NULL;
0079     if (dev)
0080         device_unregister(dev);
0081 }
0082 
0083 static void container_device_online(struct acpi_device *adev)
0084 {
0085     struct device *dev = acpi_driver_data(adev);
0086 
0087     kobject_uevent(&dev->kobj, KOBJ_ONLINE);
0088 }
0089 
0090 static struct acpi_scan_handler container_handler = {
0091     .ids = container_device_ids,
0092     .attach = container_device_attach,
0093     .detach = container_device_detach,
0094     .hotplug = {
0095         .enabled = true,
0096         .demand_offline = true,
0097         .notify_online = container_device_online,
0098     },
0099 };
0100 
0101 void __init acpi_container_init(void)
0102 {
0103     acpi_scan_add_handler(&container_handler);
0104 }
0105 
0106 #else
0107 
0108 static struct acpi_scan_handler container_handler = {
0109     .ids = container_device_ids,
0110 };
0111 
0112 void __init acpi_container_init(void)
0113 {
0114     acpi_scan_add_handler_with_hotplug(&container_handler, "container");
0115 }
0116 
0117 #endif /* CONFIG_ACPI_CONTAINER */