container.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. #include "internal.h"
  15. static const struct acpi_device_id container_device_ids[] = {
  16. {"ACPI0004", 0},
  17. {"PNP0A05", 0},
  18. {"PNP0A06", 0},
  19. {"", 0},
  20. };
  21. #ifdef CONFIG_ACPI_CONTAINER
  22. static int acpi_container_offline(struct container_dev *cdev)
  23. {
  24. struct acpi_device *adev = ACPI_COMPANION(&cdev->dev);
  25. struct acpi_device *child;
  26. /* Check all of the dependent devices' physical companions. */
  27. list_for_each_entry(child, &adev->children, node)
  28. if (!acpi_scan_is_offline(child, false))
  29. return -EBUSY;
  30. return 0;
  31. }
  32. static void acpi_container_release(struct device *dev)
  33. {
  34. kfree(to_container_dev(dev));
  35. }
  36. static int container_device_attach(struct acpi_device *adev,
  37. const struct acpi_device_id *not_used)
  38. {
  39. struct container_dev *cdev;
  40. struct device *dev;
  41. int ret;
  42. if (adev->flags.is_dock_station)
  43. return 0;
  44. cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
  45. if (!cdev)
  46. return -ENOMEM;
  47. cdev->offline = acpi_container_offline;
  48. dev = &cdev->dev;
  49. dev->bus = &container_subsys;
  50. dev_set_name(dev, "%s", dev_name(&adev->dev));
  51. ACPI_COMPANION_SET(dev, adev);
  52. dev->release = acpi_container_release;
  53. ret = device_register(dev);
  54. if (ret) {
  55. put_device(dev);
  56. return ret;
  57. }
  58. adev->driver_data = dev;
  59. return 1;
  60. }
  61. static void container_device_detach(struct acpi_device *adev)
  62. {
  63. struct device *dev = acpi_driver_data(adev);
  64. adev->driver_data = NULL;
  65. if (dev)
  66. device_unregister(dev);
  67. }
  68. static void container_device_online(struct acpi_device *adev)
  69. {
  70. struct device *dev = acpi_driver_data(adev);
  71. kobject_uevent(&dev->kobj, KOBJ_ONLINE);
  72. }
  73. static struct acpi_scan_handler container_handler = {
  74. .ids = container_device_ids,
  75. .attach = container_device_attach,
  76. .detach = container_device_detach,
  77. .hotplug = {
  78. .enabled = true,
  79. .demand_offline = true,
  80. .notify_online = container_device_online,
  81. },
  82. };
  83. void __init acpi_container_init(void)
  84. {
  85. acpi_scan_add_handler(&container_handler);
  86. }
  87. #else
  88. static struct acpi_scan_handler container_handler = {
  89. .ids = container_device_ids,
  90. };
  91. void __init acpi_container_init(void)
  92. {
  93. acpi_scan_add_handler_with_hotplug(&container_handler, "container");
  94. }
  95. #endif /* CONFIG_ACPI_CONTAINER */