wake up notifications and suspend blocking (aka more wakelock stuff)]
Subsystems (4)
RFC 1/1 wake up notifications and suspend blocking (aka more wakelock stuff)]
Forwarding to bigger group for discussion.
----- Forwarded message from mark gross <[email protected]> -----
Subject: Re: [RFC] wake up notifications and suspend blocking (aka more wakelock stuff)
Date: Tue, 20 Sep 2011 13:36:15 -0700
From: mark gross <[email protected]>
To: mark gross <[email protected]>
Reply-To: [email protected]
Cc: [email protected], [email protected], Alan Stern <[email protected]>, [email protected], [email protected], "Rafael J. Wysocki" <[email protected]>
Quoted 1 line
From
a2615c59cb3b7632cf22e2c25a10b401e2151bbfMon Sep 17 00:00:00 2001
From: mark gross <[email protected]>
Date: Mon, 19 Sep 2011 09:48:31 -0700
Subject: [PATCH 2/2] implement suspend bock pm_qos class such that whenever the
pm_qos_request is > 0 suspend to ram is blocked.
This is one of the 2 features the wakelock design attempts to implement. (the other is wake even notification consumption before re-entry into suspend)
--- drivers/base/power/wakeup.c | 5 +++-- include/linux/pm_qos_params.h | 4 +++- kernel/pm_qos_params.c | 14 +++++++++++++- kernel/power/suspend.c | 7 +++++++ 4 files changed, 26 insertions(+), 4 deletions(-)
drivers/base/power/wakeup.c +3 -2
@@ -10,8 +10,8 @@#include <linux/slab.h> #include <linux/sched.h> #include <linux/capability.h> -#include <linux/freezer.h> #include <linux/miscdevice.h> +#include <linux/pm_qos_params.h> #include <linux/suspend.h> #include <linux/seq_file.h> #include <linux/debugfs.h>
@@ -791,7 +791,8 @@ bool pm_get_wakeup_count(unsigned int *count)for (;;) {split_counters (&cnt, &inpr); -if (inpr ==0 ||signal_pending (current)) +if (((pm_qos_request (PM_QOS_SUSPEND_BLOCK ) <1 ) && (inpr ==0 )) + ||signal_pending (current))break ;pm_wakeup_update_hit_counts ();schedule_timeout_interruptible (msecs_to_jiffies (TIMEOUT ));
include/linux/pm_qos_params.h +3 -1
@@ -12,13 +12,15 @@#define PM_QOS_CPU_DMA_LATENCY 1#define PM_QOS_NETWORK_LATENCY 2#define PM_QOS_NETWORK_THROUGHPUT 3 +#define PM_QOS_SUSPEND_BLOCK 4 -#define PM_QOS_NUM_CLASSES 4 +#define PM_QOS_NUM_CLASSES 5#define PM_QOS_DEFAULT_VALUE -1#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 +#define PM_QOS_SUSPEND_BLOCK_DEFAULT_VALUE 0struct pm_qos_request_list {struct plist_node list;
kernel/pm_qos_params.c +13 -1
@@ -104,11 +104,23 @@ static struct pm_qos_object network_throughput_pm_qos = { }; +static BLOCKING_NOTIFIER_HEAD (suspend_block_notifier); +static struct pm_qos_object suspend_block_pm_qos = { + .requests =PLIST_HEAD_INIT (suspend_block_pm_qos.requests), + .notifiers = &suspend_block_notifier, + .name ="suspend_block" , + .target_value =PM_QOS_SUSPEND_BLOCK_DEFAULT_VALUE , + .default_value =PM_QOS_SUSPEND_BLOCK_DEFAULT_VALUE , + .type =PM_QOS_MAX , +}; + +static struct pm_qos_object *pm_qos_array[] = { &null_pm_qos, &cpu_dma_pm_qos, &network_lat_pm_qos, - &network_throughput_pm_qos + &network_throughput_pm_qos, + &suspend_block_pm_qos }; static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
kernel/power/suspend.c +7 -0
@@ -20,6 +20,7 @@#include <linux/kernel.h> #include <linux/list.h> #include <linux/mm.h> +#include <linux/pm_qos_params.h> #include <linux/slab.h> #include <linux/suspend.h> #include <linux/syscore_ops.h>
@@ -278,6 +279,12 @@ int enter_state(suspend_state_t state)if (!valid_state (state))return -ENODEV ; +if (state ==PM_SUSPEND_MEM ) +if (0 <pm_qos_request (PM_QOS_SUSPEND_BLOCK )) { +WARN (1 ,"suspend blocked by pm_qos" ); +return -EBUSY ; + } +if (!mutex_trylock (&pm_mutex))return -EBUSY ;
Signature · 4 lines
1.7.4.1 ----- End forwarded message -----
Quoted 1 line · On Sun, 2 Oct 2011 09:48:49 -0700 mark gross <[email protected]> wrote:
Forwarding to bigger group for discussion.
Looks clean enough - only question I have is do we need a separate 'suspend block' or can latency do it -suspend is a very very high latency event. I guess the suspend block is clearer in intent than abusing latency but I do wonder if the actual suspend path should also check latency constraints too. If I've asked for 5mS latency then suspend is a wrong choice!
Alan
Quoted 12 lines · Alan Cox
Quoted 1 line · On Sun, 2 Oct 2011 09:48:49 -0700 mark gross <[email protected]> wrote:
Forwarding to bigger group for discussion.
Looks clean enough - only question I have is do we need a separate 'suspend block' or can latency do it -suspend is a very very high latency event. I guess the suspend block is clearer in intent than abusing latency but I do wonder if the actual suspend path should also check latency constraints too. If I've asked for 5mS latency then suspend is a wrong choice!
I don't think over loading the meaning of cpu_dma_latency would work well for this. If cpu_dma_latency constraint is > 5mS then EFAIL a suspend attempt? feels clunky.
If you use less than then anyone using a constraint (like some wifi and audio) would block suspend. also not so good.
The poster child for needing this is the USB gadget device with associated charging over USB. Here we can't sleep because we'd have a hard time meeting USB spec if we did. Also, we don't want to sleep while charging if charging is under OS control. (checking temperature is tricky while suspended.)
--mark