dect
/
linux-2.6
Archived
13
0
Fork 0

Power management updates for 3.6

* ACPI conversion to PM handling based on struct dev_pm_ops.
 * Conversion of a number of platform drivers to PM handling based on struct
   dev_pm_ops and removal of empty legacy PM callbacks from a couple of PCI
   drivers.
 * Suspend-to-both for in-kernel hibernation from Bojan Smojver.
 * cpuidle fixes and cleanups from ShuoX Liu, Daniel Lezcano and Preeti U Murthy.
 * cpufreq bug fixes from Jonghwa Lee and Stephen Boyd.
 * Suspend and hibernate fixes from Srivatsa S. Bhat and Colin Cross.
 * Generic PM domains framework updates.
 * RTC CMOS wakeup signaling update from Paul Fox.
 * sparse warnings fixes from Sachin Kamat.
 * Build warnings fixes for the generic PM domains framework and PM sysfs code.
 * sysfs switch for printing device suspend times from Sameer Nanda.
 * Documentation fix from Oskar Schirmer.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.18 (GNU/Linux)
 
 iQIcBAABAgAGBQJQDF5eAAoJEKhOf7ml8uNsEaAP/2wg4faoOGob5A0/7tLqG3Cw
 xnTmGsfL7wG07Q8ykCL1BSlBb1VeJz8L6LTmUpaABI4M//oIBlcYQKyCE0Tat1AO
 9bJXFzK7qcHMhkTz6d6LDqtVzR3NGM3ypjZqj8aEXBov07LMR1AXvgNwXXhv25zM
 0unwrh1XNinBN3n+oaktpWk1YHUjsa5IMU+2tQJrocuHXcgK30vGXZVrZ4g9w1c2
 eS+ED1oKUqOYtFzIUX+aCtaDDheGaPlugk/GOtIB7Sae0s0vMlxH/T5ncB4SxRC+
 v3s4OykqQc5Dc8+0bNlBH7ykSVNB0PoQiyKDY67CxtH+q1xQSc9/f3XJqnGMaVDE
 17eZUZsL4qSyzRuCbPCGAgwBHmx3qNCMu1i1BcmnSxU+ikPUeCR7mYOP0mRThwPH
 OSfs+c/vZ+Ow6CwVE4UFrbm9Jve7ADnCrlZzT2m6XjhHGyjKP7SJlzP9TPsZ0LRk
 oxgQDYHmxbo50t9tBCz5L4ZTMKkDp28e78x84/CteP85srcW3GqDxrPyp2uzJu5O
 tvIEBvVlc4ucq8sG83RkugQwrG/2cQwG2HO9ERAwq01HHA1BYsuU3A961Jqf5CZo
 nFRSnByvVj/imPf47OWpDPAbVEs7jxufJuLEbPwGj1MkttTGDBIRu3zldXt2S6kP
 Q4qYU6fDaQQHFc90pqxQ
 =vC4/
 -----END PGP SIGNATURE-----

Merge tag 'pm-for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:

 - ACPI conversion to PM handling based on struct dev_pm_ops.
 - Conversion of a number of platform drivers to PM handling based on
   struct dev_pm_ops and removal of empty legacy PM callbacks from a
   couple of PCI drivers.
 - Suspend-to-both for in-kernel hibernation from Bojan Smojver.
 - cpuidle fixes and cleanups from ShuoX Liu, Daniel Lezcano and Preeti
   Murthy.
 - cpufreq bug fixes from Jonghwa Lee and Stephen Boyd.
 - Suspend and hibernate fixes from Srivatsa Bhat and Colin Cross.
 - Generic PM domains framework updates.
 - RTC CMOS wakeup signaling update from Paul Fox.
 - sparse warnings fixes from Sachin Kamat.
 - Build warnings fixes for the generic PM domains framework and PM
   sysfs code.
 - sysfs switch for printing device suspend times from Sameer Nanda.
 - Documentation fix from Oskar Schirmer.

* tag 'pm-for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (70 commits)
  cpufreq: Fix sysfs deadlock with concurrent hotplug/frequency switch
  EXYNOS: bugfix on retrieving old_index from freqs.old
  PM / Sleep: call early resume handlers when suspend_noirq fails
  PM / QoS: Use NULL pointer instead of plain integer in qos.c
  PM / QoS: Use NULL pointer instead of plain integer in pm_qos.h
  PM / Sleep: Require CAP_BLOCK_SUSPEND to use wake_lock/wake_unlock
  PM / Sleep: Add missing static storage class specifiers in main.c
  cpuilde / ACPI: remove time from acpi_processor_cx structure
  cpuidle / ACPI: remove usage from acpi_processor_cx structure
  cpuidle / ACPI : remove latency_ticks from acpi_processor_cx structure
  rtc-cmos: report wakeups from interrupt handler
  PM / Sleep: Fix build warning in sysfs.c for CONFIG_PM_SLEEP unset
  PM / Domains: Fix build warning for CONFIG_PM_RUNTIME unset
  olpc-xo15-sci: Use struct dev_pm_ops for power management
  PM / Domains: Replace plain integer with NULL pointer in domain.c file
  PM / Domains: Add missing static storage class specifier in domain.c file
  PM / crypto / ux500: Use struct dev_pm_ops for power management
  PM / IPMI: Remove empty legacy PCI PM callbacks
  tpm_nsc: Use struct dev_pm_ops for power management
  tpm_tis: Use struct dev_pm_ops for power management
  ...
This commit is contained in:
Linus Torvalds 2012-07-22 13:36:52 -07:00
commit 7100e505b7
65 changed files with 887 additions and 479 deletions

View File

@ -231,3 +231,16 @@ Description:
Reads from this file return a string consisting of the names of
wakeup sources created with the help of /sys/power/wake_lock
that are inactive at the moment, separated with spaces.
What: /sys/power/pm_print_times
Date: May 2012
Contact: Sameer Nanda <snanda@chromium.org>
Description:
The /sys/power/pm_print_times file allows user space to
control whether the time taken by devices to suspend and
resume is printed. These prints are useful for hunting down
devices that take too long to suspend or resume.
Writing a "1" enables this printing while writing a "0"
disables it. The default value is "0". Reading from this file
will display the current value.

View File

@ -583,9 +583,10 @@ for the given device during all power transitions, instead of the respective
subsystem-level callbacks. Specifically, if a device's pm_domain pointer is
not NULL, the ->suspend() callback from the object pointed to by it will be
executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
anlogously for all of the remaining callbacks. In other words, power management
domain callbacks, if defined for the given device, always take precedence over
the callbacks provided by the device's subsystem (e.g. bus type).
analogously for all of the remaining callbacks. In other words, power
management domain callbacks, if defined for the given device, always take
precedence over the callbacks provided by the device's subsystem (e.g. bus
type).
The support for device power management domains is only relevant to platforms
needing to use the same device driver power management callbacks in many
@ -598,7 +599,7 @@ it into account in any way.
Device Low Power (suspend) States
---------------------------------
Device low-power states aren't standard. One device might only handle
"on" and "off, while another might support a dozen different versions of
"on" and "off", while another might support a dozen different versions of
"on" (how many engines are active?), plus a state that gets back to "on"
faster than from a full "off".

View File

@ -33,6 +33,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
echo platform > /sys/power/disk; echo disk > /sys/power/state
. If you would like to write hibernation image to swap and then suspend
to RAM (provided your platform supports it), you can try
echo suspend > /sys/power/disk; echo disk > /sys/power/state
. If you have SATA disks, you'll need recent kernels with SATA suspend
support. For suspend and resume to work, make sure your disk drivers
are built into kernel -- not modules. [There's way to make

View File

@ -203,7 +203,7 @@ static int xo15_sci_remove(struct acpi_device *device, int type)
return 0;
}
static int xo15_sci_resume(struct acpi_device *device)
static int xo15_sci_resume(struct device *dev)
{
/* Enable all EC events */
olpc_ec_mask_write(EC_SCI_SRC_ALL);
@ -215,6 +215,8 @@ static int xo15_sci_resume(struct acpi_device *device)
return 0;
}
static SIMPLE_DEV_PM_OPS(xo15_sci_pm, NULL, xo15_sci_resume);
static const struct acpi_device_id xo15_sci_device_ids[] = {
{"XO15EC", 0},
{"", 0},
@ -227,8 +229,8 @@ static struct acpi_driver xo15_sci_drv = {
.ops = {
.add = xo15_sci_add,
.remove = xo15_sci_remove,
.resume = xo15_sci_resume,
},
.drv.pm = &xo15_sci_pm,
};
static int __init xo15_sci_init(void)

View File

@ -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 {
@ -309,13 +311,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;

View File

@ -1044,17 +1044,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,
@ -1062,10 +1069,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)

View File

@ -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)

View File

@ -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");

View File

@ -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,
};
/*
@ -771,14 +773,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;

View File

@ -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,18 +429,11 @@ 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);

View File

@ -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;
}

View File

@ -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)

View File

@ -290,26 +290,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);
@ -441,8 +421,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,

View File

@ -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 {
@ -1041,16 +1043,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]))

View File

@ -75,19 +75,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
start_latency_ns, "start");
}
static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
{
return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
save_state_latency_ns, "state save");
}
static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
{
return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
restore_state_latency_ns,
"state restore");
}
static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
{
bool ret = false;
@ -139,6 +126,19 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
genpd->status = GPD_STATE_ACTIVE;
}
static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd)
{
s64 usecs64;
if (!genpd->cpu_data)
return;
usecs64 = genpd->power_on_latency_ns;
do_div(usecs64, NSEC_PER_USEC);
usecs64 += genpd->cpu_data->saved_exit_latency;
genpd->cpu_data->idle_state->exit_latency = usecs64;
}
/**
* __pm_genpd_poweron - Restore power to a given PM domain and its masters.
* @genpd: PM domain to power up.
@ -146,7 +146,7 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
* Restore power to @genpd and all of its masters so that it is possible to
* resume a device belonging to it.
*/
int __pm_genpd_poweron(struct generic_pm_domain *genpd)
static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
__releases(&genpd->lock) __acquires(&genpd->lock)
{
struct gpd_link *link;
@ -176,6 +176,13 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
return 0;
}
if (genpd->cpu_data) {
cpuidle_pause_and_lock();
genpd->cpu_data->idle_state->disabled = true;
cpuidle_resume_and_unlock();
goto out;
}
/*
* The list is guaranteed not to change while the loop below is being
* executed, unless one of the masters' .power_on() callbacks fiddles
@ -215,6 +222,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
if (elapsed_ns > genpd->power_on_latency_ns) {
genpd->power_on_latency_ns = elapsed_ns;
genpd->max_off_time_changed = true;
genpd_recalc_cpu_exit_latency(genpd);
if (genpd->name)
pr_warning("%s: Power-on latency exceeded, "
"new value %lld ns\n", genpd->name,
@ -222,6 +230,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
}
}
out:
genpd_set_active(genpd);
return 0;
@ -251,6 +260,19 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
#ifdef CONFIG_PM_RUNTIME
static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
{
return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
save_state_latency_ns, "state save");
}
static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
{
return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
restore_state_latency_ns,
"state restore");
}
static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
unsigned long val, void *ptr)
{
@ -275,7 +297,7 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
pdd = dev->power.subsys_data ?
dev->power.subsys_data->domain_data : NULL;
if (pdd) {
if (pdd && pdd->dev) {
to_gpd_data(pdd)->td.constraint_changed = true;
genpd = dev_to_genpd(dev);
} else {
@ -339,19 +361,16 @@ static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
{
struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
struct device *dev = pdd->dev;
bool need_restore = gpd_data->need_restore;
if (!gpd_data->need_restore)
return;
gpd_data->need_restore = false;
mutex_unlock(&genpd->lock);
genpd_start_dev(genpd, dev);
genpd_restore_dev(genpd, dev);
genpd_stop_dev(genpd, dev);
if (need_restore)
genpd_restore_dev(genpd, dev);
mutex_lock(&genpd->lock);
gpd_data->need_restore = false;
}
/**
@ -458,6 +477,21 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
}
}
if (genpd->cpu_data) {
/*
* If cpu_data is set, cpuidle should turn the domain off when
* the CPU in it is idle. In that case we don't decrement the
* subdomain counts of the master domains, so that power is not
* removed from the current domain prematurely as a result of
* cutting off the masters' power.
*/
genpd->status = GPD_STATE_POWER_OFF;
cpuidle_pause_and_lock();
genpd->cpu_data->idle_state->disabled = false;
cpuidle_resume_and_unlock();
goto out;
}
if (genpd->power_off) {
ktime_t time_start;
s64 elapsed_ns;
@ -595,7 +629,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
/* If power.irq_safe, the PM domain is never powered off. */
if (dev->power.irq_safe)
goto out;
return genpd_start_dev(genpd, dev);
mutex_lock(&genpd->lock);
ret = __pm_genpd_poweron(genpd);
@ -628,9 +662,6 @@ static int pm_genpd_runtime_resume(struct device *dev)
wake_up_all(&genpd->status_wait_queue);
mutex_unlock(&genpd->lock);
out:
genpd_start_dev(genpd, dev);
return 0;
}
@ -1235,6 +1266,27 @@ static void pm_genpd_complete(struct device *dev)
#endif /* CONFIG_PM_SLEEP */
static struct generic_pm_domain_data *__pm_genpd_alloc_dev_data(struct device *dev)
{
struct generic_pm_domain_data *gpd_data;
gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
if (!gpd_data)
return NULL;
mutex_init(&gpd_data->lock);
gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
dev_pm_qos_add_notifier(dev, &gpd_data->nb);
return gpd_data;
}
static void __pm_genpd_free_dev_data(struct device *dev,
struct generic_pm_domain_data *gpd_data)
{
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
kfree(gpd_data);
}
/**
* __pm_genpd_add_device - Add a device to an I/O PM domain.
* @genpd: PM domain to add the device to.
@ -1244,7 +1296,7 @@ static void pm_genpd_complete(struct device *dev)
int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
struct gpd_timing_data *td)
{
struct generic_pm_domain_data *gpd_data;
struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
struct pm_domain_data *pdd;
int ret = 0;
@ -1253,14 +1305,10 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
return -EINVAL;
gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
if (!gpd_data)
gpd_data_new = __pm_genpd_alloc_dev_data(dev);
if (!gpd_data_new)
return -ENOMEM;
mutex_init(&gpd_data->lock);
gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
dev_pm_qos_add_notifier(dev, &gpd_data->nb);
genpd_acquire_lock(genpd);
if (genpd->prepared_count > 0) {
@ -1274,35 +1322,42 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
goto out;
}
ret = dev_pm_get_subsys_data(dev);
if (ret)
goto out;
genpd->device_count++;
genpd->max_off_time_changed = true;
dev_pm_get_subsys_data(dev);
mutex_lock(&gpd_data->lock);
spin_lock_irq(&dev->power.lock);
dev->pm_domain = &genpd->domain;
dev->power.subsys_data->domain_data = &gpd_data->base;
gpd_data->base.dev = dev;
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
if (dev->power.subsys_data->domain_data) {
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
} else {
gpd_data = gpd_data_new;
dev->power.subsys_data->domain_data = &gpd_data->base;
}
gpd_data->refcount++;
if (td)
gpd_data->td = *td;
spin_unlock_irq(&dev->power.lock);
mutex_lock(&gpd_data->lock);
gpd_data->base.dev = dev;
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
gpd_data->td.constraint_changed = true;
gpd_data->td.effective_constraint_ns = -1;
spin_unlock_irq(&dev->power.lock);
mutex_unlock(&gpd_data->lock);
genpd_release_lock(genpd);
return 0;
out:
genpd_release_lock(genpd);
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
kfree(gpd_data);
if (gpd_data != gpd_data_new)
__pm_genpd_free_dev_data(dev, gpd_data_new);
return ret;
}
@ -1348,6 +1403,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
{
struct generic_pm_domain_data *gpd_data;
struct pm_domain_data *pdd;
bool remove = false;
int ret = 0;
dev_dbg(dev, "%s()\n", __func__);
@ -1368,22 +1424,28 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
genpd->max_off_time_changed = true;
spin_lock_irq(&dev->power.lock);
dev->pm_domain = NULL;
pdd = dev->power.subsys_data->domain_data;
list_del_init(&pdd->list_node);
dev->power.subsys_data->domain_data = NULL;
gpd_data = to_gpd_data(pdd);
if (--gpd_data->refcount == 0) {
dev->power.subsys_data->domain_data = NULL;
remove = true;
}
spin_unlock_irq(&dev->power.lock);
gpd_data = to_gpd_data(pdd);
mutex_lock(&gpd_data->lock);
pdd->dev = NULL;
mutex_unlock(&gpd_data->lock);
genpd_release_lock(genpd);
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
kfree(gpd_data);
dev_pm_put_subsys_data(dev);
if (remove)
__pm_genpd_free_dev_data(dev, gpd_data);
return 0;
out:
@ -1541,33 +1603,52 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
* @dev: Device to add the callbacks to.
* @ops: Set of callbacks to add.
* @td: Timing data to add to the device along with the callbacks (optional).
*
* Every call to this routine should be balanced with a call to
* __pm_genpd_remove_callbacks() and they must not be nested.
*/
int pm_genpd_add_callbacks(struct device *dev, struct gpd_dev_ops *ops,
struct gpd_timing_data *td)
{
struct pm_domain_data *pdd;
struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
int ret = 0;
if (!(dev && dev->power.subsys_data && ops))
if (!(dev && ops))
return -EINVAL;
gpd_data_new = __pm_genpd_alloc_dev_data(dev);
if (!gpd_data_new)
return -ENOMEM;
pm_runtime_disable(dev);
device_pm_lock();
pdd = dev->power.subsys_data->domain_data;
if (pdd) {
struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
ret = dev_pm_get_subsys_data(dev);
if (ret)
goto out;
gpd_data->ops = *ops;
if (td)
gpd_data->td = *td;
spin_lock_irq(&dev->power.lock);
if (dev->power.subsys_data->domain_data) {
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
} else {
ret = -EINVAL;
gpd_data = gpd_data_new;
dev->power.subsys_data->domain_data = &gpd_data->base;
}
gpd_data->refcount++;
gpd_data->ops = *ops;
if (td)
gpd_data->td = *td;
spin_unlock_irq(&dev->power.lock);
out:
device_pm_unlock();
pm_runtime_enable(dev);
if (gpd_data != gpd_data_new)
__pm_genpd_free_dev_data(dev, gpd_data_new);
return ret;
}
EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
@ -1576,10 +1657,13 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
* __pm_genpd_remove_callbacks - Remove PM domain callbacks from a given device.
* @dev: Device to remove the callbacks from.
* @clear_td: If set, clear the device's timing data too.
*
* This routine can only be called after pm_genpd_add_callbacks().
*/
int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
{
struct pm_domain_data *pdd;
struct generic_pm_domain_data *gpd_data = NULL;
bool remove = false;
int ret = 0;
if (!(dev && dev->power.subsys_data))
@ -1588,24 +1672,118 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
pm_runtime_disable(dev);
device_pm_lock();
pdd = dev->power.subsys_data->domain_data;
if (pdd) {
struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
spin_lock_irq(&dev->power.lock);
gpd_data->ops = (struct gpd_dev_ops){ 0 };
if (dev->power.subsys_data->domain_data) {
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
gpd_data->ops = (struct gpd_dev_ops){ NULL };
if (clear_td)
gpd_data->td = (struct gpd_timing_data){ 0 };
if (--gpd_data->refcount == 0) {
dev->power.subsys_data->domain_data = NULL;
remove = true;
}
} else {
ret = -EINVAL;
}
spin_unlock_irq(&dev->power.lock);
device_pm_unlock();
pm_runtime_enable(dev);
return ret;
if (ret)
return ret;
dev_pm_put_subsys_data(dev);
if (remove)
__pm_genpd_free_dev_data(dev, gpd_data);
return 0;
}
EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
{
struct cpuidle_driver *cpuidle_drv;
struct gpd_cpu_data *cpu_data;
struct cpuidle_state *idle_state;
int ret = 0;
if (IS_ERR_OR_NULL(genpd) || state < 0)
return -EINVAL;
genpd_acquire_lock(genpd);
if (genpd->cpu_data) {
ret = -EEXIST;
goto out;
}
cpu_data = kzalloc(sizeof(*cpu_data), GFP_KERNEL);
if (!cpu_data) {
ret = -ENOMEM;
goto out;
}
cpuidle_drv = cpuidle_driver_ref();
if (!cpuidle_drv) {
ret = -ENODEV;
goto out;
}
if (cpuidle_drv->state_count <= state) {
ret = -EINVAL;
goto err;
}
idle_state = &cpuidle_drv->states[state];
if (!idle_state->disabled) {
ret = -EAGAIN;
goto err;
}
cpu_data->idle_state = idle_state;
cpu_data->saved_exit_latency = idle_state->exit_latency;
genpd->cpu_data = cpu_data;
genpd_recalc_cpu_exit_latency(genpd);
out:
genpd_release_lock(genpd);
return ret;
err:
cpuidle_driver_unref();
goto out;
}
int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
{
struct gpd_cpu_data *cpu_data;
struct cpuidle_state *idle_state;
int ret = 0;
if (IS_ERR_OR_NULL(genpd))
return -EINVAL;
genpd_acquire_lock(genpd);
cpu_data = genpd->cpu_data;
if (!cpu_data) {
ret = -ENODEV;
goto out;
}
idle_state = cpu_data->idle_state;
if (!idle_state->disabled) {
ret = -EAGAIN;
goto out;
}
idle_state->exit_latency = cpu_data->saved_exit_latency;
cpuidle_driver_unref();
genpd->cpu_data = NULL;
kfree(cpu_data);
out:
genpd_release_lock(genpd);
return ret;
}
/* Default device callbacks for generic PM domains. */
/**
@ -1615,16 +1793,24 @@ EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
static int pm_genpd_default_save_state(struct device *dev)
{
int (*cb)(struct device *__dev);
struct device_driver *drv = dev->driver;
cb = dev_gpd_data(dev)->ops.save_state;
if (cb)
return cb(dev);
if (drv && drv->pm && drv->pm->runtime_suspend)
return drv->pm->runtime_suspend(dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_suspend;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_suspend;
else
cb = NULL;
return 0;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_suspend;
return cb ? cb(dev) : 0;
}
/**
@ -1634,16 +1820,24 @@ static int pm_genpd_default_save_state(struct device *dev)
static int pm_genpd_default_restore_state(struct device *dev)
{
int (*cb)(struct device *__dev);
struct device_driver *drv = dev->driver;
cb = dev_gpd_data(dev)->ops.restore_state;
if (cb)
return cb(dev);
if (drv && drv->pm && drv->pm->runtime_resume)
return drv->pm->runtime_resume(dev);
if (dev->type && dev->type->pm)
cb = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
cb = dev->class->pm->runtime_resume;
else if (dev->bus && dev->bus->pm)
cb = dev->bus->pm->runtime_resume;
else
cb = NULL;
return 0;
if (!cb && dev->driver && dev->driver->pm)
cb = dev->driver->pm->runtime_resume;
return cb ? cb(dev) : 0;
}
#ifdef CONFIG_PM_SLEEP

View File

@ -28,7 +28,7 @@
#include <linux/sched.h>
#include <linux/async.h>
#include <linux/suspend.h>
#include <linux/cpuidle.h>
#include "../base.h"
#include "power.h"
@ -45,10 +45,10 @@ typedef int (*pm_callback_t)(struct device *);
*/
LIST_HEAD(dpm_list);
LIST_HEAD(dpm_prepared_list);
LIST_HEAD(dpm_suspended_list);
LIST_HEAD(dpm_late_early_list);
LIST_HEAD(dpm_noirq_list);
static LIST_HEAD(dpm_prepared_list);
static LIST_HEAD(dpm_suspended_list);
static LIST_HEAD(dpm_late_early_list);
static LIST_HEAD(dpm_noirq_list);
struct suspend_stats suspend_stats;
static DEFINE_MUTEX(dpm_list_mtx);
@ -166,7 +166,7 @@ static ktime_t initcall_debug_start(struct device *dev)
{
ktime_t calltime = ktime_set(0, 0);
if (initcall_debug) {
if (pm_print_times_enabled) {
pr_info("calling %s+ @ %i, parent: %s\n",
dev_name(dev), task_pid_nr(current),
dev->parent ? dev_name(dev->parent) : "none");
@ -181,7 +181,7 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
{
ktime_t delta, rettime;
if (initcall_debug) {
if (pm_print_times_enabled) {
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
@ -467,6 +467,7 @@ static void dpm_resume_noirq(pm_message_t state)
mutex_unlock(&dpm_list_mtx);
dpm_show_time(starttime, state, "noirq");
resume_device_irqs();
cpuidle_resume();
}
/**
@ -867,6 +868,7 @@ static int dpm_suspend_noirq(pm_message_t state)
ktime_t starttime = ktime_get();
int error = 0;
cpuidle_pause();
suspend_device_irqs();
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_late_early_list)) {
@ -989,8 +991,16 @@ static int dpm_suspend_late(pm_message_t state)
int dpm_suspend_end(pm_message_t state)
{
int error = dpm_suspend_late(state);
if (error)
return error;
return error ? : dpm_suspend_noirq(state);
error = dpm_suspend_noirq(state);
if (error) {
dpm_resume_early(state);
return error;
}
return 0;
}
EXPORT_SYMBOL_GPL(dpm_suspend_end);

View File

@ -462,7 +462,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
static void __dev_pm_qos_drop_user_request(struct device *dev)
{
dev_pm_qos_remove_request(dev->power.pq_req);
dev->power.pq_req = 0;
dev->power.pq_req = NULL;
}
/**

View File

@ -474,6 +474,8 @@ static DEVICE_ATTR(runtime_enabled, 0444, rtpm_enabled_show, NULL);
#endif
#ifdef CONFIG_PM_SLEEP
static ssize_t async_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@ -500,6 +502,8 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(async, 0644, async_show, async_store);
#endif
#endif /* CONFIG_PM_ADVANCED_DEBUG */
static struct attribute *power_attrs[] = {

View File

@ -780,9 +780,9 @@ static const struct block_device_operations mg_disk_ops = {
.getgeo = mg_getgeo
};
static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
static int mg_suspend(struct device *dev)
{
struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
struct mg_drv_data *prv_data = dev->platform_data;
struct mg_host *host = prv_data->host;
if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@ -804,9 +804,9 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
return 0;
}
static int mg_resume(struct platform_device *plat_dev)
static int mg_resume(struct device *dev)
{
struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
struct mg_drv_data *prv_data = dev->platform_data;
struct mg_host *host = prv_data->host;
if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@ -825,6 +825,8 @@ static int mg_resume(struct platform_device *plat_dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(mg_pm, mg_suspend, mg_resume);
static int mg_probe(struct platform_device *plat_dev)
{
struct mg_host *host;
@ -1074,11 +1076,10 @@ static int mg_remove(struct platform_device *plat_dev)
static struct platform_driver mg_disk_driver = {
.probe = mg_probe,
.remove = mg_remove,
.suspend = mg_suspend,
.resume = mg_resume,
.driver = {
.name = MG_DEV_NAME,
.owner = THIS_MODULE,
.pm = &mg_pm,
}
};

View File

@ -162,22 +162,24 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
static int omap_rng_suspend(struct device *dev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x0);
return 0;
}
static int omap_rng_resume(struct platform_device *pdev)
static int omap_rng_resume(struct device *dev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x1);
return 0;
}
static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
#define OMAP_RNG_PM (&omap_rng_pm)
#else
#define omap_rng_suspend NULL
#define omap_rng_resume NULL
#define OMAP_RNG_PM NULL
#endif
@ -188,11 +190,10 @@ static struct platform_driver omap_rng_driver = {
.driver = {
.name = "omap_rng",
.owner = THIS_MODULE,
.pm = OMAP_RNG_PM,
},
.probe = omap_rng_probe,
.remove = __exit_p(omap_rng_remove),
.suspend = omap_rng_suspend,
.resume = omap_rng_resume
};
static int __init omap_rng_init(void)

View File

@ -2503,18 +2503,6 @@ static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
cleanup_one_si(info);
}
#ifdef CONFIG_PM
static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
return 0;
}
static int ipmi_pci_resume(struct pci_dev *pdev)
{
return 0;
}
#endif
static struct pci_device_id ipmi_pci_devices[] = {
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
@ -2527,10 +2515,6 @@ static struct pci_driver ipmi_pci_driver = {
.id_table = ipmi_pci_devices,
.probe = ipmi_pci_probe,
.remove = __devexit_p(ipmi_pci_remove),
#ifdef CONFIG_PM
.suspend = ipmi_pci_suspend,
.resume = ipmi_pci_resume,
#endif
};
#endif /* CONFIG_PCI */

View File

@ -1459,7 +1459,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int old_camera_power;
static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
static int sonypi_suspend(struct device *dev)
{
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
@ -1467,14 +1467,16 @@ static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
return 0;
}
static int sonypi_resume(struct platform_device *dev)
static int sonypi_resume(struct device *dev)
{
sonypi_enable(old_camera_power);
return 0;
}
static SIMPLE_DEV_PM_OPS(sonypi_pm, sonypi_suspend, sonypi_resume);
#define SONYPI_PM (&sonypi_pm)
#else
#define sonypi_suspend NULL
#define sonypi_resume NULL
#define SONYPI_PM NULL
#endif
static void sonypi_shutdown(struct platform_device *dev)
@ -1486,12 +1488,11 @@ static struct platform_driver sonypi_driver = {
.driver = {
.name = "sonypi",
.owner = THIS_MODULE,
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
.remove = __devexit_p(sonypi_remove),
.shutdown = sonypi_shutdown,
.suspend = sonypi_suspend,
.resume = sonypi_resume,
};
static struct platform_device *sonypi_platform_device;

View File

@ -1274,7 +1274,7 @@ static struct tpm_input_header savestate_header = {
* We are about to suspend. Save the TPM state
* so that it can be restored.
*/
int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
int tpm_pm_suspend(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_cmd_t cmd;

View File

@ -299,7 +299,7 @@ extern ssize_t tpm_write(struct file *, const char __user *, size_t,
loff_t *);
extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *, pm_message_t);
extern int tpm_pm_suspend(struct device *);
extern int tpm_pm_resume(struct device *);
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *);

View File

@ -168,22 +168,14 @@ static void atml_plat_remove(void)
}
}
static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg)
{
return tpm_pm_suspend(&dev->dev, msg);
}
static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume);
static int tpm_atml_resume(struct platform_device *dev)
{
return tpm_pm_resume(&dev->dev);
}
static struct platform_driver atml_drv = {
.driver = {
.name = "tpm_atmel",
.owner = THIS_MODULE,
.pm = &tpm_atml_pm,
},
.suspend = tpm_atml_suspend,
.resume = tpm_atml_resume,
};
static int __init init_atmel(void)

View File

@ -274,22 +274,13 @@ static void tpm_nsc_remove(struct device *dev)
}
}
static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg)
{
return tpm_pm_suspend(&dev->dev, msg);
}
static int tpm_nsc_resume(struct platform_device *dev)
{
return tpm_pm_resume(&dev->dev);
}
static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume);
static struct platform_driver nsc_drv = {
.suspend = tpm_nsc_suspend,
.resume = tpm_nsc_resume,
.driver = {
.name = "tpm_nsc",
.owner = THIS_MODULE,
.pm = &tpm_nsc_pm,
},
};

View File

@ -750,7 +750,7 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
{
return tpm_pm_suspend(&dev->dev, msg);
return tpm_pm_suspend(&dev->dev);
}
static int tpm_tis_pnp_resume(struct pnp_dev *dev)
@ -806,27 +806,25 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
#endif
static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
{
return tpm_pm_suspend(&dev->dev, msg);
}
static int tpm_tis_resume(struct platform_device *dev)
static int tpm_tis_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
return tpm_pm_resume(&dev->dev);
return tpm_pm_resume(dev);
}
static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
static struct platform_driver tis_drv = {
.driver = {
.name = "tpm_tis",
.owner = THIS_MODULE,
.pm = &tpm_tis_pm,
},
.suspend = tpm_tis_suspend,
.resume = tpm_tis_resume,
};
static struct platform_device *pdev;

View File

@ -138,7 +138,7 @@ void disable_cpufreq(void)
static LIST_HEAD(cpufreq_governor_list);
static DEFINE_MUTEX(cpufreq_governor_mutex);
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
{
struct cpufreq_policy *data;
unsigned long flags;
@ -162,7 +162,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
if (!data)
goto err_out_put_module;
if (!kobject_get(&data->kobj))
if (!sysfs && !kobject_get(&data->kobj))
goto err_out_put_module;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@ -175,16 +175,35 @@ err_out_unlock:
err_out:
return NULL;
}
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{
return __cpufreq_cpu_get(cpu, false);
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
{
return __cpufreq_cpu_get(cpu, true);
}
static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
{
if (!sysfs)
kobject_put(&data->kobj);
module_put(cpufreq_driver->owner);
}
void cpufreq_cpu_put(struct cpufreq_policy *data)
{
kobject_put(&data->kobj);
module_put(cpufreq_driver->owner);
__cpufreq_cpu_put(data, false);
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
{
__cpufreq_cpu_put(data, true);
}
/*********************************************************************
* EXTERNALLY AFFECTING FREQUENCY CHANGES *
@ -617,7 +636,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
struct cpufreq_policy *policy = to_policy(kobj);
struct freq_attr *fattr = to_attr(attr);
ssize_t ret = -EINVAL;
policy = cpufreq_cpu_get(policy->cpu);
policy = cpufreq_cpu_get_sysfs(policy->cpu);
if (!policy)
goto no_policy;
@ -631,7 +650,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
unlock_policy_rwsem_read(policy->cpu);
fail:
cpufreq_cpu_put(policy);
cpufreq_cpu_put_sysfs(policy);
no_policy:
return ret;
}
@ -642,7 +661,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
struct cpufreq_policy *policy = to_policy(kobj);
struct freq_attr *fattr = to_attr(attr);
ssize_t ret = -EINVAL;
policy = cpufreq_cpu_get(policy->cpu);
policy = cpufreq_cpu_get_sysfs(policy->cpu);
if (!policy)
goto no_policy;
@ -656,7 +675,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
unlock_policy_rwsem_write(policy->cpu);
fail:
cpufreq_cpu_put(policy);
cpufreq_cpu_put_sysfs(policy);
no_policy:
return ret;
}

View File

@ -62,8 +62,18 @@ static int exynos_target(struct cpufreq_policy *policy,
goto out;
}
if (cpufreq_frequency_table_target(policy, freq_table,
freqs.old, relation, &old_index)) {
/*
* The policy max have been changed so that we cannot get proper
* old_index with cpufreq_frequency_table_target(). Thus, ignore
* policy and get the index from the raw freqeuncy table.
*/
for (old_index = 0;
freq_table[old_index].frequency != CPUFREQ_TABLE_END;
old_index++)
if (freq_table[old_index].frequency == freqs.old)
break;
if (freq_table[old_index].frequency == CPUFREQ_TABLE_END) {
ret = -EINVAL;
goto out;
}

View File

@ -201,6 +201,22 @@ void cpuidle_resume_and_unlock(void)
EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
/* Currently used in suspend/resume path to suspend cpuidle */
void cpuidle_pause(void)
{
mutex_lock(&cpuidle_lock);
cpuidle_uninstall_idle_handler();
mutex_unlock(&cpuidle_lock);
}
/* Currently used in suspend/resume path to resume cpuidle */
void cpuidle_resume(void)
{
mutex_lock(&cpuidle_lock);
cpuidle_install_idle_handler();
mutex_unlock(&cpuidle_lock);
}
/**
* cpuidle_wrap_enter - performs timekeeping and irqen around enter function
* @dev: pointer to a valid cpuidle_device object
@ -265,7 +281,7 @@ static void poll_idle_init(struct cpuidle_driver *drv)
state->power_usage = -1;
state->flags = 0;
state->enter = poll_idle;
state->disable = 0;
state->disabled = false;
}
#else
static void poll_idle_init(struct cpuidle_driver *drv) {}

View File

@ -16,6 +16,7 @@
static struct cpuidle_driver *cpuidle_curr_driver;
DEFINE_SPINLOCK(cpuidle_driver_lock);
int cpuidle_driver_refcount;
static void __cpuidle_register_driver(struct cpuidle_driver *drv)
{
@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
}
spin_lock(&cpuidle_driver_lock);
cpuidle_curr_driver = NULL;
if (!WARN_ON(cpuidle_driver_refcount > 0))
cpuidle_curr_driver = NULL;
spin_unlock(&cpuidle_driver_lock);
}
EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
struct cpuidle_driver *cpuidle_driver_ref(void)
{
struct cpuidle_driver *drv;
spin_lock(&cpuidle_driver_lock);
drv = cpuidle_curr_driver;
cpuidle_driver_refcount++;
spin_unlock(&cpuidle_driver_lock);
return drv;
}
void cpuidle_driver_unref(void)
{
spin_lock(&cpuidle_driver_lock);
if (!WARN_ON(cpuidle_driver_refcount <= 0))
cpuidle_driver_refcount--;
spin_unlock(&cpuidle_driver_lock);
}

View File

@ -281,7 +281,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
* unless the timer is happening really really soon.
*/
if (data->expected_us > 5 &&
drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0)
!drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
/*
@ -290,8 +291,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
*/
for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
struct cpuidle_state *s = &drv->states[i];
struct cpuidle_state_usage *su = &dev->states_usage[i];
if (s->disable)
if (s->disabled || su->disable)
continue;
if (s->target_residency > data->predicted_us)
continue;

View File

@ -217,7 +217,8 @@ struct cpuidle_state_attr {
struct attribute attr;
ssize_t (*show)(struct cpuidle_state *, \
struct cpuidle_state_usage *, char *);
ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
ssize_t (*store)(struct cpuidle_state *, \
struct cpuidle_state_usage *, const char *, size_t);
};
#define define_one_state_ro(_name, show) \
@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
return sprintf(buf, "%u\n", state->_name);\
}
#define define_store_state_function(_name) \
#define define_store_state_ull_function(_name) \
static ssize_t store_state_##_name(struct cpuidle_state *state, \
struct cpuidle_state_usage *state_usage, \
const char *buf, size_t size) \
{ \
long value; \
unsigned long long value; \
int err; \
if (!capable(CAP_SYS_ADMIN)) \
return -EPERM; \
err = kstrtol(buf, 0, &value); \
err = kstrtoull(buf, 0, &value); \
if (err) \
return err; \
if (value) \
state->disable = 1; \
state_usage->_name = 1; \
else \
state->disable = 0; \
state_usage->_name = 0; \
return size; \
}
@ -273,8 +275,8 @@ define_show_state_ull_function(usage)
define_show_state_ull_function(time)
define_show_state_str_function(name)
define_show_state_str_function(desc)
define_show_state_function(disable)
define_store_state_function(disable)
define_show_state_ull_function(disable)
define_store_state_ull_function(disable)
define_one_state_ro(name, show_state_name);
define_one_state_ro(desc, show_state_desc);
@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj,
{
int ret = -EIO;
struct cpuidle_state *state = kobj_to_state(kobj);
struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
if (cattr->store)
ret = cattr->store(state, buf, size);
ret = cattr->store(state, state_usage, buf, size);
return ret;
}

View File

@ -1661,27 +1661,26 @@ static void ux500_cryp_shutdown(struct platform_device *pdev)
}
static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
static int ux500_cryp_suspend(struct device *dev)
{
int ret;
struct platform_device *pdev = to_platform_device(dev);
struct cryp_device_data *device_data;
struct resource *res_irq;
struct cryp_ctx *temp_ctx = NULL;
dev_dbg(&pdev->dev, "[%s]", __func__);
dev_dbg(dev, "[%s]", __func__);
/* Handle state? */
device_data = platform_get_drvdata(pdev);
if (!device_data) {
dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
__func__);
dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
return -ENOMEM;
}
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res_irq)
dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
__func__);
dev_err(dev, "[%s]: IORESOURCE_IRQ, unavailable", __func__);
else
disable_irq(res_irq->start);
@ -1692,32 +1691,32 @@ static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
if (device_data->current_ctx == ++temp_ctx) {
if (down_interruptible(&driver_data.device_allocation))
dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
"failed", __func__);
ret = cryp_disable_power(&pdev->dev, device_data, false);
dev_dbg(dev, "[%s]: down_interruptible() failed",
__func__);
ret = cryp_disable_power(dev, device_data, false);
} else
ret = cryp_disable_power(&pdev->dev, device_data, true);
ret = cryp_disable_power(dev, device_data, true);
if (ret)
dev_err(&pdev->dev, "[%s]: cryp_disable_power()", __func__);
dev_err(dev, "[%s]: cryp_disable_power()", __func__);
return ret;
}
static int ux500_cryp_resume(struct platform_device *pdev)
static int ux500_cryp_resume(struct device *dev)
{
int ret = 0;
struct platform_device *pdev = to_platform_device(dev);
struct cryp_device_data *device_data;
struct resource *res_irq;
struct cryp_ctx *temp_ctx = NULL;
dev_dbg(&pdev->dev, "[%s]", __func__);
dev_dbg(dev, "[%s]", __func__);
device_data = platform_get_drvdata(pdev);
if (!device_data) {
dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
__func__);
dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
return -ENOMEM;
}
@ -1730,11 +1729,10 @@ static int ux500_cryp_resume(struct platform_device *pdev)
if (!device_data->current_ctx)
up(&driver_data.device_allocation);
else
ret = cryp_enable_power(&pdev->dev, device_data, true);
ret = cryp_enable_power(dev, device_data, true);
if (ret)
dev_err(&pdev->dev, "[%s]: cryp_enable_power() failed!",
__func__);
dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__);
else {
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res_irq)
@ -1744,15 +1742,16 @@ static int ux500_cryp_resume(struct platform_device *pdev)
return ret;
}
static SIMPLE_DEV_PM_OPS(ux500_cryp_pm, ux500_cryp_suspend, ux500_cryp_resume);
static struct platform_driver cryp_driver = {
.probe = ux500_cryp_probe,
.remove = ux500_cryp_remove,
.shutdown = ux500_cryp_shutdown,
.suspend = ux500_cryp_suspend,
.resume = ux500_cryp_resume,
.driver = {
.owner = THIS_MODULE,
.name = "cryp1"
.pm = &ux500_cryp_pm,
}
};

View File

@ -1894,19 +1894,17 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
/**
* ux500_hash_suspend - Function that suspends the hash device.
* @pdev: The platform device.
* @state: -
* @dev: Device to suspend.
*/
static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
static int ux500_hash_suspend(struct device *dev)
{
int ret;
struct hash_device_data *device_data;
struct hash_ctx *temp_ctx = NULL;
device_data = platform_get_drvdata(pdev);
device_data = dev_get_drvdata(dev);
if (!device_data) {
dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
__func__);
dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
return -ENOMEM;
}
@ -1917,33 +1915,32 @@ static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
if (device_data->current_ctx == ++temp_ctx) {
if (down_interruptible(&driver_data.device_allocation))
dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
"failed", __func__);
dev_dbg(dev, "[%s]: down_interruptible() failed",
__func__);
ret = hash_disable_power(device_data, false);
} else
ret = hash_disable_power(device_data, true);
if (ret)
dev_err(&pdev->dev, "[%s]: hash_disable_power()", __func__);
dev_err(dev, "[%s]: hash_disable_power()", __func__);
return ret;
}
/**
* ux500_hash_resume - Function that resume the hash device.
* @pdev: The platform device.
* @dev: Device to resume.
*/
static int ux500_hash_resume(struct platform_device *pdev)
static int ux500_hash_resume(struct device *dev)
{
int ret = 0;
struct hash_device_data *device_data;
struct hash_ctx *temp_ctx = NULL;
device_data = platform_get_drvdata(pdev);
device_data = dev_get_drvdata(dev);
if (!device_data) {
dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
__func__);
dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
return -ENOMEM;
}
@ -1958,21 +1955,21 @@ static int ux500_hash_resume(struct platform_device *pdev)
ret = hash_enable_power(device_data, true);
if (ret)
dev_err(&pdev->dev, "[%s]: hash_enable_power() failed!",
__func__);
dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
return ret;
}
static SIMPLE_DEV_PM_OPS(ux500_hash_pm, ux500_hash_suspend, ux500_hash_resume);
static struct platform_driver hash_driver = {
.probe = ux500_hash_probe,
.remove = ux500_hash_remove,
.shutdown = ux500_hash_shutdown,
.suspend = ux500_hash_suspend,
.resume = ux500_hash_resume,
.driver = {
.owner = THIS_MODULE,
.name = "hash1",
.pm = &ux500_hash_pm,
}
};

View File

@ -929,20 +929,25 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type)
return 0;
}
static int acpi_power_meter_resume(struct acpi_device *device)
static int acpi_power_meter_resume(struct device *dev)
{
struct acpi_power_meter_resource *resource;
if (!device || !acpi_driver_data(device))
if (!dev)
return -EINVAL;
resource = acpi_driver_data(to_acpi_device(dev));
if (!resource)
return -EINVAL;
resource = acpi_driver_data(device);
free_capabilities(resource);
read_capabilities(resource);
return 0;
}
static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);
static struct acpi_driver acpi_power_meter_driver = {
.name = "power_meter",
.class = ACPI_POWER_METER_CLASS,
@ -950,9 +955,9 @@ static struct acpi_driver acpi_power_meter_driver = {
.ops = {
.add = acpi_power_meter_add,
.remove = acpi_power_meter_remove,
.resume = acpi_power_meter_resume,
.notify = acpi_power_meter_notify,
},
.drv.pm = &acpi_power_meter_pm,
};
/* Module init/exit routines */

View File

@ -96,6 +96,7 @@ static const struct idle_cpu *icpu;
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
static int intel_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
static int intel_idle_cpu_init(int cpu);
static struct cpuidle_state *cpuidle_state_table;
@ -302,22 +303,35 @@ static void __setup_broadcast_timer(void *arg)
clockevents_notify(reason, &cpu);
}
static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
unsigned long action, void *hcpu)
static int cpu_hotplug_notify(struct notifier_block *n,
unsigned long action, void *hcpu)
{
int hotcpu = (unsigned long)hcpu;
struct cpuidle_device *dev;
switch (action & 0xf) {
case CPU_ONLINE:
smp_call_function_single(hotcpu, __setup_broadcast_timer,
(void *)true, 1);
if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
smp_call_function_single(hotcpu, __setup_broadcast_timer,
(void *)true, 1);
/*
* Some systems can hotplug a cpu at runtime after
* the kernel has booted, we have to initialize the
* driver in this case
*/
dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
if (!dev->registered)
intel_idle_cpu_init(hotcpu);
break;
}
return NOTIFY_OK;
}
static struct notifier_block setup_broadcast_notifier = {
.notifier_call = setup_broadcast_cpuhp_notify,
static struct notifier_block cpu_hotplug_notifier = {
.notifier_call = cpu_hotplug_notify,
};
static void auto_demotion_disable(void *dummy)
@ -405,10 +419,10 @@ static int intel_idle_probe(void)
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
else {
else
on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
register_cpu_notifier(&setup_broadcast_notifier);
}
register_cpu_notifier(&cpu_hotplug_notifier);
pr_debug(PREFIX "v" INTEL_IDLE_VERSION
" model 0x%X\n", boot_cpu_data.x86_model);
@ -494,7 +508,7 @@ static int intel_idle_cpuidle_driver_init(void)
* allocate, initialize, register cpuidle_devices
* @cpu: cpu/core to initialize
*/
int intel_idle_cpu_init(int cpu)
static int intel_idle_cpu_init(int cpu)
{
int cstate;
struct cpuidle_device *dev;
@ -539,7 +553,6 @@ int intel_idle_cpu_init(int cpu)
return 0;
}
EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
static int __init intel_idle_init(void)
{
@ -581,10 +594,10 @@ static void __exit intel_idle_exit(void)
intel_idle_cpuidle_devices_uninit();
cpuidle_unregister_driver(&intel_idle_driver);
if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
unregister_cpu_notifier(&setup_broadcast_notifier);
}
unregister_cpu_notifier(&cpu_hotplug_notifier);
return;
}

View File

@ -1877,8 +1877,7 @@ static int acer_platform_remove(struct platform_device *device)
return 0;
}
static int acer_platform_suspend(struct platform_device *dev,
pm_message_t state)
static int acer_suspend(struct device *dev)
{
u32 value;
struct acer_data *data = &interface->data;
@ -1900,7 +1899,7 @@ pm_message_t state)
return 0;
}
static int acer_platform_resume(struct platform_device *device)
static int acer_resume(struct device *dev)
{
struct acer_data *data = &interface->data;
@ -1916,6 +1915,8 @@ static int acer_platform_resume(struct platform_device *device)
return 0;
}
static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
static void acer_platform_shutdown(struct platform_device *device)
{
struct acer_data *data = &interface->data;
@ -1931,11 +1932,10 @@ static struct platform_driver acer_platform_driver = {
.driver = {
.name = "acer-wmi",
.owner = THIS_MODULE,
.pm = &acer_pm,
},
.probe = acer_platform_probe,
.remove = acer_platform_remove,
.suspend = acer_platform_suspend,
.resume = acer_platform_resume,
.shutdown = acer_platform_shutdown,
};

View File

@ -362,15 +362,18 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
return cmpc_remove_acpi_notify_device(acpi);
}
static int cmpc_tablet_resume(struct acpi_device *acpi)
static int cmpc_tablet_resume(struct device *dev)
{
struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
struct input_dev *inputdev = dev_get_drvdata(dev);
unsigned long long val = 0;
if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val)))
input_report_switch(inputdev, SW_TABLET_MODE, !val);
return 0;
}
static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume);
static const struct acpi_device_id cmpc_tablet_device_ids[] = {
{CMPC_TABLET_HID, 0},
{"", 0}
@ -384,9 +387,9 @@ static struct acpi_driver cmpc_tablet_acpi_driver = {
.ops = {
.add = cmpc_tablet_add,
.remove = cmpc_tablet_remove,
.resume = cmpc_tablet_resume,
.notify = cmpc_tablet_handler,
}
},
.drv.pm = &cmpc_tablet_pm,
};

View File

@ -440,12 +440,14 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type)
return 0;
}
static int acpi_fujitsu_resume(struct acpi_device *adev)
static int acpi_fujitsu_resume(struct device *dev)
{
fujitsu_reset();
return 0;
}
static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume);
static struct acpi_driver acpi_fujitsu_driver = {
.name = MODULENAME,
.class = "hotkey",
@ -453,8 +455,8 @@ static struct acpi_driver acpi_fujitsu_driver = {
.ops = {
.add = acpi_fujitsu_add,
.remove = acpi_fujitsu_remove,
.resume = acpi_fujitsu_resume,
}
},
.drv.pm = &acpi_fujitsu_pm,
};
static int __init fujitsu_module_init(void)

View File

@ -305,17 +305,19 @@ static int hdaps_probe(struct platform_device *dev)
return 0;
}
static int hdaps_resume(struct platform_device *dev)
static int hdaps_resume(struct device *dev)
{
return hdaps_device_init();
}
static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume);
static struct platform_driver hdaps_driver = {
.probe = hdaps_probe,
.resume = hdaps_resume,
.driver = {
.name = "hdaps",
.owner = THIS_MODULE,
.pm = &hdaps_pm,
},
};

View File

@ -353,20 +353,22 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
#ifdef CONFIG_PM
static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
static int lis3lv02d_suspend(struct device *dev)
{
/* make sure the device is off when we suspend */
lis3lv02d_poweroff(&lis3_dev);
return 0;
}
static int lis3lv02d_resume(struct acpi_device *device)
static int lis3lv02d_resume(struct device *dev)
{
return lis3lv02d_poweron(&lis3_dev);
}
static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
#define HP_ACCEL_PM (&hp_accel_pm)
#else
#define lis3lv02d_suspend NULL
#define lis3lv02d_resume NULL
#define HP_ACCEL_PM NULL
#endif
/* For the HP MDPS aka 3D Driveguard */
@ -377,9 +379,8 @@ static struct acpi_driver lis3lv02d_driver = {
.ops = {
.add = lis3lv02d_add,
.remove = lis3lv02d_remove,
.suspend = lis3lv02d_suspend,
.resume = lis3lv02d_resume,
}
},
.drv.pm = HP_ACCEL_PM,
};
static int __init lis3lv02d_init_module(void)

View File

@ -1719,21 +1719,6 @@ static void ips_remove(struct pci_dev *dev)
dev_dbg(&dev->dev, "IPS driver removed\n");
}
#ifdef CONFIG_PM
static int ips_suspend(struct pci_dev *dev, pm_message_t state)
{
return 0;
}
static int ips_resume(struct pci_dev *dev)
{
return 0;
}
#else
#define ips_suspend NULL
#define ips_resume NULL
#endif /* CONFIG_PM */
static void ips_shutdown(struct pci_dev *dev)
{
}
@ -1743,8 +1728,6 @@ static struct pci_driver ips_pci_driver = {
.id_table = ips_id_table,
.probe = ips_probe,
.remove = ips_remove,
.suspend = ips_suspend,
.resume = ips_resume,
.shutdown = ips_shutdown,
};

View File

@ -418,23 +418,23 @@ static struct thermal_device_info *initialize_sensor(int index)
/**
* mid_thermal_resume - resume routine
* @pdev: platform device structure
* @dev: device structure
*
* mid thermal resume: re-initializes the adc. Can sleep.
*/
static int mid_thermal_resume(struct platform_device *pdev)
static int mid_thermal_resume(struct device *dev)
{
return mid_initialize_adc(&pdev->dev);
return mid_initialize_adc(dev);
}
/**
* mid_thermal_suspend - suspend routine
* @pdev: platform device structure
* @dev: device structure
*
* mid thermal suspend implements the suspend functionality
* by stopping the ADC. Can sleep.
*/
static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
static int mid_thermal_suspend(struct device *dev)
{
/*
* This just stops the ADC and does not disable it.
@ -444,6 +444,9 @@ static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
return configure_adc(0);
}
static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
mid_thermal_suspend, mid_thermal_resume);
/**
* read_curr_temp - reads the current temperature and stores in temp
* @temp: holds the current temperature value after reading
@ -557,10 +560,9 @@ static struct platform_driver mid_thermal_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.pm = &mid_thermal_pm,
},
.probe = mid_thermal_probe,
.suspend = mid_thermal_suspend,
.resume = mid_thermal_resume,
.remove = __devexit_p(mid_thermal_remove),
.id_table = therm_id_table,
};

View File

@ -85,7 +85,8 @@
#define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4
#define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4)
static int msi_laptop_resume(struct platform_device *device);
static int msi_laptop_resume(struct device *device);
static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume);
#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
@ -437,8 +438,8 @@ static struct platform_driver msipf_driver = {
.driver = {
.name = "msi-laptop-pf",
.owner = THIS_MODULE,
.pm = &msi_laptop_pm,
},
.resume = msi_laptop_resume,
};
static struct platform_device *msipf_device;
@ -752,7 +753,7 @@ err_bluetooth:
return retval;
}
static int msi_laptop_resume(struct platform_device *device)
static int msi_laptop_resume(struct device *device)
{
u8 data;
int result;

View File

@ -177,7 +177,6 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
static int acpi_pcc_hotkey_add(struct acpi_device *device);
static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
static int acpi_pcc_hotkey_resume(struct acpi_device *device);
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
static const struct acpi_device_id pcc_device_ids[] = {
@ -189,6 +188,9 @@ static const struct acpi_device_id pcc_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
static int acpi_pcc_hotkey_resume(struct device *dev);
static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
static struct acpi_driver acpi_pcc_driver = {
.name = ACPI_PCC_DRIVER_NAME,
.class = ACPI_PCC_CLASS,
@ -196,9 +198,9 @@ static struct acpi_driver acpi_pcc_driver = {
.ops = {
.add = acpi_pcc_hotkey_add,
.remove = acpi_pcc_hotkey_remove,
.resume = acpi_pcc_hotkey_resume,
.notify = acpi_pcc_hotkey_notify,
},
.drv.pm = &acpi_pcc_hotkey_pm,
};
static const struct key_entry panasonic_keymap[] = {
@ -538,11 +540,15 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
/* kernel module interface */
static int acpi_pcc_hotkey_resume(struct acpi_device *device)
static int acpi_pcc_hotkey_resume(struct device *dev)
{
struct pcc_acpi *pcc = acpi_driver_data(device);
struct pcc_acpi *pcc;
if (device == NULL || pcc == NULL)
if (!dev)
return -EINVAL;
pcc = acpi_driver_data(to_acpi_device(dev));
if (!pcc)
return -EINVAL;
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",

View File

@ -1477,7 +1477,7 @@ static void sony_nc_function_resume(void)
&result);
}
static int sony_nc_resume(struct acpi_device *device)
static int sony_nc_resume(struct device *dev)
{
struct sony_nc_value *item;
acpi_handle handle;
@ -1509,6 +1509,8 @@ static int sony_nc_resume(struct acpi_device *device)
return 0;
}
static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
static void sony_nc_rfkill_cleanup(void)
{
int i;
@ -2770,9 +2772,9 @@ static struct acpi_driver sony_nc_driver = {
.ops = {
.add = sony_nc_add,
.remove = sony_nc_remove,
.resume = sony_nc_resume,
.notify = sony_nc_notify,
},
.drv.pm = &sony_nc_pm,
};
/*********** SPIC (SNY6001) Device ***********/
@ -4285,19 +4287,22 @@ err_free_resources:
return result;
}
static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
static int sony_pic_suspend(struct device *dev)
{
if (sony_pic_disable(device))
if (sony_pic_disable(to_acpi_device(dev)))
return -ENXIO;
return 0;
}
static int sony_pic_resume(struct acpi_device *device)
static int sony_pic_resume(struct device *dev)
{
sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
sony_pic_enable(to_acpi_device(dev),
spic_dev.cur_ioport, spic_dev.cur_irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
static const struct acpi_device_id sony_pic_device_ids[] = {
{SONY_PIC_HID, 0},
{"", 0},
@ -4311,9 +4316,8 @@ static struct acpi_driver sony_pic_driver = {
.ops = {
.add = sony_pic_add,
.remove = sony_pic_remove,
.suspend = sony_pic_suspend,
.resume = sony_pic_resume,
},
.drv.pm = &sony_pic_pm,
};
static struct dmi_system_id __initdata sonypi_dmi_table[] = {

View File

@ -277,7 +277,7 @@ struct ibm_struct {
int (*write) (char *);
void (*exit) (void);
void (*resume) (void);
void (*suspend) (pm_message_t state);
void (*suspend) (void);
void (*shutdown) (void);
struct list_head all_drivers;
@ -922,8 +922,7 @@ static struct input_dev *tpacpi_inputdev;
static struct mutex tpacpi_inputdev_send_mutex;
static LIST_HEAD(tpacpi_all_drivers);
static int tpacpi_suspend_handler(struct platform_device *pdev,
pm_message_t state)
static int tpacpi_suspend_handler(struct device *dev)
{
struct ibm_struct *ibm, *itmp;
@ -931,13 +930,13 @@ static int tpacpi_suspend_handler(struct platform_device *pdev,
&tpacpi_all_drivers,
all_drivers) {
if (ibm->suspend)
(ibm->suspend)(state);
(ibm->suspend)();
}
return 0;
}
static int tpacpi_resume_handler(struct platform_device *pdev)
static int tpacpi_resume_handler(struct device *dev)
{
struct ibm_struct *ibm, *itmp;
@ -951,6 +950,9 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
return 0;
}
static SIMPLE_DEV_PM_OPS(tpacpi_pm,
tpacpi_suspend_handler, tpacpi_resume_handler);
static void tpacpi_shutdown_handler(struct platform_device *pdev)
{
struct ibm_struct *ibm, *itmp;
@ -967,9 +969,8 @@ static struct platform_driver tpacpi_pdriver = {
.driver = {
.name = TPACPI_DRVR_NAME,
.owner = THIS_MODULE,
.pm = &tpacpi_pm,
},
.suspend = tpacpi_suspend_handler,
.resume = tpacpi_resume_handler,
.shutdown = tpacpi_shutdown_handler,
};
@ -3758,7 +3759,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
}
}
static void hotkey_suspend(pm_message_t state)
static void hotkey_suspend(void)
{
/* Do these on suspend, we get the events on early resume! */
hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
@ -6329,7 +6330,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
return 0;
}
static void brightness_suspend(pm_message_t state)
static void brightness_suspend(void)
{
tpacpi_brightness_checkpoint_nvram();
}
@ -6748,7 +6749,7 @@ static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
.get = volume_alsa_mute_get,
};
static void volume_suspend(pm_message_t state)
static void volume_suspend(void)
{
tpacpi_volume_checkpoint_nvram();
}
@ -8107,7 +8108,7 @@ static void fan_exit(void)
flush_workqueue(tpacpi_wq);
}
static void fan_suspend(pm_message_t state)
static void fan_suspend(void)
{
int rc;

View File

@ -1296,10 +1296,9 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
}
}
static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
pm_message_t state)
static int toshiba_acpi_suspend(struct device *device)
{
struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
u32 result;
if (dev->hotkey_dev)
@ -1308,9 +1307,9 @@ static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
return 0;
}
static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
static int toshiba_acpi_resume(struct device *device)
{
struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
u32 result;
if (dev->hotkey_dev)
@ -1319,6 +1318,9 @@ static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,
toshiba_acpi_suspend, toshiba_acpi_resume);
static struct acpi_driver toshiba_acpi_driver = {
.name = "Toshiba ACPI driver",
.owner = THIS_MODULE,
@ -1328,9 +1330,8 @@ static struct acpi_driver toshiba_acpi_driver = {
.add = toshiba_acpi_add,
.remove = toshiba_acpi_remove,
.notify = toshiba_acpi_notify,
.suspend = toshiba_acpi_suspend,
.resume = toshiba_acpi_resume,
},
.drv.pm = &toshiba_acpi_pm,
};
static int __init toshiba_acpi_init(void)

View File

@ -34,7 +34,6 @@ MODULE_LICENSE("GPL");
static int toshiba_bt_rfkill_add(struct acpi_device *device);
static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
static int toshiba_bt_resume(struct acpi_device *device);
static const struct acpi_device_id bt_device_ids[] = {
{ "TOS6205", 0},
@ -42,6 +41,9 @@ static const struct acpi_device_id bt_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, bt_device_ids);
static int toshiba_bt_resume(struct device *dev);
static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
static struct acpi_driver toshiba_bt_rfkill_driver = {
.name = "Toshiba BT",
.class = "Toshiba",
@ -50,9 +52,9 @@ static struct acpi_driver toshiba_bt_rfkill_driver = {
.add = toshiba_bt_rfkill_add,
.remove = toshiba_bt_rfkill_remove,
.notify = toshiba_bt_rfkill_notify,
.resume = toshiba_bt_resume,
},
.owner = THIS_MODULE,
.drv.pm = &toshiba_bt_pm,
};
@ -88,9 +90,9 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
toshiba_bluetooth_enable(device->handle);
}
static int toshiba_bt_resume(struct acpi_device *device)
static int toshiba_bt_resume(struct device *dev)
{
return toshiba_bluetooth_enable(device->handle);
return toshiba_bluetooth_enable(to_acpi_device(dev)->handle);
}
static int toshiba_bt_rfkill_add(struct acpi_device *device)

View File

@ -77,11 +77,13 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event)
}
}
static int ebook_switch_resume(struct acpi_device *device)
static int ebook_switch_resume(struct device *dev)
{
return ebook_send_state(device);
return ebook_send_state(to_acpi_device(dev));
}
static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume);
static int ebook_switch_add(struct acpi_device *device)
{
struct ebook_switch *button;
@ -161,10 +163,10 @@ static struct acpi_driver xo15_ebook_driver = {
.ids = ebook_device_ids,
.ops = {
.add = ebook_switch_add,
.resume = ebook_switch_resume,
.remove = ebook_switch_remove,
.notify = ebook_switch_notify,
},
.drv.pm = &ebook_switch_pm,
};
static int __init xo15_ebook_init(void)

View File

@ -568,6 +568,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
hpet_mask_rtc_irq_bit(RTC_AIE);
CMOS_READ(RTC_INTR_FLAGS);
pm_wakeup_event(cmos_rtc.dev, 0);
}
spin_unlock(&rtc_lock);

View File

@ -117,9 +117,6 @@ struct acpi_device;
typedef int (*acpi_op_add) (struct acpi_device * device);
typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
typedef int (*acpi_op_start) (struct acpi_device * device);
typedef int (*acpi_op_suspend) (struct acpi_device * device,
pm_message_t state);
typedef int (*acpi_op_resume) (struct acpi_device * device);
typedef int (*acpi_op_bind) (struct acpi_device * device);
typedef int (*acpi_op_unbind) (struct acpi_device * device);
typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
@ -133,8 +130,6 @@ struct acpi_device_ops {
acpi_op_add add;
acpi_op_remove remove;
acpi_op_start start;
acpi_op_suspend suspend;
acpi_op_resume resume;
acpi_op_bind bind;
acpi_op_unbind unbind;
acpi_op_notify notify;

View File

@ -59,10 +59,7 @@ struct acpi_processor_cx {
u8 entry_method;
u8 index;
u32 latency;
u32 latency_ticks;
u32 power;
u32 usage;
u64 time;
u8 bm_sts_skip;
char desc[ACPI_CX_DESC_LEN];
};
@ -334,8 +331,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr);
int acpi_processor_hotplug(struct acpi_processor *pr);
int acpi_processor_power_exit(struct acpi_processor *pr,
struct acpi_device *device);
int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
int acpi_processor_resume(struct acpi_device * device);
int acpi_processor_suspend(struct device *dev);
int acpi_processor_resume(struct device *dev);
extern struct cpuidle_driver acpi_idle_driver;
/* in processor_thermal.c */

View File

@ -34,6 +34,7 @@ struct cpuidle_driver;
struct cpuidle_state_usage {
void *driver_data;
unsigned long long disable;
unsigned long long usage;
unsigned long long time; /* in US */
};
@ -46,7 +47,7 @@ struct cpuidle_state {
unsigned int exit_latency; /* in US */
int power_usage; /* in mW */
unsigned int target_residency; /* in US */
unsigned int disable;
bool disabled; /* disabled on all CPUs */
int (*enter) (struct cpuidle_device *dev,
struct cpuidle_driver *drv,
@ -136,13 +137,17 @@ struct cpuidle_driver {
extern void disable_cpuidle(void);
extern int cpuidle_idle_call(void);
extern int cpuidle_register_driver(struct cpuidle_driver *drv);
struct cpuidle_driver *cpuidle_get_driver(void);
extern struct cpuidle_driver *cpuidle_get_driver(void);
extern struct cpuidle_driver *cpuidle_driver_ref(void);
extern void cpuidle_driver_unref(void);
extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
extern int cpuidle_register_device(struct cpuidle_device *dev);
extern void cpuidle_unregister_device(struct cpuidle_device *dev);
extern void cpuidle_pause_and_lock(void);
extern void cpuidle_resume_and_unlock(void);
extern void cpuidle_pause(void);
extern void cpuidle_resume(void);
extern int cpuidle_enable_device(struct cpuidle_device *dev);
extern void cpuidle_disable_device(struct cpuidle_device *dev);
extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
@ -157,6 +162,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; }
static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
{return -ENODEV; }
static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
static inline void cpuidle_driver_unref(void) {}
static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
static inline int cpuidle_register_device(struct cpuidle_device *dev)
{return -ENODEV; }
@ -164,6 +171,8 @@ static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
static inline void cpuidle_pause_and_lock(void) { }
static inline void cpuidle_resume_and_unlock(void) { }
static inline void cpuidle_pause(void) { }
static inline void cpuidle_resume(void) { }
static inline int cpuidle_enable_device(struct cpuidle_device *dev)
{return -ENODEV; }
static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
@ -202,14 +211,7 @@ struct cpuidle_governor {
extern int cpuidle_register_governor(struct cpuidle_governor *gov);
extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
#ifdef CONFIG_INTEL_IDLE
extern int intel_idle_cpu_init(int cpu);
#else
static inline int intel_idle_cpu_init(int cpu) { return -1; }
#endif
#else
static inline int intel_idle_cpu_init(int cpu) { return -1; }
static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
{return 0;}

View File

@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/notifier.h>
#include <linux/cpuidle.h>
enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */
@ -45,6 +46,11 @@ struct gpd_dev_ops {
bool (*active_wakeup)(struct device *dev);
};
struct gpd_cpu_data {
unsigned int saved_exit_latency;
struct cpuidle_state *idle_state;
};
struct generic_pm_domain {
struct dev_pm_domain domain; /* PM domain operations */
struct list_head gpd_list_node; /* Node in the global PM domains list */
@ -75,6 +81,7 @@ struct generic_pm_domain {
bool max_off_time_changed;
bool cached_power_down_ok;
struct device_node *of_node; /* Node in device tree */
struct gpd_cpu_data *cpu_data;
};
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@ -105,6 +112,7 @@ struct generic_pm_domain_data {
struct gpd_timing_data td;
struct notifier_block nb;
struct mutex lock;
unsigned int refcount;
bool need_restore;
bool always_on;
};
@ -155,6 +163,8 @@ extern int pm_genpd_add_callbacks(struct device *dev,
struct gpd_dev_ops *ops,
struct gpd_timing_data *td);
extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td);
extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd);
extern void pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off);
@ -211,6 +221,14 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
{
return -ENOSYS;
}
static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
{
return -ENOSYS;
}
static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
{
return -ENOSYS;
}
static inline void pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off)
{

View File

@ -66,7 +66,7 @@ enum pm_qos_req_action {
static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
{
return req->dev != 0;
return req->dev != NULL;
}
int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,

View File

@ -408,6 +408,12 @@ static inline void unlock_system_sleep(void) {}
#endif /* !CONFIG_PM_SLEEP */
#ifdef CONFIG_PM_SLEEP_DEBUG
extern bool pm_print_times_enabled;
#else
#define pm_print_times_enabled (false)
#endif
#ifdef CONFIG_PM_AUTOSLEEP
/* kernel/power/autosleep.c */

View File

@ -175,7 +175,7 @@ config PM_TEST_SUSPEND
You probably want to have your system's RTC driver statically
linked, ensuring that it's available when this test runs.
config CAN_PM_TRACE
config PM_SLEEP_DEBUG
def_bool y
depends on PM_DEBUG && PM_SLEEP
@ -196,7 +196,7 @@ config PM_TRACE
config PM_TRACE_RTC
bool "Suspend/resume event tracing"
depends on CAN_PM_TRACE
depends on PM_SLEEP_DEBUG
depends on X86
select PM_TRACE
---help---

View File

@ -5,6 +5,7 @@
* Copyright (c) 2003 Open Source Development Lab
* Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
* Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
* Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
*
* This file is released under the GPLv2.
*/
@ -45,6 +46,9 @@ enum {
HIBERNATION_PLATFORM,
HIBERNATION_SHUTDOWN,
HIBERNATION_REBOOT,
#ifdef CONFIG_SUSPEND
HIBERNATION_SUSPEND,
#endif
/* keep last */
__HIBERNATION_AFTER_LAST
};
@ -353,6 +357,7 @@ int hibernation_snapshot(int platform_mode)
}
suspend_console();
ftrace_stop();
pm_restrict_gfp_mask();
error = dpm_suspend(PMSG_FREEZE);
@ -378,6 +383,7 @@ int hibernation_snapshot(int platform_mode)
if (error || !in_suspend)
pm_restore_gfp_mask();
ftrace_start();
resume_console();
dpm_complete(msg);
@ -480,6 +486,7 @@ int hibernation_restore(int platform_mode)
pm_prepare_console();
suspend_console();
ftrace_stop();
pm_restrict_gfp_mask();
error = dpm_suspend_start(PMSG_QUIESCE);
if (!error) {
@ -487,6 +494,7 @@ int hibernation_restore(int platform_mode)
dpm_resume_end(PMSG_RECOVER);
}
pm_restore_gfp_mask();
ftrace_start();
resume_console();
pm_restore_console();
return error;
@ -513,6 +521,7 @@ int hibernation_platform_enter(void)
entering_platform_hibernation = true;
suspend_console();
ftrace_stop();
error = dpm_suspend_start(PMSG_HIBERNATE);
if (error) {
if (hibernation_ops->recover)
@ -556,6 +565,7 @@ int hibernation_platform_enter(void)
Resume_devices:
entering_platform_hibernation = false;
dpm_resume_end(PMSG_RESTORE);
ftrace_start();
resume_console();
Close:
@ -573,6 +583,10 @@ int hibernation_platform_enter(void)
*/
static void power_down(void)
{
#ifdef CONFIG_SUSPEND
int error;
#endif
switch (hibernation_mode) {
case HIBERNATION_REBOOT:
kernel_restart(NULL);
@ -582,6 +596,25 @@ static void power_down(void)
case HIBERNATION_SHUTDOWN:
kernel_power_off();
break;
#ifdef CONFIG_SUSPEND
case HIBERNATION_SUSPEND:
error = suspend_devices_and_enter(PM_SUSPEND_MEM);
if (error) {
if (hibernation_ops)
hibernation_mode = HIBERNATION_PLATFORM;
else
hibernation_mode = HIBERNATION_SHUTDOWN;
power_down();
}
/*
* Restore swap signature.
*/
error = swsusp_unmark();
if (error)
printk(KERN_ERR "PM: Swap will be unusable! "
"Try swapon -a.\n");
return;
#endif
}
kernel_halt();
/*
@ -819,6 +852,9 @@ static const char * const hibernation_modes[] = {
[HIBERNATION_PLATFORM] = "platform",
[HIBERNATION_SHUTDOWN] = "shutdown",
[HIBERNATION_REBOOT] = "reboot",
#ifdef CONFIG_SUSPEND
[HIBERNATION_SUSPEND] = "suspend",
#endif
};
/*
@ -859,6 +895,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
switch (i) {
case HIBERNATION_SHUTDOWN:
case HIBERNATION_REBOOT:
#ifdef CONFIG_SUSPEND
case HIBERNATION_SUSPEND:
#endif
break;
case HIBERNATION_PLATFORM:
if (hibernation_ops)
@ -899,6 +938,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
switch (mode) {
case HIBERNATION_SHUTDOWN:
case HIBERNATION_REBOOT:
#ifdef CONFIG_SUSPEND
case HIBERNATION_SUSPEND:
#endif
hibernation_mode = mode;
break;
case HIBERNATION_PLATFORM:

View File

@ -235,6 +235,47 @@ late_initcall(pm_debugfs_init);
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_PM_SLEEP_DEBUG
/*
* pm_print_times: print time taken by devices to suspend and resume.
*
* show() returns whether printing of suspend and resume times is enabled.
* store() accepts 0 or 1. 0 disables printing and 1 enables it.
*/
bool pm_print_times_enabled;
static ssize_t pm_print_times_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", pm_print_times_enabled);
}
static ssize_t pm_print_times_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
unsigned long val;
if (kstrtoul(buf, 10, &val))
return -EINVAL;
if (val > 1)
return -EINVAL;
pm_print_times_enabled = !!val;
return n;
}
power_attr(pm_print_times);
static inline void pm_print_times_init(void)
{
pm_print_times_enabled = !!initcall_debug;
}
#else /* !CONFIG_PP_SLEEP_DEBUG */
static inline void pm_print_times_init(void) {}
#endif /* CONFIG_PM_SLEEP_DEBUG */
struct kobject *power_kobj;
/**
@ -531,6 +572,9 @@ static struct attribute * g[] = {
#ifdef CONFIG_PM_DEBUG
&pm_test_attr.attr,
#endif
#ifdef CONFIG_PM_SLEEP_DEBUG
&pm_print_times_attr.attr,
#endif
#endif
NULL,
};
@ -566,6 +610,7 @@ static int __init pm_init(void)
error = sysfs_create_group(power_kobj, &attr_group);
if (error)
return error;
pm_print_times_init();
return pm_autosleep_init();
}

View File

@ -156,6 +156,9 @@ extern void swsusp_free(void);
extern int swsusp_read(unsigned int *flags_p);
extern int swsusp_write(unsigned int flags);
extern void swsusp_close(fmode_t);
#ifdef CONFIG_SUSPEND
extern int swsusp_unmark(void);
#endif
/* kernel/power/block_io.c */
extern struct block_device *hib_resume_bdev;

View File

@ -24,6 +24,7 @@
#include <linux/export.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/ftrace.h>
#include <trace/events/power.h>
#include "power.h"
@ -212,6 +213,7 @@ int suspend_devices_and_enter(suspend_state_t state)
goto Close;
}
suspend_console();
ftrace_stop();
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
@ -231,6 +233,7 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start();
dpm_resume_end(PMSG_RESUME);
suspend_test_finish("resume devices");
ftrace_start();
resume_console();
Close:
if (suspend_ops->end)

View File

@ -448,9 +448,9 @@ static int save_image(struct swap_map_handle *handle,
struct timeval start;
struct timeval stop;
printk(KERN_INFO "PM: Saving image data pages (%u pages) ... ",
printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n",
nr_to_write);
m = nr_to_write / 100;
m = nr_to_write / 10;
if (!m)
m = 1;
nr_pages = 0;
@ -464,7 +464,8 @@ static int save_image(struct swap_map_handle *handle,
if (ret)
break;
if (!(nr_pages % m))
printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
printk(KERN_INFO "PM: Image saving progress: %3d%%\n",
nr_pages / m * 10);
nr_pages++;
}
err2 = hib_wait_on_bio_chain(&bio);
@ -472,9 +473,7 @@ static int save_image(struct swap_map_handle *handle,
if (!ret)
ret = err2;
if (!ret)
printk(KERN_CONT "\b\b\b\bdone\n");
else
printk(KERN_CONT "\n");
printk(KERN_INFO "PM: Image saving done.\n");
swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
return ret;
}
@ -668,9 +667,9 @@ static int save_image_lzo(struct swap_map_handle *handle,
printk(KERN_INFO
"PM: Using %u thread(s) for compression.\n"
"PM: Compressing and saving image data (%u pages) ... ",
"PM: Compressing and saving image data (%u pages)...\n",
nr_threads, nr_to_write);
m = nr_to_write / 100;
m = nr_to_write / 10;
if (!m)
m = 1;
nr_pages = 0;
@ -690,8 +689,10 @@ static int save_image_lzo(struct swap_map_handle *handle,
data_of(*snapshot), PAGE_SIZE);
if (!(nr_pages % m))
printk(KERN_CONT "\b\b\b\b%3d%%",
nr_pages / m);
printk(KERN_INFO
"PM: Image saving progress: "
"%3d%%\n",
nr_pages / m * 10);
nr_pages++;
}
if (!off)
@ -761,11 +762,8 @@ out_finish:
do_gettimeofday(&stop);
if (!ret)
ret = err2;
if (!ret) {
printk(KERN_CONT "\b\b\b\bdone\n");
} else {
printk(KERN_CONT "\n");
}
if (!ret)
printk(KERN_INFO "PM: Image saving done.\n");
swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
out_clean:
if (crc) {
@ -973,9 +971,9 @@ static int load_image(struct swap_map_handle *handle,
int err2;
unsigned nr_pages;
printk(KERN_INFO "PM: Loading image data pages (%u pages) ... ",
printk(KERN_INFO "PM: Loading image data pages (%u pages)...\n",
nr_to_read);
m = nr_to_read / 100;
m = nr_to_read / 10;
if (!m)
m = 1;
nr_pages = 0;
@ -993,7 +991,8 @@ static int load_image(struct swap_map_handle *handle,
if (ret)
break;
if (!(nr_pages % m))
printk("\b\b\b\b%3d%%", nr_pages / m);
printk(KERN_INFO "PM: Image loading progress: %3d%%\n",
nr_pages / m * 10);
nr_pages++;
}
err2 = hib_wait_on_bio_chain(&bio);
@ -1001,12 +1000,11 @@ static int load_image(struct swap_map_handle *handle,
if (!ret)
ret = err2;
if (!ret) {
printk("\b\b\b\bdone\n");
printk(KERN_INFO "PM: Image loading done.\n");
snapshot_write_finalize(snapshot);
if (!snapshot_image_loaded(snapshot))
ret = -ENODATA;
} else
printk("\n");
}
swsusp_show_speed(&start, &stop, nr_to_read, "Read");
return ret;
}
@ -1185,9 +1183,9 @@ static int load_image_lzo(struct swap_map_handle *handle,
printk(KERN_INFO
"PM: Using %u thread(s) for decompression.\n"
"PM: Loading and decompressing image data (%u pages) ... ",
"PM: Loading and decompressing image data (%u pages)...\n",
nr_threads, nr_to_read);
m = nr_to_read / 100;
m = nr_to_read / 10;
if (!m)
m = 1;
nr_pages = 0;
@ -1319,7 +1317,10 @@ static int load_image_lzo(struct swap_map_handle *handle,
data[thr].unc + off, PAGE_SIZE);
if (!(nr_pages % m))
printk("\b\b\b\b%3d%%", nr_pages / m);
printk(KERN_INFO
"PM: Image loading progress: "
"%3d%%\n",
nr_pages / m * 10);
nr_pages++;
ret = snapshot_write_next(snapshot);
@ -1344,7 +1345,7 @@ out_finish:
}
do_gettimeofday(&stop);
if (!ret) {
printk("\b\b\b\bdone\n");
printk(KERN_INFO "PM: Image loading done.\n");
snapshot_write_finalize(snapshot);
if (!snapshot_image_loaded(snapshot))
ret = -ENODATA;
@ -1357,8 +1358,7 @@ out_finish:
}
}
}
} else
printk("\n");
}
swsusp_show_speed(&start, &stop, nr_to_read, "Read");
out_clean:
for (i = 0; i < ring_size; i++)
@ -1472,6 +1472,34 @@ void swsusp_close(fmode_t mode)
blkdev_put(hib_resume_bdev, mode);
}
/**
* swsusp_unmark - Unmark swsusp signature in the resume device
*/
#ifdef CONFIG_SUSPEND
int swsusp_unmark(void)
{
int error;
hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) {
memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10);
error = hib_bio_write_page(swsusp_resume_block,
swsusp_header, NULL);
} else {
printk(KERN_ERR "PM: Cannot find swsusp signature!\n");
error = -ENODEV;
}
/*
* We just returned from suspend, we don't need the image any more.
*/
free_all_swap_pages(root_swap);
return error;
}
#endif
static int swsusp_header_init(void)
{
swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);

View File

@ -9,6 +9,7 @@
* manipulate wakelocks on Android.
*/
#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/err.h>
@ -188,6 +189,9 @@ int pm_wake_lock(const char *buf)
size_t len;
int ret = 0;
if (!capable(CAP_BLOCK_SUSPEND))
return -EPERM;
while (*str && !isspace(*str))
str++;
@ -231,6 +235,9 @@ int pm_wake_unlock(const char *buf)
size_t len;
int ret = 0;
if (!capable(CAP_BLOCK_SUSPEND))
return -EPERM;
len = strlen(buf);
if (!len)
return -EINVAL;