Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * container.c - ACPI Generic Container Driver 4 : : * 5 : : * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com) 6 : : * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com) 7 : : * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com) 8 : : * Copyright (C) 2004 FUJITSU LIMITED 9 : : * Copyright (C) 2004, 2013 Intel Corp. 10 : : * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> 11 : : */ 12 : : #include <linux/acpi.h> 13 : : #include <linux/container.h> 14 : : 15 : : #include "internal.h" 16 : : 17 : : #define _COMPONENT ACPI_CONTAINER_COMPONENT 18 : : ACPI_MODULE_NAME("container"); 19 : : 20 : : static const struct acpi_device_id container_device_ids[] = { 21 : : {"ACPI0004", 0}, 22 : : {"PNP0A05", 0}, 23 : : {"PNP0A06", 0}, 24 : : {"", 0}, 25 : : }; 26 : : 27 : : #ifdef CONFIG_ACPI_CONTAINER 28 : : 29 : 0 : static int acpi_container_offline(struct container_dev *cdev) 30 : : { 31 [ # # ]: 0 : struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); 32 : 0 : struct acpi_device *child; 33 : : 34 : : /* Check all of the dependent devices' physical companions. */ 35 [ # # ]: 0 : list_for_each_entry(child, &adev->children, node) 36 [ # # ]: 0 : if (!acpi_scan_is_offline(child, false)) 37 : : return -EBUSY; 38 : : 39 : : return 0; 40 : : } 41 : : 42 : 0 : static void acpi_container_release(struct device *dev) 43 : : { 44 : 0 : kfree(to_container_dev(dev)); 45 : 0 : } 46 : : 47 : 33 : static int container_device_attach(struct acpi_device *adev, 48 : : const struct acpi_device_id *not_used) 49 : : { 50 : 33 : struct container_dev *cdev; 51 : 33 : struct device *dev; 52 : 33 : int ret; 53 : : 54 [ + - ]: 33 : if (adev->flags.is_dock_station) 55 : : return 0; 56 : : 57 : 33 : cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 58 [ + - ]: 33 : if (!cdev) 59 : : return -ENOMEM; 60 : : 61 : 33 : cdev->offline = acpi_container_offline; 62 : 33 : dev = &cdev->dev; 63 : 33 : dev->bus = &container_subsys; 64 [ + - ]: 66 : dev_set_name(dev, "%s", dev_name(&adev->dev)); 65 [ + - ]: 66 : ACPI_COMPANION_SET(dev, adev); 66 : 33 : dev->release = acpi_container_release; 67 : 33 : ret = device_register(dev); 68 [ - + ]: 33 : if (ret) { 69 : 0 : put_device(dev); 70 : 0 : return ret; 71 : : } 72 : 33 : adev->driver_data = dev; 73 : 33 : return 1; 74 : : } 75 : : 76 : 0 : static void container_device_detach(struct acpi_device *adev) 77 : : { 78 [ # # ]: 0 : struct device *dev = acpi_driver_data(adev); 79 : : 80 : 0 : adev->driver_data = NULL; 81 [ # # ]: 0 : if (dev) 82 : 0 : device_unregister(dev); 83 : 0 : } 84 : : 85 : 33 : static void container_device_online(struct acpi_device *adev) 86 : : { 87 : 33 : struct device *dev = acpi_driver_data(adev); 88 : : 89 : 33 : kobject_uevent(&dev->kobj, KOBJ_ONLINE); 90 : 33 : } 91 : : 92 : : static struct acpi_scan_handler container_handler = { 93 : : .ids = container_device_ids, 94 : : .attach = container_device_attach, 95 : : .detach = container_device_detach, 96 : : .hotplug = { 97 : : .enabled = true, 98 : : .demand_offline = true, 99 : : .notify_online = container_device_online, 100 : : }, 101 : : }; 102 : : 103 : 11 : void __init acpi_container_init(void) 104 : : { 105 : 11 : acpi_scan_add_handler(&container_handler); 106 : 11 : } 107 : : 108 : : #else 109 : : 110 : : static struct acpi_scan_handler container_handler = { 111 : : .ids = container_device_ids, 112 : : }; 113 : : 114 : : void __init acpi_container_init(void) 115 : : { 116 : : acpi_scan_add_handler_with_hotplug(&container_handler, "container"); 117 : : } 118 : : 119 : : #endif /* CONFIG_ACPI_CONTAINER */