Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 254047
b: refs/heads/master
c: 804a007
h: refs/heads/master
i:
  254045: 6eb9890
  254043: 8102e3d
  254039: 5c4d5ee
  254031: cbd5140
  254015: 7e835bf
v: v3
  • Loading branch information
Linus Torvalds committed Jun 27, 2011
1 parent 3e8d699 commit a9be87c
Show file tree
Hide file tree
Showing 102 changed files with 880 additions and 733 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9403c9c598e91d473c0582066e47ed2289292e45
refs/heads/master: 804a007f5401f87fc6e7da1e8884dc32912e35d0
67 changes: 14 additions & 53 deletions trunk/Documentation/power/devices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions trunk/Documentation/power/runtime_pm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/mn10300/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions trunk/block/blk-throttle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand Down Expand Up @@ -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],
Expand Down
16 changes: 10 additions & 6 deletions trunk/block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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]);
Expand Down
79 changes: 45 additions & 34 deletions trunk/block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
* isn't in progress and won't happen until unblocked by
* disk_unblock_events(). Events blocking is counted and the actual
* unblocking happens after the matching number of unblocks are done.
*
* Note that this intentionally does not block event checking from
* disk_clear_events().
*
* CONTEXT:
* Might sleep.
*/
void disk_block_events(struct gendisk *disk)
{
struct disk_events *ev = disk->ev;
unsigned long flags;
bool cancel;

if (!ev)
return;

/*
* Outer mutex ensures that the first blocker completes canceling
* the event work before further blockers are allowed to finish.
*/
mutex_lock(&ev->block_mutex);

spin_lock_irqsave(&ev->lock, flags);
cancel = !ev->block++;
spin_unlock_irqrestore(&ev->lock, flags);

if (cancel) {
if (sync)
cancel_delayed_work_sync(&disk->ev->dwork);
else
cancel_delayed_work(&disk->ev->dwork);
}
if (cancel)
cancel_delayed_work_sync(&disk->ev->dwork);

mutex_unlock(&ev->block_mutex);
}

static void __disk_unblock_events(struct gendisk *disk, bool check_now)
Expand Down Expand Up @@ -1460,27 +1483,6 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
spin_unlock_irqrestore(&ev->lock, flags);
}

/**
* 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
* isn't in progress and won't happen until unblocked by
* disk_unblock_events(). Events blocking is counted and the actual
* unblocking happens after the matching number of unblocks are done.
*
* Note that this intentionally does not block event checking from
* disk_clear_events().
*
* CONTEXT:
* Might sleep.
*/
void disk_block_events(struct gendisk *disk)
{
if (disk->ev)
__disk_block_events(disk, true);
}

/**
* disk_unblock_events - unblock disk event checking
* @disk: disk to unblock events for
Expand Down Expand Up @@ -1508,10 +1510,18 @@ void disk_unblock_events(struct gendisk *disk)
*/
void disk_check_events(struct gendisk *disk)
{
if (disk->ev) {
__disk_block_events(disk, false);
__disk_unblock_events(disk, true);
struct disk_events *ev = disk->ev;
unsigned long flags;

if (!ev)
return;

spin_lock_irqsave(&ev->lock, flags);
if (!ev->block) {
cancel_delayed_work(&ev->dwork);
queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
}
spin_unlock_irqrestore(&ev->lock, flags);
}
EXPORT_SYMBOL_GPL(disk_check_events);

Expand Down Expand Up @@ -1546,7 +1556,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
spin_unlock_irq(&ev->lock);

/* uncondtionally schedule event check and wait for it to finish */
__disk_block_events(disk, true);
disk_block_events(disk);
queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
flush_delayed_work(&ev->dwork);
__disk_unblock_events(disk, false);
Expand Down Expand Up @@ -1664,7 +1674,7 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev,
if (intv < 0 && intv != -1)
return -EINVAL;

__disk_block_events(disk, true);
disk_block_events(disk);
disk->ev->poll_msecs = intv;
__disk_unblock_events(disk, true);

Expand Down Expand Up @@ -1750,6 +1760,7 @@ static void disk_add_events(struct gendisk *disk)
INIT_LIST_HEAD(&ev->node);
ev->disk = disk;
spin_lock_init(&ev->lock);
mutex_init(&ev->block_mutex);
ev->block = 1;
ev->poll_msecs = -1;
INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);
Expand All @@ -1770,7 +1781,7 @@ static void disk_del_events(struct gendisk *disk)
if (!disk->ev)
return;

__disk_block_events(disk, true);
disk_block_events(disk);

mutex_lock(&disk_events_mutex);
list_del_init(&disk->ev->node);
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4143,9 +4143,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
* Devices which choke on SETXFER. Applies only if both the
* device and controller are SATA.
*/
{ "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-216D", "1.08", ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVRTD08", NULL, ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },

/* End Marker */
{ }
Expand Down
6 changes: 6 additions & 0 deletions trunk/drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
*/
int ata_sas_port_start(struct ata_port *ap)
{
/*
* the port is marked as frozen at allocation time, but if we don't
* have new eh, we won't thaw it
*/
if (!ap->ops->error_handler)
ap->pflags &= ~ATA_PFLAG_FROZEN;
return 0;
}
EXPORT_SYMBOL_GPL(ata_sas_port_start);
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/ata/pata_marvell.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ static const struct pci_device_id marvell_pci_tbl[] = {
{ PCI_DEVICE(0x11AB, 0x6121), },
{ PCI_DEVICE(0x11AB, 0x6123), },
{ PCI_DEVICE(0x11AB, 0x6145), },
{ PCI_DEVICE(0x1B4B, 0x91A0), },
{ PCI_DEVICE(0x1B4B, 0x91A4), },

{ } /* terminate list */
};

Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/ata/sata_dwc_460ex.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ static void sata_dwc_tf_dump(struct ata_taskfile *tf)
/*
* Function: get_burst_length_encode
* arguments: datalength: length in bytes of data
* returns value to be programmed in register corrresponding to data length
* returns value to be programmed in register corresponding to data length
* This value is effectively the log(base 2) of the length
*/
static int get_burst_length_encode(int datalength)
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/base/power/clock_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,15 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
clknb = container_of(nb, struct pm_clk_notifier_block, nb);

switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
case BUS_NOTIFY_BIND_DRIVER:
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
enable_clock(dev, *con_id);
} else {
enable_clock(dev, NULL);
}
break;
case BUS_NOTIFY_DEL_DEVICE:
case BUS_NOTIFY_UNBOUND_DRIVER:
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
disable_clock(dev, *con_id);
Expand Down
Loading

0 comments on commit a9be87c

Please sign in to comment.