linux/drivers/acpi/container.c
<<
>>
Prefs
   1/*
   2 * container.c  - ACPI Generic Container Driver
   3 *
   4 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
   5 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
   6 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
   7 * Copyright (C) 2004 FUJITSU LIMITED
   8 * Copyright (C) 2004, 2013 Intel Corp.
   9 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  10 *
  11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12 *
  13 *  This program is free software; you can redistribute it and/or modify
  14 *  it under the terms of the GNU General Public License as published by
  15 *  the Free Software Foundation; either version 2 of the License, or (at
  16 *  your option) any later version.
  17 *
  18 *  This program is distributed in the hope that it will be useful, but
  19 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  21 *  General Public License for more details.
  22 *
  23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24 */
  25#include <linux/acpi.h>
  26#include <linux/container.h>
  27
  28#include "internal.h"
  29
  30#define _COMPONENT                      ACPI_CONTAINER_COMPONENT
  31ACPI_MODULE_NAME("container");
  32
  33static const struct acpi_device_id container_device_ids[] = {
  34        {"ACPI0004", 0},
  35        {"PNP0A05", 0},
  36        {"PNP0A06", 0},
  37        {"", 0},
  38};
  39
  40#ifdef CONFIG_ACPI_CONTAINER
  41
  42static int acpi_container_offline(struct container_dev *cdev)
  43{
  44        struct acpi_device *adev = ACPI_COMPANION(&cdev->dev);
  45        struct acpi_device *child;
  46
  47        /* Check all of the dependent devices' physical companions. */
  48        list_for_each_entry(child, &adev->children, node)
  49                if (!acpi_scan_is_offline(child, false))
  50                        return -EBUSY;
  51
  52        return 0;
  53}
  54
  55static void acpi_container_release(struct device *dev)
  56{
  57        kfree(to_container_dev(dev));
  58}
  59
  60static int container_device_attach(struct acpi_device *adev,
  61                                   const struct acpi_device_id *not_used)
  62{
  63        struct container_dev *cdev;
  64        struct device *dev;
  65        int ret;
  66
  67        if (adev->flags.is_dock_station)
  68                return 0;
  69
  70        cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
  71        if (!cdev)
  72                return -ENOMEM;
  73
  74        cdev->offline = acpi_container_offline;
  75        dev = &cdev->dev;
  76        dev->bus = &container_subsys;
  77        dev_set_name(dev, "%s", dev_name(&adev->dev));
  78        ACPI_COMPANION_SET(dev, adev);
  79        dev->release = acpi_container_release;
  80        ret = device_register(dev);
  81        if (ret) {
  82                put_device(dev);
  83                return ret;
  84        }
  85        adev->driver_data = dev;
  86        return 1;
  87}
  88
  89static void container_device_detach(struct acpi_device *adev)
  90{
  91        struct device *dev = acpi_driver_data(adev);
  92
  93        adev->driver_data = NULL;
  94        if (dev)
  95                device_unregister(dev);
  96}
  97
  98static void container_device_online(struct acpi_device *adev)
  99{
 100        struct device *dev = acpi_driver_data(adev);
 101
 102        kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 103}
 104
 105static struct acpi_scan_handler container_handler = {
 106        .ids = container_device_ids,
 107        .attach = container_device_attach,
 108        .detach = container_device_detach,
 109        .hotplug = {
 110                .enabled = true,
 111                .demand_offline = true,
 112                .notify_online = container_device_online,
 113        },
 114};
 115
 116void __init acpi_container_init(void)
 117{
 118        acpi_scan_add_handler(&container_handler);
 119}
 120
 121#else
 122
 123static struct acpi_scan_handler container_handler = {
 124        .ids = container_device_ids,
 125};
 126
 127void __init acpi_container_init(void)
 128{
 129        acpi_scan_add_handler_with_hotplug(&container_handler, "container");
 130}
 131
 132#endif /* CONFIG_ACPI_CONTAINER */
 133