diff options
101 files changed, 879 insertions, 732 deletions
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 88880839ece..64565aac6e4 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -520,59 +520,20 @@ Support for power domains is provided through the pwr_domain field of struct device. This field is a pointer to an object of type struct dev_power_domain, defined in include/linux/pm.h, providing a set of power management callbacks analogous to the subsystem-level and device driver callbacks that are executed -for the given device during all power transitions, in addition to the respective -subsystem-level callbacks. Specifically, the power domain "suspend" callbacks -(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are -executed after the analogous subsystem-level callbacks, while the power domain -"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore, -etc.) are executed before the analogous subsystem-level callbacks. Error codes -returned by the "suspend" and "resume" power domain callbacks are ignored. - -Power domain ->runtime_idle() callback is executed before the subsystem-level -->runtime_idle() callback and the result returned by it is not ignored. Namely, -if it returns error code, the subsystem-level ->runtime_idle() callback will not -be called and the helper function rpm_idle() executing it will return error -code. This mechanism is intended to help platforms where saving device state -is a time consuming operation and should only be carried out if all devices -in the power domain are idle, before turning off the shared power resource(s). -Namely, the power domain ->runtime_idle() callback may return error code until -the pm_runtime_idle() helper (or its asychronous version) has been called for -all devices in the power domain (it is recommended that the returned error code -be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle() -callback from being run prematurely. - -The support for device power domains is only relevant to platforms needing to -use the same subsystem-level (e.g. platform bus type) and device driver power -management callbacks in many different power domain configurations and wanting -to avoid incorporating the support for power domains into the subsystem-level -callbacks. The other platforms need not implement it or take it into account -in any way. - - -System Devices --------------- -System devices (sysdevs) follow a slightly different API, which can be found in - - include/linux/sysdev.h - drivers/base/sys.c - -System devices will be suspended with interrupts disabled, and after all other -devices have been suspended. On resume, they will be resumed before any other -devices, and also with interrupts disabled. These things occur in special -"sysdev_driver" phases, which affect only system devices. - -Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when -the non-boot CPUs are all offline and IRQs are disabled on the remaining online -CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a -sleep state (or a system image is created). During resume (or after the image -has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs -are enabled on the only online CPU, the non-boot CPUs are enabled, and the -resume_noirq (or thaw_noirq or restore_noirq) phase begins. - -Code to actually enter and exit the system-wide low power state sometimes -involves hardware details that are only known to the boot firmware, and -may leave a CPU running software (from SRAM or flash memory) that monitors -the system and manages its wakeup sequence. +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). + +The support for device power management domains is only relevant to platforms +needing to use the same device driver power management callbacks in many +different power domain configurations and wanting to avoid incorporating the +support for power domains into subsystem-level callbacks, for example by +modifying the platform bus type. Other platforms need not implement it or take +it into account in any way. Device Low Power (suspend) States diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 654097b130b..22accb3eb40 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -566,11 +566,6 @@ to do this is: pm_runtime_set_active(dev); pm_runtime_enable(dev); -The PM core always increments the run-time usage counter before calling the -->prepare() callback and decrements it after calling the ->complete() callback. -Hence disabling run-time PM temporarily like this will not cause any run-time -suspend callbacks to be lost. - 7. Generic subsystem callbacks Subsystems may wish to conserve code space by using the set of generic power diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 3d6e60dad9d..780560b330d 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h @@ -15,6 +15,7 @@ * User space memory access functions */ #include <linux/thread_info.h> +#include <linux/kernel.h> #include <asm/page.h> #include <asm/errno.h> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 0972315c386..68c3c139520 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -188,7 +188,7 @@ static bool resource_contains(struct resource *res, resource_size_t point) return false; } -static void coalesce_windows(struct pci_root_info *info, int type) +static void coalesce_windows(struct pci_root_info *info, unsigned long type) { int i, j; struct resource *res1, *res2; diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a62be8d0dc1..3689f833afd 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -927,7 +927,7 @@ static int throtl_dispatch(struct request_queue *q) bio_list_init(&bio_list_on_stack); - throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u", + throtl_log(td, "dispatch nr_queued=%d read=%u write=%u", total_nr_queued(td), td->nr_queued[READ], td->nr_queued[WRITE]); @@ -1204,7 +1204,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop) } queue_bio: - throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu" + throtl_log_tg(td, tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu" " iodisp=%u iops=%u queued=%d/%d", rw == READ ? 'R' : 'W', tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3c7b537bf90..f3799432676 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -988,9 +988,10 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, st->min_vdisktime); - cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u" - " sect=%u", used_sl, cfqq->slice_dispatch, charge, - iops_mode(cfqd), cfqq->nr_sectors); + cfq_log_cfqq(cfqq->cfqd, cfqq, + "sl_used=%u disp=%u charge=%u iops=%u sect=%lu", + used_sl, cfqq->slice_dispatch, charge, + iops_mode(cfqd), cfqq->nr_sectors); cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl, unaccounted_sl); cfq_blkiocg_set_start_empty_time(&cfqg->blkg); @@ -2023,8 +2024,8 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) */ if (sample_valid(cic->ttime_samples) && (cfqq->slice_end - jiffies < cic->ttime_mean)) { - cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%d", - cic->ttime_mean); + cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%lu", + cic->ttime_mean); return; } @@ -2772,8 +2773,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, smp_wmb(); cic->key = cfqd_dead_key(cfqd); - if (ioc->ioc_data == cic) + if (rcu_dereference(ioc->ioc_data) == cic) { + spin_lock(&ioc->lock); rcu_assign_pointer(ioc->ioc_data, NULL); + spin_unlock(&ioc->lock); + } if (cic->cfqq[BLK_RW_ASYNC]) { cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); diff --git a/block/genhd.c b/block/genhd.c index 95822ae25cf..3608289c8ec 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1371,6 +1371,7 @@ struct disk_events { struct gendisk *disk; /* the associated disk */ spinlock_t lock; + struct mutex block_mutex; /* protects blocking */ int block; /* event blocking depth */ unsigned int pending; /* events already sent out */ unsigned int clearing; /* events being cleared */ @@ -1414,22 +1415,44 @@ static unsigned long disk_events_poll_jiffies(struct gendisk *disk) return msecs_to_jiffies(intv_msecs); } -static void __disk_block_events(struct gendisk *disk, bool sync) +/** + * disk_block_events - block and flush disk event checking + * @disk: disk to block events for + * + * On return from this function, it is guaranteed that event checking |