mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 14:05:39 +00:00
1e2380cd14
The ACPI dock station code carries out an extra namespace scan before the main one in order to find and register all of the dock device objects. Then, it registers a notify handler for each of them for handling dock events. However, dock device objects need not be scanned for upfront. They very well can be enumerated and registered during the first phase of the main namespace scan, before attaching scan handlers and ACPI drivers to ACPI device objects. Then, the dependent devices can be added to the in the second phase. That makes it possible to drop the extra namespace scan, so do it. Moreover, it is not necessary to register notify handlers for all of the dock stations' namespace nodes, becuase notifications may be dispatched from the global notify handler for them. Do that and drop two functions used for dock notify handling, acpi_dock_deferred_cb() and dock_notify_handler(), that aren't necessary any more. Finally, some dock station objects have _HID objects matching the ACPI container scan handler which causes it to claim those objects and try to handle their hotplug, but that is not a good idea, because those objects have their own special hotplug handling anyway. For this reason, the hotplug_notify flag should not be set for ACPI device objects representing dock stations and the container scan handler should be made ignore those objects, so make that happen. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
115 lines
3.1 KiB
C
115 lines
3.1 KiB
C
/*
|
|
* container.c - ACPI Generic Container Driver
|
|
*
|
|
* Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
|
|
* Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
|
|
* Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
|
|
* Copyright (C) 2004 FUJITSU LIMITED
|
|
* Copyright (C) 2004, 2013 Intel Corp.
|
|
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
|
*
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
*/
|
|
#include <linux/acpi.h>
|
|
#include <linux/container.h>
|
|
|
|
#include "internal.h"
|
|
|
|
#define PREFIX "ACPI: "
|
|
|
|
#define _COMPONENT ACPI_CONTAINER_COMPONENT
|
|
ACPI_MODULE_NAME("container");
|
|
|
|
static const struct acpi_device_id container_device_ids[] = {
|
|
{"ACPI0004", 0},
|
|
{"PNP0A05", 0},
|
|
{"PNP0A06", 0},
|
|
{"", 0},
|
|
};
|
|
|
|
static int acpi_container_offline(struct container_dev *cdev)
|
|
{
|
|
struct acpi_device *adev = ACPI_COMPANION(&cdev->dev);
|
|
struct acpi_device *child;
|
|
|
|
/* Check all of the dependent devices' physical companions. */
|
|
list_for_each_entry(child, &adev->children, node)
|
|
if (!acpi_scan_is_offline(child, false))
|
|
return -EBUSY;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void acpi_container_release(struct device *dev)
|
|
{
|
|
kfree(to_container_dev(dev));
|
|
}
|
|
|
|
static int container_device_attach(struct acpi_device *adev,
|
|
const struct acpi_device_id *not_used)
|
|
{
|
|
struct container_dev *cdev;
|
|
struct device *dev;
|
|
int ret;
|
|
|
|
if (adev->flags.is_dock_station)
|
|
return 0;
|
|
|
|
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
|
|
if (!cdev)
|
|
return -ENOMEM;
|
|
|
|
cdev->offline = acpi_container_offline;
|
|
dev = &cdev->dev;
|
|
dev->bus = &container_subsys;
|
|
dev_set_name(dev, "%s", dev_name(&adev->dev));
|
|
ACPI_COMPANION_SET(dev, adev);
|
|
dev->release = acpi_container_release;
|
|
ret = device_register(dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
adev->driver_data = dev;
|
|
return 1;
|
|
}
|
|
|
|
static void container_device_detach(struct acpi_device *adev)
|
|
{
|
|
struct device *dev = acpi_driver_data(adev);
|
|
|
|
adev->driver_data = NULL;
|
|
if (dev)
|
|
device_unregister(dev);
|
|
}
|
|
|
|
static struct acpi_scan_handler container_handler = {
|
|
.ids = container_device_ids,
|
|
.attach = container_device_attach,
|
|
.detach = container_device_detach,
|
|
.hotplug = {
|
|
.enabled = true,
|
|
.demand_offline = true,
|
|
},
|
|
};
|
|
|
|
void __init acpi_container_init(void)
|
|
{
|
|
acpi_scan_add_handler_with_hotplug(&container_handler, "container");
|
|
}
|