diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 1a40111e1c86..891c42d1cd65 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -180,14 +180,15 @@ static void acpi_print_osc_error(acpi_handle handle, int i; if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) - printk(KERN_DEBUG "%s\n", error); + printk(KERN_DEBUG "%s: %s\n", context->uuid_str, error); else { - printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error); + printk(KERN_DEBUG "%s (%s): %s\n", + (char *)buffer.pointer, context->uuid_str, error); kfree(buffer.pointer); } - printk(KERN_DEBUG"_OSC request data:"); + printk(KERN_DEBUG "_OSC request data:"); for (i = 0; i < context->cap.length; i += sizeof(u32)) - printk("%x ", *((u32 *)(context->cap.pointer + i))); + printk(" %x", *((u32 *)(context->cap.pointer + i))); printk("\n"); } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 11d87bf67e73..1e6833a5cd44 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -86,6 +86,14 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) +extern struct list_head acpi_bus_id_list; + +struct acpi_device_bus_id { + char bus_id[15]; + unsigned int instance_no; + struct list_head node; +}; + int acpi_device_add(struct acpi_device *device, void (*release)(struct device *)); void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bb66093b7799..67da6fb72274 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -366,6 +366,19 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) iounmap(vaddr); } +/** + * acpi_os_map_iomem - Get a virtual address for a given physical address range. + * @phys: Start of the physical address range to map. + * @size: Size of the physical address range to map. + * + * Look up the given physical address range in the list of existing ACPI memory + * mappings. If found, get a reference to it and return a pointer to it (its + * virtual address). If not found, map it, add it to that list and return a + * pointer to it. + * + * During early init (when acpi_gbl_permanent_mmap has not been set yet) this + * routine simply calls __acpi_map_table() to get the job done. + */ void __iomem *__init_refok acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) { @@ -441,6 +454,20 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map) } } +/** + * acpi_os_unmap_iomem - Drop a memory mapping reference. + * @virt: Start of the address range to drop a reference to. + * @size: Size of the address range to drop a reference to. + * + * Look up the given virtual address range in the list of existing ACPI memory + * mappings, drop a reference to it and unmap it if there are no more active + * references to it. + * + * During early init (when acpi_gbl_permanent_mmap has not been set yet) this + * routine simply calls __acpi_unmap_table() to get the job done. Since + * __acpi_unmap_table() is an __init function, the __ref annotation is needed + * here. + */ void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 78d5f02a073b..407a3760e8de 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -39,7 +39,7 @@ static const char *dummy_hid = "device"; static LIST_HEAD(acpi_dep_list); static DEFINE_MUTEX(acpi_dep_list_lock); -static LIST_HEAD(acpi_bus_id_list); +LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); @@ -52,12 +52,6 @@ struct acpi_dep_data { acpi_handle slave; }; -struct acpi_device_bus_id{ - char bus_id[15]; - unsigned int instance_no; - struct list_head node; -}; - void acpi_scan_lock_acquire(void) { mutex_lock(&acpi_scan_lock); @@ -471,10 +465,24 @@ static void acpi_device_release(struct device *dev) static void acpi_device_del(struct acpi_device *device) { + struct acpi_device_bus_id *acpi_device_bus_id; + mutex_lock(&acpi_device_lock); if (device->parent) list_del(&device->node); + list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) + if (!strcmp(acpi_device_bus_id->bus_id, + acpi_device_hid(device))) { + if (acpi_device_bus_id->instance_no > 0) + acpi_device_bus_id->instance_no--; + else { + list_del(&acpi_device_bus_id->node); + kfree(acpi_device_bus_id); + } + break; + } + list_del(&device->wakeup_list); mutex_unlock(&acpi_device_lock); @@ -1461,7 +1469,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, *type = ACPI_BUS_TYPE_DEVICE; status = acpi_bus_get_status_handle(handle, sta); if (ACPI_FAILURE(status)) - return -ENODEV; + *sta = 0; break; case ACPI_TYPE_PROCESSOR: *type = ACPI_BUS_TYPE_PROCESSOR; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 475c9079bf85..f2f9873bb5c3 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -29,6 +29,7 @@ #include #include "internal.h" +#include "sleep.h" #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("utils"); @@ -709,6 +710,36 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) } EXPORT_SYMBOL(acpi_check_dsm); +/** + * acpi_dev_present - Detect presence of a given ACPI device in the system. + * @hid: Hardware ID of the device. + * + * Return %true if the device was present at the moment of invocation. + * Note that if the device is pluggable, it may since have disappeared. + * + * For this function to work, acpi_bus_scan() must have been executed + * which happens in the subsys_initcall() subsection. Hence, do not + * call from a subsys_initcall() or earlier (use acpi_get_devices() + * instead). Calling from module_init() is fine (which is synonymous + * with device_initcall()). + */ +bool acpi_dev_present(const char *hid) +{ + struct acpi_device_bus_id *acpi_device_bus_id; + bool found = false; + + mutex_lock(&acpi_device_lock); + list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) + if (!strcmp(acpi_device_bus_id->bus_id, hid)) { + found = true; + break; + } + mutex_unlock(&acpi_device_lock); + + return found; +} +EXPORT_SYMBOL(acpi_dev_present); + /* * acpi_backlight= handling, this is done here rather then in video_detect.c * because __setup cannot be used in modules. diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ad0a5ff3d4cd..14362a84c78e 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -87,6 +87,8 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, .package.elements = (eles) \ } +bool acpi_dev_present(const char *hid); + #ifdef CONFIG_ACPI #include @@ -631,7 +633,9 @@ static inline bool acpi_device_can_wakeup(struct acpi_device *adev) static inline bool acpi_device_can_poweroff(struct acpi_device *adev) { - return adev->power.states[ACPI_STATE_D3_COLD].flags.valid; + return adev->power.states[ACPI_STATE_D3_COLD].flags.valid || + ((acpi_gbl_FADT.header.revision < 6) && + adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set); } #else /* CONFIG_ACPI */