summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/ac.c17
-rw-r--r--drivers/acpi/battery.c15
-rw-r--r--drivers/acpi/button.c9
-rw-r--r--drivers/acpi/fan.c21
-rw-r--r--drivers/acpi/glue.c4
-rw-r--r--drivers/acpi/numa.c12
-rw-r--r--drivers/acpi/pci_root.c13
-rw-r--r--drivers/acpi/power.c14
-rw-r--r--drivers/acpi/processor_driver.c15
-rw-r--r--drivers/acpi/processor_idle.c43
-rw-r--r--drivers/acpi/sbs.c10
-rw-r--r--drivers/acpi/scan.c22
-rw-r--r--drivers/acpi/sleep.c28
-rw-r--r--drivers/acpi/sysfs.c4
-rw-r--r--drivers/acpi/thermal.c17
-rw-r--r--drivers/acpi/video_detect.c60
16 files changed, 177 insertions, 127 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index d1fcbc0..ac70341 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -61,7 +61,6 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_resume(struct acpi_device *device);
static void acpi_ac_notify(struct acpi_device *device, u32 event);
static const struct acpi_device_id ac_device_ids[] = {
@@ -70,6 +69,9 @@ static const struct acpi_device_id ac_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
+static int acpi_ac_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
+
static struct acpi_driver acpi_ac_driver = {
.name = "ac",
.class = ACPI_AC_CLASS,
@@ -78,9 +80,9 @@ static struct acpi_driver acpi_ac_driver = {
.ops = {
.add = acpi_ac_add,
.remove = acpi_ac_remove,
- .resume = acpi_ac_resume,
.notify = acpi_ac_notify,
},
+ .drv.pm = &acpi_ac_pm,
};
struct acpi_ac {
@@ -311,13 +313,18 @@ static int acpi_ac_add(struct acpi_device *device)
return result;
}
-static int acpi_ac_resume(struct acpi_device *device)
+static int acpi_ac_resume(struct device *dev)
{
struct acpi_ac *ac;
unsigned old_state;
- if (!device || !acpi_driver_data(device))
+
+ if (!dev)
return -EINVAL;
- ac = acpi_driver_data(device);
+
+ ac = acpi_driver_data(to_acpi_device(dev));
+ if (!ac)
+ return -EINVAL;
+
old_state = ac->state;
if (acpi_ac_get_state(ac))
return 0;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 5662d64..ff2c876 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1053,17 +1053,24 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
}
/* this is needed to learn about changes made in suspended state */
-static int acpi_battery_resume(struct acpi_device *device)
+static int acpi_battery_resume(struct device *dev)
{
struct acpi_battery *battery;
- if (!device)
+
+ if (!dev)
return -EINVAL;
- battery = acpi_driver_data(device);
+
+ battery = acpi_driver_data(to_acpi_device(dev));
+ if (!battery)
+ return -EINVAL;
+
battery->update_time = 0;
acpi_battery_update(battery);
return 0;
}
+static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
+
static struct acpi_driver acpi_battery_driver = {
.name = "battery",
.class = ACPI_BATTERY_CLASS,
@@ -1071,10 +1078,10 @@ static struct acpi_driver acpi_battery_driver = {
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
.ops = {
.add = acpi_battery_add,
- .resume = acpi_battery_resume,
.remove = acpi_battery_remove,
.notify = acpi_battery_notify,
},
+ .drv.pm = &acpi_battery_pm,
};
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index d27d072..79d4c22 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -76,19 +76,21 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
static int acpi_button_add(struct acpi_device *device);
static int acpi_button_remove(struct acpi_device *device, int type);
-static int acpi_button_resume(struct acpi_device *device);
static void acpi_button_notify(struct acpi_device *device, u32 event);
+static int acpi_button_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
+
static struct acpi_driver acpi_button_driver = {
.name = "button",
.class = ACPI_BUTTON_CLASS,
.ids = button_device_ids,
.ops = {
.add = acpi_button_add,
- .resume = acpi_button_resume,
.remove = acpi_button_remove,
.notify = acpi_button_notify,
},
+ .drv.pm = &acpi_button_pm,
};
struct acpi_button {
@@ -308,8 +310,9 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
}
}
-static int acpi_button_resume(struct acpi_device *device)
+static int acpi_button_resume(struct device *dev)
{
+ struct acpi_device *device = to_acpi_device(dev);
struct acpi_button *button = acpi_driver_data(device);
if (button->type == ACPI_BUTTON_TYPE_LID)
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 0f0356c..669d9ee 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -46,8 +46,6 @@ MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device);
static int acpi_fan_remove(struct acpi_device *device, int type);
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
-static int acpi_fan_resume(struct acpi_device *device);
static const struct acpi_device_id fan_device_ids[] = {
{"PNP0C0B", 0},
@@ -55,6 +53,10 @@ static const struct acpi_device_id fan_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, fan_device_ids);
+static int acpi_fan_suspend(struct device *dev);
+static int acpi_fan_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
+
static struct acpi_driver acpi_fan_driver = {
.name = "fan",
.class = ACPI_FAN_CLASS,
@@ -62,9 +64,8 @@ static struct acpi_driver acpi_fan_driver = {
.ops = {
.add = acpi_fan_add,
.remove = acpi_fan_remove,
- .suspend = acpi_fan_suspend,
- .resume = acpi_fan_resume,
},
+ .drv.pm = &acpi_fan_pm,
};
/* thermal cooling device callbacks */
@@ -183,24 +184,24 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
return 0;
}
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
+static int acpi_fan_suspend(struct device *dev)
{
- if (!device)
+ if (!dev)
return -EINVAL;
- acpi_bus_set_power(device->handle, ACPI_STATE_D0);
+ acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
return AE_OK;
}
-static int acpi_fan_resume(struct acpi_device *device)
+static int acpi_fan_resume(struct device *dev)
{
int result;
- if (!device)
+ if (!dev)
return -EINVAL;
- result = acpi_bus_update_power(device->handle, NULL);
+ result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
if (result)
printk(KERN_ERR PREFIX "Error updating fan power state\n");
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 1564e09..243ee85 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -39,6 +39,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
}
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(register_acpi_bus_type);
int unregister_acpi_bus_type(struct acpi_bus_type *type)
{
@@ -54,6 +55,7 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
}
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
{
@@ -69,7 +71,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
up_read(&bus_type_sem);
return ret;
}
-EXPORT_SYMBOL_GPL(register_acpi_bus_type);
static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
{
@@ -86,7 +87,6 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
up_read(&bus_type_sem);
return ret;
}
-EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
/* Get device's handler per its address under its parent */
struct acpi_find_child {
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index e56f3be..cb31298 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -237,6 +237,8 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header,
return 0;
}
+static int __initdata parsed_numa_memblks;
+
static int __init
acpi_parse_memory_affinity(struct acpi_subtable_header * header,
const unsigned long end)
@@ -250,8 +252,8 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,
acpi_table_print_srat_entry(header);
/* let architecture-dependent part to do it */
- acpi_numa_memory_affinity_init(memory_affinity);
-
+ if (!acpi_numa_memory_affinity_init(memory_affinity))
+ parsed_numa_memblks++;
return 0;
}
@@ -304,8 +306,10 @@ int __init acpi_numa_init(void)
acpi_numa_arch_fixup();
- if (cnt <= 0)
- return cnt ?: -ENOENT;
+ if (cnt < 0)
+ return cnt;
+ else if (!parsed_numa_memblks)
+ return -ENOENT;
return 0;
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7aff631..72a2c98 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -505,6 +505,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
+
/*
* All supported architectures that use ACPI have support for
* PCI domains, so we indicate this in _OSC support capabilities.
@@ -571,8 +573,15 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
if (pci_msi_enabled())
flags |= OSC_MSI_SUPPORT;
- if (flags != base_flags)
- acpi_pci_osc_support(root, flags);
+ if (flags != base_flags) {
+ status = acpi_pci_osc_support(root, flags);
+ if (ACPI_FAILURE(status)) {
+ dev_info(root->bus->bridge, "ACPI _OSC support "
+ "notification failed, disabling PCIe ASPM\n");
+ pcie_no_aspm();
+ flags = base_flags;
+ }
+ }
if (!pcie_ports_disabled
&& (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index dd6d6a3..215ecd0 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -60,7 +60,6 @@ ACPI_MODULE_NAME("power");
static int acpi_power_add(struct acpi_device *device);
static int acpi_power_remove(struct acpi_device *device, int type);
-static int acpi_power_resume(struct acpi_device *device);
static const struct acpi_device_id power_device_ids[] = {
{ACPI_POWER_HID, 0},
@@ -68,6 +67,9 @@ static const struct acpi_device_id power_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, power_device_ids);
+static int acpi_power_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume);
+
static struct acpi_driver acpi_power_driver = {
.name = "power",
.class = ACPI_POWER_CLASS,
@@ -75,8 +77,8 @@ static struct acpi_driver acpi_power_driver = {
.ops = {
.add = acpi_power_add,
.remove = acpi_power_remove,
- .resume = acpi_power_resume,
},
+ .drv.pm = &acpi_power_pm,
};
/*
@@ -390,6 +392,7 @@ void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handl
__acpi_power_resource_unregister_device(dev,
list->handles[i]);
}
+EXPORT_SYMBOL_GPL(acpi_power_resource_unregister_device);
static int __acpi_power_resource_register_device(
struct acpi_power_managed_device *powered_device, acpi_handle handle)
@@ -460,6 +463,7 @@ no_power_resource:
printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
/**
* acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
@@ -771,14 +775,16 @@ static int acpi_power_remove(struct acpi_device *device, int type)
return 0;
}
-static int acpi_power_resume(struct acpi_device *device)
+static int acpi_power_resume(struct device *dev)
{
int result = 0, state;
+ struct acpi_device *device;
struct acpi_power_resource *resource;
- if (!device)
+ if (!dev)
return -EINVAL;
+ device = to_acpi_device(dev);
resource = acpi_driver_data(device);
if (!resource)
return -EINVAL;
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 971c454..bfc31cb 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -93,6 +93,9 @@ static const struct acpi_device_id processor_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, processor_device_ids);
+static SIMPLE_DEV_PM_OPS(acpi_processor_pm,
+ acpi_processor_suspend, acpi_processor_resume);
+
static struct acpi_driver acpi_processor_driver = {
.name = "processor",
.class = ACPI_PROCESSOR_CLASS,
@@ -100,10 +103,9 @@ static struct acpi_driver acpi_processor_driver = {
.ops = {
.add = acpi_processor_add,
.remove = acpi_processor_remove,
- .suspend = acpi_processor_suspend,
- .resume = acpi_processor_resume,
.notify = acpi_processor_notify,
},
+ .drv.pm = &acpi_processor_pm,
};
#define INSTALL_NOTIFY_HANDLER 1
@@ -427,22 +429,15 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
* Initialize missing things
*/
if (pr->flags.need_hotplug_init) {
- struct cpuidle_driver *idle_driver =
- cpuidle_get_driver();
-
printk(KERN_INFO "Will online and init hotplugged "
"CPU: %d\n", pr->id);
WARN(acpi_processor_start(pr), "Failed to start CPU:"
" %d\n", pr->id);
pr->flags.need_hotplug_init = 0;
- if (idle_driver && !strcmp(idle_driver->name,
- "intel_idle")) {
- intel_idle_cpu_init(pr->id);
- }
/* Normal CPU soft online event */
} else {
acpi_processor_ppc_has_changed(pr, 0);
- acpi_processor_cst_has_changed(pr);
+ acpi_processor_hotplug(pr);
acpi_processor_reevaluate_tstate(pr, action);
acpi_processor_tstate_has_changed(pr);
}
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 9837c9c..ad3730b 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -221,10 +221,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
#endif
-/*
- * Suspend / resume control
- */
-static int acpi_idle_suspend;
static u32 saved_bm_rld;
static void acpi_idle_bm_rld_save(void)
@@ -241,23 +237,15 @@ static void acpi_idle_bm_rld_restore(void)
acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
}
-int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
+int acpi_processor_suspend(struct device *dev)
{
- if (acpi_idle_suspend == 1)
- return 0;
-
acpi_idle_bm_rld_save();
- acpi_idle_suspend = 1;
return 0;
}
-int acpi_processor_resume(struct acpi_device * device)
+int acpi_processor_resume(struct device *dev)
{
- if (acpi_idle_suspend == 0)
- return 0;
-
acpi_idle_bm_rld_restore();
- acpi_idle_suspend = 0;
return 0;
}
@@ -595,7 +583,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
*/
cx->valid = 1;
- cx->latency_ticks = cx->latency;
/*
* On older chipsets, BM_RLD needs to be set
* in order for Bus Master activity to wake the
@@ -628,7 +615,6 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
if (!cx->address)
break;
cx->valid = 1;
- cx->latency_ticks = cx->latency; /* Normalize latency */
break;
case ACPI_STATE_C3:
@@ -763,11 +749,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
local_irq_disable();
- if (acpi_idle_suspend) {
- local_irq_enable();
- cpu_relax();
- return -EBUSY;
- }
lapic_timer_state_broadcast(pr, cx, 1);
kt1 = ktime_get_real();
@@ -779,7 +760,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
dev->last_residency = (int)idle_time;
local_irq_enable();
- cx->usage++;
lapic_timer_state_broadcast(pr, cx, 0);
return index;
@@ -838,11 +818,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
local_irq_disable();
- if (acpi_idle_suspend) {
- local_irq_enable();
- cpu_relax();
- return -EBUSY;
- }
if (cx->entry_method != ACPI_CSTATE_FFH) {
current_thread_info()->status &= ~TS_POLLING;
@@ -887,10 +862,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (cx->entry_method != ACPI_CSTATE_FFH)
current_thread_info()->status |= TS_POLLING;
- cx->usage++;
-
lapic_timer_state_broadcast(pr, cx, 0);
- cx->time += idle_time;
return index;
}
@@ -928,8 +900,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
drv, drv->safe_state_index);
} else {
local_irq_disable();
- if (!acpi_idle_suspend)
- acpi_safe_halt();
+ acpi_safe_halt();
local_irq_enable();
return -EBUSY;
}
@@ -937,11 +908,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
local_irq_disable();
- if (acpi_idle_suspend) {
- local_irq_enable();
- cpu_relax();
- return -EBUSY;
- }
if (cx->entry_method != ACPI_CSTATE_FFH) {
current_thread_info()->status &= ~TS_POLLING;
@@ -1014,10 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (cx->entry_method != ACPI_CSTATE_FFH)
current_thread_info()->status |= TS_POLLING;
- cx->usage++;
-
lapic_timer_state_broadcast(pr, cx, 0);
- cx->time += idle_time;
return index;
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 6e36d0c..c0b9aa5 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -988,16 +988,18 @@ static void acpi_sbs_rmdirs(void)
#endif
}
-static int acpi_sbs_resume(struct acpi_device *device)
+static int acpi_sbs_resume(struct device *dev)
{
struct acpi_sbs *sbs;
- if (!device)
+ if (!dev)
return -EINVAL;
- sbs = device->driver_data;
+ sbs = to_acpi_device(dev)->driver_data;
acpi_sbs_callback(sbs);
return 0;
}
+static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
+
static struct acpi_driver acpi_sbs_driver = {
.name = "sbs",
.class = ACPI_SBS_CLASS,
@@ -1005,8 +1007,8 @@ static struct acpi_driver acpi_sbs_driver = {
.ops = {
.add = acpi_sbs_add,
.remove = acpi_sbs_remove,
- .resume = acpi_sbs_resume,
},
+ .drv.pm = &acpi_sbs_pm,
};
static int __init acpi_sbs_init(void)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 148556a..d1ecca2 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -330,26 +330,6 @@ static void acpi_device_release(struct device *dev)
kfree(acpi_dev);
}
-static int acpi_device_suspend(struct device *dev, pm_message_t state)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = acpi_dev->driver;
-
- if (acpi_drv && acpi_drv->ops.suspend)
- return acpi_drv->ops.suspend(acpi_dev, state);
- return 0;
-}
-
-static int acpi_device_resume(struct device *dev)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = acpi_dev->driver;
-
- if (acpi_drv && acpi_drv->ops.resume)
- return acpi_drv->ops.resume(acpi_dev);
- return 0;
-}
-
static int acpi_bus_match(struct device *dev, struct device_driver *drv)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -481,8 +461,6 @@ static int acpi_device_remove(struct device * dev)
struct bus_type acpi_bus_type = {
.name = "acpi",
- .suspend = acpi_device_suspend,
- .resume = acpi_device_resume,
.match = acpi_bus_match,
.probe = acpi_device_probe,
.remove = acpi_device_remove,
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index bd35e3c..fdcdbb6 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -29,7 +29,6 @@
#include "sleep.h"
static u8 sleep_states[ACPI_S_STATE_COUNT];
-static bool pwr_btn_event_pending;
static void acpi_sleep_tts_switch(u32 acpi_state)
{
@@ -82,6 +81,7 @@ static int acpi_sleep_prepare(u32 acpi_state)
#ifdef CONFIG_ACPI_SLEEP
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+static bool pwr_btn_event_pending;
/*
* The ACPI specification wants us to save NVS memory regions during hibernation
@@ -688,8 +688,9 @@ int acpi_suspend(u32 acpi_state)
* @dev: device to examine; its driver model wakeup flags control
* whether it should be able to wake up the system
* @d_min_p: used to store the upper limit of allowed states range
- * Return value: preferred power state of the device on success, -ENODEV on
- * failure (ie. if there's no 'struct acpi_device' for @dev)
+ * @d_max_in: specify the lowest allowed states
+ * Return value: preferred power state of the device on success, -ENODEV
+ * (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
*
* Find the lowest power (highest number) ACPI device power state that
* device @dev can be in while the system is in the sleep state represented
@@ -704,13 +705,15 @@ int acpi_suspend(u32 acpi_state)
* via @wake.
*/
-int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
+int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
{
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
char acpi_method[] = "_SxD";
unsigned long long d_min, d_max;
+ if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
+ return -EINVAL;
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
printk(KERN_DEBUG "ACPI handle has no context!\n");
return -ENODEV;
@@ -718,8 +721,10 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
acpi_method[2] = '0' + acpi_target_sleep_state;
/*
- * If the sleep state is S0, we will return D3, but if the device has
- * _S0W, we will use the value from _S0W
+ * If the sleep state is S0, the lowest limit from ACPI is D3,
+ * but if the device has _S0W, we will use the value from _S0W
+ * as the lowest limit from ACPI. Finally, we will constrain
+ * the lowest limit with the specified one.
*/
d_min = ACPI_STATE_D0;
d_max = ACPI_STATE_D3;
@@ -763,10 +768,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
}
}
+ if (d_max_in < d_min)
+ return -EINVAL;
if (d_min_p)
*d_min_p = d_min;
+ /* constrain d_max with specified lowest limit (max number) */
+ if (d_max > d_max_in) {
+ for (d_max = d_max_in; d_max > d_min; d_max--) {
+ if (adev->power.states[d_max].flags.valid)
+ break;
+ }
+ }
return d_max;
}
+EXPORT_SYMBOL(acpi_pm_device_sleep_state);
#endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP
@@ -803,6 +818,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
return 0;
}
+EXPORT_SYMBOL(acpi_pm_device_run_wake);
/**
* acpi_pm_device_sleep_wake - enable or disable the system wake-up
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 240a244..7c3f98b 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
{
int result = 0;
- if (!strncmp(val, "enable", strlen("enable"))) {
+ if (!strncmp(val, "enable", sizeof("enable") - 1)) {
result = acpi_debug_trace(trace_method_name, trace_debug_level,
trace_debug_layer, 0);
if (result)
@@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
goto exit;
}
- if (!strncmp(val, "disable", strlen("disable"))) {
+ if (!strncmp(val, "disable", sizeof("disable") - 1)) {
int name = 0;
result = acpi_debug_trace((char *)&name, trace_debug_level,
trace_debug_layer, 0);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 8275e7b..9fe90e9 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -98,7 +98,6 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
static int acpi_thermal_add(struct acpi_device *device);
static int acpi_thermal_remove(struct acpi_device *device, int type);
-static int acpi_thermal_resume(struct acpi_device *device);
static void acpi_thermal_notify(struct acpi_device *device, u32 event);
static const struct acpi_device_id thermal_device_ids[] = {
@@ -107,6 +106,9 @@ static const struct acpi_device_id thermal_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
+static int acpi_thermal_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
+
static struct acpi_driver acpi_thermal_driver = {
.name = "thermal",
.class = ACPI_THERMAL_CLASS,
@@ -114,9 +116,9 @@ static struct acpi_driver acpi_thermal_driver = {
.ops = {
.add = acpi_thermal_add,
.remove = acpi_thermal_remove,
- .resume = acpi_thermal_resume,
.notify = acpi_thermal_notify,
},
+ .drv.pm = &acpi_thermal_pm,
};
struct acpi_thermal_state {
@@ -1039,16 +1041,17 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
return 0;
}
-static int acpi_thermal_resume(struct acpi_device *device)
+static int acpi_thermal_resume(struct device *dev)
{
- struct acpi_thermal *tz = NULL;
+ struct acpi_thermal *tz;
int i, j, power_state, result;
-
- if (!device || !acpi_driver_data(device))
+ if (!dev)
return -EINVAL;
- tz = acpi_driver_data(device);
+ tz = acpi_driver_data(to_acpi_device(dev));
+ if (!tz)
+ return -EINVAL;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
if (!(&tz->trips.active[i]))
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 45d8097..b728880 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -132,6 +132,33 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}
+/* Force to use vendor driver when the ACPI device is known to be
+ * buggy */
+static int video_detect_force_vendor(const struct dmi_system_id *d)
+{
+ acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
+ return 0;
+}
+
+static struct dmi_system_id video_detect_dmi_table[] = {
+ /* On Samsung X360, the BIOS will set a flag (VDRV) if generic
+ * ACPI backlight device is used. This flag will definitively break
+ * the backlight interface (even the vendor interface) untill next
+ * reboot. It's why we should prevent video.ko from being used here
+ * and we can't rely on a later call to acpi_video_unregister().
+ */
+ {
+ .callback = video_detect_force_vendor,
+ .ident = "X360",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
+ DMI_MATCH(DMI_BOARD_NAME, "X360"),
+ },
+ },
+ { },
+};
+
/*
* Returns the video capabilities of a specific ACPI graphics device
*
@@ -164,6 +191,8 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
* ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
*}
*/
+
+ dmi_check_system(video_detect_dmi_table);
} else {
status = acpi_bus_get_device(graphics_handle, &tmp_dev);
if (ACPI_FAILURE(status)) {
@@ -182,8 +211,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
}
EXPORT_SYMBOL(acpi_video_get_capabilities);
-/* Returns true if video.ko can do backlight switching */
-int acpi_video_backlight_support(void)
+static void acpi_video_caps_check(void)
{
/*
* We must check whether the ACPI graphics device is physically plugged
@@ -191,6 +219,34 @@ int acpi_video_backlight_support(void)
*/
if (!acpi_video_caps_checked)
acpi_video_get_capabilities(NULL);
+}
+
+/* Promote the vendor interface instead of the generic video module.
+ * This function allow DMI blacklists to be implemented by externals
+ * platform drivers instead of putting a big blacklist in video_detect.c
+ * After calling this function you will probably want to call
+ * acpi_video_unregister() to make sure the video module is not loaded
+ */
+void acpi_video_dmi_promote_vendor(void)
+{
+ acpi_video_caps_check();
+ acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
+}
+EXPORT_SYMBOL(acpi_video_dmi_promote_vendor);
+
+/* To be called when a driver who previously promoted the vendor
+ * interface */
+void acpi_video_dmi_demote_vendor(void)
+{
+ acpi_video_caps_check();
+ acpi_video_support &= ~ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
+}
+EXPORT_SYMBOL(acpi_video_dmi_demote_vendor);
+
+/* Returns true if video.ko can do backlight switching */
+int acpi_video_backlight_support(void)
+{
+ acpi_video_caps_check();
/* First check for boot param -> highest prio */
if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR)