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:
commit
7100e505b7
|
@ -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.
|
||||
|
|
|
@ -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".
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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---
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue