11da177e4SLinus Torvalds /* 268a67f6cSRafael J. Wysocki * container.c - ACPI Generic Container Driver 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com) 51da177e4SLinus Torvalds * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com) 61da177e4SLinus Torvalds * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com) 71da177e4SLinus Torvalds * Copyright (C) 2004 FUJITSU LIMITED 868a67f6cSRafael J. Wysocki * Copyright (C) 2004, 2013 Intel Corp. 968a67f6cSRafael J. Wysocki * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 141da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 151da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 161da177e4SLinus Torvalds * your option) any later version. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 191da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 201da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 211da177e4SLinus Torvalds * General Public License for more details. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 241da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 251da177e4SLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 281da177e4SLinus Torvalds */ 291da177e4SLinus Torvalds #include <linux/acpi.h> 30caa73ea1SRafael J. Wysocki #include <linux/container.h> 311da177e4SLinus Torvalds 322f9b06fcSAndy Shevchenko #include "internal.h" 332f9b06fcSAndy Shevchenko 341da177e4SLinus Torvalds #define _COMPONENT ACPI_CONTAINER_COMPONENT 35f52fd66dSLen Brown ACPI_MODULE_NAME("container"); 361da177e4SLinus Torvalds 371ba90e3aSThomas Renninger static const struct acpi_device_id container_device_ids[] = { 381ba90e3aSThomas Renninger {"ACPI0004", 0}, 391ba90e3aSThomas Renninger {"PNP0A05", 0}, 401ba90e3aSThomas Renninger {"PNP0A06", 0}, 411ba90e3aSThomas Renninger {"", 0}, 421ba90e3aSThomas Renninger }; 431ba90e3aSThomas Renninger 44*a1ec6572SRafael J. Wysocki #ifdef CONFIG_ACPI_CONTAINER 45*a1ec6572SRafael J. Wysocki 46caa73ea1SRafael J. Wysocki static int acpi_container_offline(struct container_dev *cdev) 47caa73ea1SRafael J. Wysocki { 48caa73ea1SRafael J. Wysocki struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); 49caa73ea1SRafael J. Wysocki struct acpi_device *child; 50caa73ea1SRafael J. Wysocki 51caa73ea1SRafael J. Wysocki /* Check all of the dependent devices' physical companions. */ 52caa73ea1SRafael J. Wysocki list_for_each_entry(child, &adev->children, node) 53caa73ea1SRafael J. Wysocki if (!acpi_scan_is_offline(child, false)) 54caa73ea1SRafael J. Wysocki return -EBUSY; 55caa73ea1SRafael J. Wysocki 56caa73ea1SRafael J. Wysocki return 0; 57caa73ea1SRafael J. Wysocki } 58caa73ea1SRafael J. Wysocki 59caa73ea1SRafael J. Wysocki static void acpi_container_release(struct device *dev) 60caa73ea1SRafael J. Wysocki { 61caa73ea1SRafael J. Wysocki kfree(to_container_dev(dev)); 62caa73ea1SRafael J. Wysocki } 63caa73ea1SRafael J. Wysocki 6446394fd0SRafael J. Wysocki static int container_device_attach(struct acpi_device *adev, 65737f1a9fSRafael J. Wysocki const struct acpi_device_id *not_used) 66737f1a9fSRafael J. Wysocki { 67caa73ea1SRafael J. Wysocki struct container_dev *cdev; 68caa73ea1SRafael J. Wysocki struct device *dev; 69caa73ea1SRafael J. Wysocki int ret; 70caa73ea1SRafael J. Wysocki 711e2380cdSRafael J. Wysocki if (adev->flags.is_dock_station) 721e2380cdSRafael J. Wysocki return 0; 731e2380cdSRafael J. Wysocki 74caa73ea1SRafael J. Wysocki cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 75caa73ea1SRafael J. Wysocki if (!cdev) 76caa73ea1SRafael J. Wysocki return -ENOMEM; 77caa73ea1SRafael J. Wysocki 78caa73ea1SRafael J. Wysocki cdev->offline = acpi_container_offline; 79caa73ea1SRafael J. Wysocki dev = &cdev->dev; 80caa73ea1SRafael J. Wysocki dev->bus = &container_subsys; 81caa73ea1SRafael J. Wysocki dev_set_name(dev, "%s", dev_name(&adev->dev)); 82caa73ea1SRafael J. Wysocki ACPI_COMPANION_SET(dev, adev); 83caa73ea1SRafael J. Wysocki dev->release = acpi_container_release; 84caa73ea1SRafael J. Wysocki ret = device_register(dev); 850f6aa09eSRafael J. Wysocki if (ret) { 860f6aa09eSRafael J. Wysocki put_device(dev); 87caa73ea1SRafael J. Wysocki return ret; 880f6aa09eSRafael J. Wysocki } 89caa73ea1SRafael J. Wysocki adev->driver_data = dev; 90737f1a9fSRafael J. Wysocki return 1; 91737f1a9fSRafael J. Wysocki } 92737f1a9fSRafael J. Wysocki 9346394fd0SRafael J. Wysocki static void container_device_detach(struct acpi_device *adev) 9446394fd0SRafael J. Wysocki { 95caa73ea1SRafael J. Wysocki struct device *dev = acpi_driver_data(adev); 96caa73ea1SRafael J. Wysocki 97caa73ea1SRafael J. Wysocki adev->driver_data = NULL; 98caa73ea1SRafael J. Wysocki if (dev) 99caa73ea1SRafael J. Wysocki device_unregister(dev); 10046394fd0SRafael J. Wysocki } 10146394fd0SRafael J. Wysocki 10279917f34SRafael J. Wysocki static struct acpi_scan_handler container_handler = { 1031ba90e3aSThomas Renninger .ids = container_device_ids, 104737f1a9fSRafael J. Wysocki .attach = container_device_attach, 10546394fd0SRafael J. Wysocki .detach = container_device_detach, 10668a67f6cSRafael J. Wysocki .hotplug = { 10768a67f6cSRafael J. Wysocki .enabled = true, 108caa73ea1SRafael J. Wysocki .demand_offline = true, 10968a67f6cSRafael J. Wysocki }, 1101da177e4SLinus Torvalds }; 1111da177e4SLinus Torvalds 112737f1a9fSRafael J. Wysocki void __init acpi_container_init(void) 1131da177e4SLinus Torvalds { 114*a1ec6572SRafael J. Wysocki acpi_scan_add_handler(&container_handler); 115*a1ec6572SRafael J. Wysocki } 116*a1ec6572SRafael J. Wysocki 117*a1ec6572SRafael J. Wysocki #else 118*a1ec6572SRafael J. Wysocki 119*a1ec6572SRafael J. Wysocki static struct acpi_scan_handler container_handler = { 120*a1ec6572SRafael J. Wysocki .ids = container_device_ids, 121*a1ec6572SRafael J. Wysocki }; 122*a1ec6572SRafael J. Wysocki 123*a1ec6572SRafael J. Wysocki void __init acpi_container_init(void) 124*a1ec6572SRafael J. Wysocki { 12579917f34SRafael J. Wysocki acpi_scan_add_handler_with_hotplug(&container_handler, "container"); 1261da177e4SLinus Torvalds } 127*a1ec6572SRafael J. Wysocki 128*a1ec6572SRafael J. Wysocki #endif /* CONFIG_ACPI_CONTAINER */ 129