* [PATCH 0/2] PM / sleep: prohibit devices probing during suspend/hibernation
@ 2015-10-08 16:57 Grygorii Strashko
2015-10-08 16:57 ` [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe Grygorii Strashko
2015-10-08 16:57 ` [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
0 siblings, 2 replies; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-08 16:57 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Alan Stern
Cc: Pavel Machek, Len Brown, linux-kernel, linux-pm,
Grygorii Strashko, Thierry Reding
The main goal of this patchset is to ensure that devices probing will not
happen during system transition to low power states like suspend or
hibernation, because it is unsafe [1] and system behavior will be
unpredictable in this case (for example: after successful probe the device
potentially has a different set of PM callbacks than before [2]).
Tested on dra7-evm using a simple kernel module which only does
msleep(5000) in its probe.
Test cmd: insmod test_probe.ko & echo mem > sys/power/state
- suspend will wait for test_probe to finish
[1] https://lkml.org/lkml/2015/9/11/554
[2] https://lkml.org/lkml/2015/9/15/1039
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Thierry Reding <thierry.reding@gmail.com>
Grygorii Strashko (2):
PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
PM / sleep: prohibit devices probing during suspend/hibernation
drivers/base/base.h | 1 +
drivers/base/dd.c | 39 ++++++++++++++++++++++++++++++++++++++-
drivers/base/power/main.c | 13 +++++++++++++
3 files changed, 52 insertions(+), 1 deletion(-)
--
2.5.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-08 16:57 [PATCH 0/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
@ 2015-10-08 16:57 ` Grygorii Strashko
2015-10-08 20:50 ` Rafael J. Wysocki
2015-10-08 16:57 ` [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
1 sibling, 1 reply; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-08 16:57 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Alan Stern
Cc: Pavel Machek, Len Brown, linux-kernel, linux-pm,
Grygorii Strashko, Thierry Reding
Now wait_for_device_probe() waits for currently executing probes to finish,
but it doesn't take into account deferred probing mechanism. As result,
nothing prevents deferred probe workqueue to continue probing devices right
after wait_for_device_probe() is finished.
Hence, lest ensure deferred probe workqueue is finished in
wait_for_device_probe() before proceeding.
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/base/dd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index be0eb46..98de1a5 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -391,6 +391,10 @@ int driver_probe_done(void)
*/
void wait_for_device_probe(void)
{
+ /* wait for the deferred probe workqueue to finish */
+ if (driver_deferred_probe_enable)
+ flush_workqueue(deferred_wq);
+
/* wait for the known devices to complete their probing */
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
async_synchronize_full();
--
2.5.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 16:57 [PATCH 0/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
2015-10-08 16:57 ` [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe Grygorii Strashko
@ 2015-10-08 16:57 ` Grygorii Strashko
2015-10-08 17:24 ` Alan Stern
1 sibling, 1 reply; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-08 16:57 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Alan Stern
Cc: Pavel Machek, Len Brown, linux-kernel, linux-pm,
Grygorii Strashko, Thierry Reding
It is unsafe [1] if probing of devices will happen during suspend or
hibernation and system behavior will be unpredictable in this case.
So, lets prohibit device's probing in dpm_prepare() and defer their
probing instead. The normal behavior will be restored in
dpm_complete().
This patch introduces new DD core API device_defer_all_probes(bool enable)
to enable/disable probing of devices:
if @enable = true
It will disable probing of devices and defer their probes.
otherwise
It will restore normal behavior and trigger re-probing of deferred devices.
[1] https://lkml.org/lkml/2015/9/11/554
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
drivers/base/base.h | 1 +
drivers/base/dd.c | 35 ++++++++++++++++++++++++++++++++++-
drivers/base/power/main.c | 13 +++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 1782f3a..6c9684b 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -131,6 +131,7 @@ extern void device_remove_groups(struct device *dev,
extern char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev);
+extern void device_defer_all_probes(bool enable);
/* /sys/devices directory */
extern struct kset *devices_kset;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 98de1a5..d600c14 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -55,6 +55,13 @@ static struct workqueue_struct *deferred_wq;
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
/*
+ * In some cases, like suspend to RAM or hibernation, It might be reasonable
+ * to prohibit probing of devices as it could be unsafe.
+ * Once defer_all_probes is true all drivers probes will be forcibly deferred.
+ */
+static bool defer_all_probes;
+
+/*
* deferred_probe_work_func() - Retry probing devices in the active list.
*/
static void deferred_probe_work_func(struct work_struct *work)
@@ -172,6 +179,26 @@ static void driver_deferred_probe_trigger(void)
}
/**
+ * device_defer_all_probes() - Enable/disable probing of devices
+ * @enable: Enable/disable probing of devices
+ *
+ * if @enable = true
+ * It will disable probing of devices and defer their probes.
+ * otherwise
+ * It will restore normal behavior and trigger re-probing of deferred
+ * devices.
+ */
+void device_defer_all_probes(bool enable)
+{
+ defer_all_probes = enable;
+ if (enable)
+ /* sync with probes to avoid any races. */
+ wait_for_device_probe();
+ else
+ driver_deferred_probe_trigger();
+}
+
+/**
* deferred_probe_initcall() - Enable probing of deferred devices
*
* We don't want to get in the way when the bulk of drivers are getting probed.
@@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
static int really_probe(struct device *dev, struct device_driver *drv)
{
- int ret = 0;
+ int ret = -EPROBE_DEFER;
int local_trigger_count = atomic_read(&deferred_trigger_count);
+ if (defer_all_probes) {
+ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
+ driver_deferred_probe_add(dev);
+ return ret;
+ }
+
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 1710c26..98c1da36 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -963,6 +963,9 @@ void dpm_complete(pm_message_t state)
}
list_splice(&list, &dpm_list);
mutex_unlock(&dpm_list_mtx);
+
+ /* Allow device probing and trigger re-probing of deferred devices */
+ device_defer_all_probes(false);
trace_suspend_resume(TPS("dpm_complete"), state.event, false);
}
@@ -1624,6 +1627,16 @@ int dpm_prepare(pm_message_t state)
trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
might_sleep();
+ /* Give a chance for the known devices to complete their probing. */
+ wait_for_device_probe();
+ /*
+ * It is unsafe if probing of devices will happen during suspend or
+ * hibernation and system behavior will be unpredictable in this case.
+ * So, lets prohibit device's probing here and defer their probes
+ * instead. The normal behavior will be restored in dpm_complete().
+ */
+ device_defer_all_probes(true);
+
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.next);
--
2.5.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 16:57 ` [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
@ 2015-10-08 17:24 ` Alan Stern
2015-10-08 18:54 ` Grygorii Strashko
0 siblings, 1 reply; 15+ messages in thread
From: Alan Stern @ 2015-10-08 17:24 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Thu, 8 Oct 2015, Grygorii Strashko wrote:
> It is unsafe [1] if probing of devices will happen during suspend or
> hibernation and system behavior will be unpredictable in this case.
> So, lets prohibit device's probing in dpm_prepare() and defer their
s/lets/let's/, and same for the comment in the code.
> probing instead. The normal behavior will be restored in
> dpm_complete().
> @@ -172,6 +179,26 @@ static void driver_deferred_probe_trigger(void)
> }
>
> /**
> + * device_defer_all_probes() - Enable/disable probing of devices
> + * @enable: Enable/disable probing of devices
> + *
> + * if @enable = true
> + * It will disable probing of devices and defer their probes.
> + * otherwise
> + * It will restore normal behavior and trigger re-probing of deferred
> + * devices.
> + */
> +void device_defer_all_probes(bool enable)
> +{
> + defer_all_probes = enable;
> + if (enable)
> + /* sync with probes to avoid any races. */
> + wait_for_device_probe();
> + else
> + driver_deferred_probe_trigger();
> +}
Some people might prefer to see two separate functions, an enable
routine and a disable routine. I don't much care.
> @@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
>
> static int really_probe(struct device *dev, struct device_driver *drv)
> {
> - int ret = 0;
> + int ret = -EPROBE_DEFER;
> int local_trigger_count = atomic_read(&deferred_trigger_count);
>
> + if (defer_all_probes) {
> + dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
> + driver_deferred_probe_add(dev);
> + return ret;
> + }
In theory there's a race here. If one CPU sets defer_all_probes, the
new value might not be perceived by another CPU until a little while
later. Is there an easy way to insure that this race won't cause any
problems?
Or do we already know that when this mechanism gets used, the system is
already running on a single CPU? I forget when that happens.
> @@ -1624,6 +1627,16 @@ int dpm_prepare(pm_message_t state)
> trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
> might_sleep();
>
> + /* Give a chance for the known devices to complete their probing. */
> + wait_for_device_probe();
> + /*
> + * It is unsafe if probing of devices will happen during suspend or
> + * hibernation and system behavior will be unpredictable in this case.
> + * So, lets prohibit device's probing here and defer their probes
> + * instead. The normal behavior will be restored in dpm_complete().
> + */
> + device_defer_all_probes(true);
Don't you want to call these two functions in the opposite order?
First prevent new probes from occurring, then wait for any probes that
are already in progress? The way you have it here, a new probe could
start between these two lines.
Alan Stern
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 17:24 ` Alan Stern
@ 2015-10-08 18:54 ` Grygorii Strashko
2015-10-08 19:20 ` Alan Stern
0 siblings, 1 reply; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-08 18:54 UTC (permalink / raw)
To: Alan Stern
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On 10/08/2015 12:24 PM, Alan Stern wrote:
> On Thu, 8 Oct 2015, Grygorii Strashko wrote:
>
>> It is unsafe [1] if probing of devices will happen during suspend or
>> hibernation and system behavior will be unpredictable in this case.
>> So, lets prohibit device's probing in dpm_prepare() and defer their
>
> s/lets/let's/, and same for the comment in the code.
>
>> probing instead. The normal behavior will be restored in
>> dpm_complete().
>
>
>> @@ -172,6 +179,26 @@ static void driver_deferred_probe_trigger(void)
>> }
>>
>> /**
>> + * device_defer_all_probes() - Enable/disable probing of devices
>> + * @enable: Enable/disable probing of devices
>> + *
>> + * if @enable = true
>> + * It will disable probing of devices and defer their probes.
>> + * otherwise
>> + * It will restore normal behavior and trigger re-probing of deferred
>> + * devices.
>> + */
>> +void device_defer_all_probes(bool enable)
>> +{
>> + defer_all_probes = enable;
>> + if (enable)
>> + /* sync with probes to avoid any races. */
>> + wait_for_device_probe();
^ pls, pay attention on above code line
>> + else
>> + driver_deferred_probe_trigger();
>> +}
>
> Some people might prefer to see two separate functions, an enable
> routine and a disable routine. I don't much care.
May be. Should I change it?
>
>> @@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
>>
>> static int really_probe(struct device *dev, struct device_driver *drv)
>> {
>> - int ret = 0;
>> + int ret = -EPROBE_DEFER;
>> int local_trigger_count = atomic_read(&deferred_trigger_count);
>>
>> + if (defer_all_probes) {
>> + dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
>> + driver_deferred_probe_add(dev);
>> + return ret;
>> + }
>
> In theory there's a race here. If one CPU sets defer_all_probes, the
> new value might not be perceived by another CPU until a little while
> later. Is there an easy way to insure that this race won't cause any
> problems?
Yes. this question was raised by Rafael also [1].
>
> Or do we already know that when this mechanism gets used, the system is
> already running on a single CPU? I forget when that happens.
No. nonboot cpus are still on.
>
>> @@ -1624,6 +1627,16 @@ int dpm_prepare(pm_message_t state)
>> trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
>> might_sleep();
>>
>> + /* Give a chance for the known devices to complete their probing. */
>> + wait_for_device_probe();
^ this sync point is important at least at boot time + hibernation restore
>> + /*
>> + * It is unsafe if probing of devices will happen during suspend or
>> + * hibernation and system behavior will be unpredictable in this case.
>> + * So, lets prohibit device's probing here and defer their probes
>> + * instead. The normal behavior will be restored in dpm_complete().
>> + */
>> + device_defer_all_probes(true);
>
> Don't you want to call these two functions in the opposite order?
> First prevent new probes from occurring, then wait for any probes that
> are already in progress? The way you have it here, a new probe could
> start between these two lines.
No. Initially I did it as below:
wait_for_device_probe(); <- wait for active probes
device_defer_all_probes(true); <- prohibit probing
wait_for_device_probe(); <- sync again to avoid races
then I decided to move second wait_for_device_probe() call inside
device_defer_all_probes() because it's always required.
[1] https://lkml.org/lkml/2015/9/17/857
--
regards,
-grygorii
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 18:54 ` Grygorii Strashko
@ 2015-10-08 19:20 ` Alan Stern
2015-10-08 19:48 ` Grygorii Strashko
2015-10-08 20:46 ` Rafael J. Wysocki
0 siblings, 2 replies; 15+ messages in thread
From: Alan Stern @ 2015-10-08 19:20 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Thu, 8 Oct 2015, Grygorii Strashko wrote:
> >> /**
> >> + * device_defer_all_probes() - Enable/disable probing of devices
> >> + * @enable: Enable/disable probing of devices
> >> + *
> >> + * if @enable = true
> >> + * It will disable probing of devices and defer their probes.
> >> + * otherwise
> >> + * It will restore normal behavior and trigger re-probing of deferred
> >> + * devices.
> >> + */
> >> +void device_defer_all_probes(bool enable)
> >> +{
> >> + defer_all_probes = enable;
> >> + if (enable)
> >> + /* sync with probes to avoid any races. */
> >> + wait_for_device_probe();
>
> ^ pls, pay attention on above code line
>
> >> + else
> >> + driver_deferred_probe_trigger();
> >> +}
> >
> > Some people might prefer to see two separate functions, an enable
> > routine and a disable routine. I don't much care.
>
> May be. Should I change it?
It would then be more in line with functions like
pm_runtime_set_{active|suspended} or pm_runtime_[dont_]use_autosuspend.
> >> @@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
> >>
> >> static int really_probe(struct device *dev, struct device_driver *drv)
> >> {
> >> - int ret = 0;
> >> + int ret = -EPROBE_DEFER;
> >> int local_trigger_count = atomic_read(&deferred_trigger_count);
> >>
> >> + if (defer_all_probes) {
> >> + dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
> >> + driver_deferred_probe_add(dev);
> >> + return ret;
> >> + }
> >
> > In theory there's a race here. If one CPU sets defer_all_probes, the
> > new value might not be perceived by another CPU until a little while
> > later. Is there an easy way to insure that this race won't cause any
> > problems?
>
> Yes. this question was raised by Rafael also [1].
I see. Can you add a comment explaining all of this?
Alan Stern
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 19:20 ` Alan Stern
@ 2015-10-08 19:48 ` Grygorii Strashko
2015-10-08 20:05 ` Alan Stern
2015-10-08 20:46 ` Rafael J. Wysocki
1 sibling, 1 reply; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-08 19:48 UTC (permalink / raw)
To: Alan Stern
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On 10/08/2015 02:20 PM, Alan Stern wrote:
> On Thu, 8 Oct 2015, Grygorii Strashko wrote:
>
>>>> /**
>>>> + * device_defer_all_probes() - Enable/disable probing of devices
>>>> + * @enable: Enable/disable probing of devices
>>>> + *
>>>> + * if @enable = true
>>>> + * It will disable probing of devices and defer their probes.
>>>> + * otherwise
>>>> + * It will restore normal behavior and trigger re-probing of deferred
>>>> + * devices.
>>>> + */
>>>> +void device_defer_all_probes(bool enable)
>>>> +{
>>>> + defer_all_probes = enable;
>>>> + if (enable)
>>>> + /* sync with probes to avoid any races. */
>>>> + wait_for_device_probe();
>>
>> ^ pls, pay attention on above code line
>>
>>>> + else
>>>> + driver_deferred_probe_trigger();
>>>> +}
>>>
>>> Some people might prefer to see two separate functions, an enable
>>> routine and a disable routine. I don't much care.
>>
>> May be. Should I change it?
>
> It would then be more in line with functions like
> pm_runtime_set_{active|suspended} or pm_runtime_[dont_]use_autosuspend.
ok
>
>>>> @@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
>>>>
>>>> static int really_probe(struct device *dev, struct device_driver *drv)
>>>> {
>>>> - int ret = 0;
>>>> + int ret = -EPROBE_DEFER;
>>>> int local_trigger_count = atomic_read(&deferred_trigger_count);
>>>>
>>>> + if (defer_all_probes) {
Will it be ok If I add below comment here?
/*
* Value of defer_all_probes can be set only by
* device_defer_all_probes_enable() which, in turn, will call
* wait_for_device_probe() right after that to avoid any races.
*/
>>>> + dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
>>>> + driver_deferred_probe_add(dev);
>>>> + return ret;
>>>> + }
>>>
>>> In theory there's a race here. If one CPU sets defer_all_probes, the
>>> new value might not be perceived by another CPU until a little while
>>> later. Is there an easy way to insure that this race won't cause any
>>> problems?
>>
>> Yes. this question was raised by Rafael also [1].
>
> I see. Can you add a comment explaining all of this?
--
regards,
-grygorii
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 19:48 ` Grygorii Strashko
@ 2015-10-08 20:05 ` Alan Stern
0 siblings, 0 replies; 15+ messages in thread
From: Alan Stern @ 2015-10-08 20:05 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Thu, 8 Oct 2015, Grygorii Strashko wrote:
> >>>> @@ -277,9 +304,15 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
> >>>>
> >>>> static int really_probe(struct device *dev, struct device_driver *drv)
> >>>> {
> >>>> - int ret = 0;
> >>>> + int ret = -EPROBE_DEFER;
> >>>> int local_trigger_count = atomic_read(&deferred_trigger_count);
> >>>>
> >>>> + if (defer_all_probes) {
>
> Will it be ok If I add below comment here?
> /*
> * Value of defer_all_probes can be set only by
> * device_defer_all_probes_enable() which, in turn, will call
> * wait_for_device_probe() right after that to avoid any races.
> */
That will help. You could also add a comment where
wait_for_device_probe is called before device_defer_all_probes_enable,
explaining that is needed.
Alan Stern
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 19:20 ` Alan Stern
2015-10-08 19:48 ` Grygorii Strashko
@ 2015-10-08 20:46 ` Rafael J. Wysocki
2015-10-09 14:31 ` Grygorii Strashko
1 sibling, 1 reply; 15+ messages in thread
From: Rafael J. Wysocki @ 2015-10-08 20:46 UTC (permalink / raw)
To: Alan Stern, Grygorii Strashko
Cc: Greg Kroah-Hartman, Pavel Machek, Len Brown, linux-kernel,
linux-pm, Thierry Reding
On Thursday, October 08, 2015 03:20:08 PM Alan Stern wrote:
> On Thu, 8 Oct 2015, Grygorii Strashko wrote:
>
> > >> /**
> > >> + * device_defer_all_probes() - Enable/disable probing of devices
> > >> + * @enable: Enable/disable probing of devices
> > >> + *
> > >> + * if @enable = true
> > >> + * It will disable probing of devices and defer their probes.
> > >> + * otherwise
> > >> + * It will restore normal behavior and trigger re-probing of deferred
> > >> + * devices.
> > >> + */
> > >> +void device_defer_all_probes(bool enable)
> > >> +{
> > >> + defer_all_probes = enable;
> > >> + if (enable)
> > >> + /* sync with probes to avoid any races. */
> > >> + wait_for_device_probe();
> >
> > ^ pls, pay attention on above code line
> >
> > >> + else
> > >> + driver_deferred_probe_trigger();
> > >> +}
> > >
> > > Some people might prefer to see two separate functions, an enable
> > > routine and a disable routine. I don't much care.
> >
> > May be. Should I change it?
>
> It would then be more in line with functions like
> pm_runtime_set_{active|suspended} or pm_runtime_[dont_]use_autosuspend.
Also it would be cleaner code without conditionals:
enable:
defer_all_probes = true;
wait_for_device_probe();
disable:
defer_all_probes = false;
driver_deferred_probe_trigger();
Cleaner, no?
Thanks,
Rafael
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-08 16:57 ` [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe Grygorii Strashko
@ 2015-10-08 20:50 ` Rafael J. Wysocki
2015-10-08 20:53 ` Alan Stern
0 siblings, 1 reply; 15+ messages in thread
From: Rafael J. Wysocki @ 2015-10-08 20:50 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Greg Kroah-Hartman, Alan Stern, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Thursday, October 08, 2015 11:57:06 AM Grygorii Strashko wrote:
> Now wait_for_device_probe() waits for currently executing probes to finish,
> but it doesn't take into account deferred probing mechanism. As result,
> nothing prevents deferred probe workqueue to continue probing devices right
> after wait_for_device_probe() is finished.
>
> Hence, lest ensure deferred probe workqueue is finished in
s/lest/let's/
> wait_for_device_probe() before proceeding.
>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
> drivers/base/dd.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index be0eb46..98de1a5 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -391,6 +391,10 @@ int driver_probe_done(void)
> */
> void wait_for_device_probe(void)
> {
> + /* wait for the deferred probe workqueue to finish */
> + if (driver_deferred_probe_enable)
> + flush_workqueue(deferred_wq);
> +
> /* wait for the known devices to complete their probing */
> wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
> async_synchronize_full();
I'm not sure if this is sufficient.
Something may be added to the workqueue right after you've flushed it and
then be reporobed after the wait_event() in theory. Or am I missing anything?
Thanks,
Rafael
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-08 20:50 ` Rafael J. Wysocki
@ 2015-10-08 20:53 ` Alan Stern
2015-10-09 14:38 ` Grygorii Strashko
0 siblings, 1 reply; 15+ messages in thread
From: Alan Stern @ 2015-10-08 20:53 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Grygorii Strashko, Greg Kroah-Hartman, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Thu, 8 Oct 2015, Rafael J. Wysocki wrote:
> > @@ -391,6 +391,10 @@ int driver_probe_done(void)
> > */
> > void wait_for_device_probe(void)
> > {
> > + /* wait for the deferred probe workqueue to finish */
> > + if (driver_deferred_probe_enable)
> > + flush_workqueue(deferred_wq);
> > +
> > /* wait for the known devices to complete their probing */
> > wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
> > async_synchronize_full();
>
> I'm not sure if this is sufficient.
>
> Something may be added to the workqueue right after you've flushed it and
> then be reporobed after the wait_event() in theory. Or am I missing anything?
Maybe I'm missing part of this, but I think the point is to make sure
that every probe which began or was queued before this function got
called, has finished before the function returns.
Thus, in the case at hand we want to defer all probes starting from
some point in the system sleep transition. Grygorii sets his
defer_all_probes variable and then calls this function. It waits for
any probes that were initiated before the function call. Any probe
that was initiated after the function call (for example, the ones
you're concerned about between the flush_workqueue and wait_event) will
see that defer_all_probes is set and so will defer itself.
Now, I'm not sure what happens when a probe that was deferred tries to
defer itself again. Do we end up in an infinite probing loop? Is
the deferred_wq workqueue freezable?
Alan Stern
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation
2015-10-08 20:46 ` Rafael J. Wysocki
@ 2015-10-09 14:31 ` Grygorii Strashko
0 siblings, 0 replies; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-09 14:31 UTC (permalink / raw)
To: Rafael J. Wysocki, Alan Stern
Cc: Greg Kroah-Hartman, Pavel Machek, Len Brown, linux-kernel,
linux-pm, Thierry Reding
On 10/08/2015 03:46 PM, Rafael J. Wysocki wrote:
> On Thursday, October 08, 2015 03:20:08 PM Alan Stern wrote:
>> On Thu, 8 Oct 2015, Grygorii Strashko wrote:
>>
>>>>> /**
>>>>> + * device_defer_all_probes() - Enable/disable probing of devices
>>>>> + * @enable: Enable/disable probing of devices
>>>>> + *
>>>>> + * if @enable = true
>>>>> + * It will disable probing of devices and defer their probes.
>>>>> + * otherwise
>>>>> + * It will restore normal behavior and trigger re-probing of deferred
>>>>> + * devices.
>>>>> + */
>>>>> +void device_defer_all_probes(bool enable)
>>>>> +{
>>>>> + defer_all_probes = enable;
>>>>> + if (enable)
>>>>> + /* sync with probes to avoid any races. */
>>>>> + wait_for_device_probe();
>>>
>>> ^ pls, pay attention on above code line
>>>
>>>>> + else
>>>>> + driver_deferred_probe_trigger();
>>>>> +}
>>>>
>>>> Some people might prefer to see two separate functions, an enable
>>>> routine and a disable routine. I don't much care.
>>>
>>> May be. Should I change it?
>>
>> It would then be more in line with functions like
>> pm_runtime_set_{active|suspended} or pm_runtime_[dont_]use_autosuspend.
>
> Also it would be cleaner code without conditionals:
>
> enable:
> defer_all_probes = true;
> wait_for_device_probe();
>
> disable:
> defer_all_probes = false;
> driver_deferred_probe_trigger();
>
> Cleaner, no?
>
NP. Will do.
--
regards,
-grygorii
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-08 20:53 ` Alan Stern
@ 2015-10-09 14:38 ` Grygorii Strashko
2015-10-09 21:16 ` Rafael J. Wysocki
0 siblings, 1 reply; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-09 14:38 UTC (permalink / raw)
To: Alan Stern, Rafael J. Wysocki
Cc: Greg Kroah-Hartman, Pavel Machek, Len Brown, linux-kernel,
linux-pm, Thierry Reding
On 10/08/2015 03:53 PM, Alan Stern wrote:
> On Thu, 8 Oct 2015, Rafael J. Wysocki wrote:
>
>>> @@ -391,6 +391,10 @@ int driver_probe_done(void)
>>> */
>>> void wait_for_device_probe(void)
>>> {
>>> + /* wait for the deferred probe workqueue to finish */
>>> + if (driver_deferred_probe_enable)
>>> + flush_workqueue(deferred_wq);
>>> +
>>> /* wait for the known devices to complete their probing */
>>> wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
>>> async_synchronize_full();
>>
>> I'm not sure if this is sufficient.
>>
>> Something may be added to the workqueue right after you've flushed it and
>> then be reporobed after the wait_event() in theory. Or am I missing anything?
>
> Maybe I'm missing part of this, but I think the point is to make sure
> that every probe which began or was queued before this function got
> called, has finished before the function returns.
>
> Thus, in the case at hand we want to defer all probes starting from
> some point in the system sleep transition. Grygorii sets his
> defer_all_probes variable and then calls this function. It waits for
> any probes that were initiated before the function call. Any probe
> that was initiated after the function call (for example, the ones
> you're concerned about between the flush_workqueue and wait_event) will
> see that defer_all_probes is set and so will defer itself.
Yes. It will work as expected with the next patch.
For all other case, where this API is used alone -
it will make things more safe, but there is no way to completely block
scheduling of new probes.
>
> Now, I'm not sure what happens when a probe that was deferred tries to
> defer itself again. Do we end up in an infinite probing loop?
No. handling of defered probes will be re triggered only if
some probe was finished successfully.
> Is the deferred_wq workqueue freezable?
seems WQ_FREEZABLE is not set for this WQ.
--
regards,
-grygorii
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-09 14:38 ` Grygorii Strashko
@ 2015-10-09 21:16 ` Rafael J. Wysocki
2015-10-13 18:25 ` Grygorii Strashko
0 siblings, 1 reply; 15+ messages in thread
From: Rafael J. Wysocki @ 2015-10-09 21:16 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Alan Stern, Greg Kroah-Hartman, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On Friday, October 09, 2015 09:38:13 AM Grygorii Strashko wrote:
> On 10/08/2015 03:53 PM, Alan Stern wrote:
> > On Thu, 8 Oct 2015, Rafael J. Wysocki wrote:
> >
> >>> @@ -391,6 +391,10 @@ int driver_probe_done(void)
> >>> */
> >>> void wait_for_device_probe(void)
> >>> {
> >>> + /* wait for the deferred probe workqueue to finish */
> >>> + if (driver_deferred_probe_enable)
> >>> + flush_workqueue(deferred_wq);
> >>> +
> >>> /* wait for the known devices to complete their probing */
> >>> wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
> >>> async_synchronize_full();
> >>
> >> I'm not sure if this is sufficient.
> >>
> >> Something may be added to the workqueue right after you've flushed it and
> >> then be reporobed after the wait_event() in theory. Or am I missing anything?
> >
> > Maybe I'm missing part of this, but I think the point is to make sure
> > that every probe which began or was queued before this function got
> > called, has finished before the function returns.
> >
> > Thus, in the case at hand we want to defer all probes starting from
> > some point in the system sleep transition. Grygorii sets his
> > defer_all_probes variable and then calls this function. It waits for
> > any probes that were initiated before the function call. Any probe
> > that was initiated after the function call (for example, the ones
> > you're concerned about between the flush_workqueue and wait_event) will
> > see that defer_all_probes is set and so will defer itself.
>
> Yes. It will work as expected with the next patch.
> For all other case, where this API is used alone -
> it will make things more safe, but there is no way to completely block
> scheduling of new probes.
Well, in that case why don't you make it part of the second patch after all
instead of making a false impression of fixing a more general problem?
Thanks,
Rafael
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe
2015-10-09 21:16 ` Rafael J. Wysocki
@ 2015-10-13 18:25 ` Grygorii Strashko
0 siblings, 0 replies; 15+ messages in thread
From: Grygorii Strashko @ 2015-10-13 18:25 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Alan Stern, Greg Kroah-Hartman, Pavel Machek, Len Brown,
linux-kernel, linux-pm, Thierry Reding
On 10/10/2015 12:16 AM, Rafael J. Wysocki wrote:
> On Friday, October 09, 2015 09:38:13 AM Grygorii Strashko wrote:
>> On 10/08/2015 03:53 PM, Alan Stern wrote:
>>> On Thu, 8 Oct 2015, Rafael J. Wysocki wrote:
>>>
>>>>> @@ -391,6 +391,10 @@ int driver_probe_done(void)
>>>>> */
>>>>> void wait_for_device_probe(void)
>>>>> {
>>>>> + /* wait for the deferred probe workqueue to finish */
>>>>> + if (driver_deferred_probe_enable)
>>>>> + flush_workqueue(deferred_wq);
>>>>> +
>>>>> /* wait for the known devices to complete their probing */
>>>>> wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
>>>>> async_synchronize_full();
>>>>
>>>> I'm not sure if this is sufficient.
>>>>
>>>> Something may be added to the workqueue right after you've flushed it and
>>>> then be reporobed after the wait_event() in theory. Or am I missing anything?
>>>
>>> Maybe I'm missing part of this, but I think the point is to make sure
>>> that every probe which began or was queued before this function got
>>> called, has finished before the function returns.
>>>
>>> Thus, in the case at hand we want to defer all probes starting from
>>> some point in the system sleep transition. Grygorii sets his
>>> defer_all_probes variable and then calls this function. It waits for
>>> any probes that were initiated before the function call. Any probe
>>> that was initiated after the function call (for example, the ones
>>> you're concerned about between the flush_workqueue and wait_event) will
>>> see that defer_all_probes is set and so will defer itself.
>>
>> Yes. It will work as expected with the next patch.
>> For all other case, where this API is used alone -
>> it will make things more safe, but there is no way to completely block
>> scheduling of new probes.
>
> Well, in that case why don't you make it part of the second patch after all
> instead of making a false impression of fixing a more general problem?
>
ok.
--
regards,
-grygorii
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2015-10-13 18:25 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-08 16:57 [PATCH 0/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
2015-10-08 16:57 ` [PATCH 1/2] PM / sleep: ensure deferred probe workqueue is finished in wait_for_device_probe Grygorii Strashko
2015-10-08 20:50 ` Rafael J. Wysocki
2015-10-08 20:53 ` Alan Stern
2015-10-09 14:38 ` Grygorii Strashko
2015-10-09 21:16 ` Rafael J. Wysocki
2015-10-13 18:25 ` Grygorii Strashko
2015-10-08 16:57 ` [PATCH 2/2] PM / sleep: prohibit devices probing during suspend/hibernation Grygorii Strashko
2015-10-08 17:24 ` Alan Stern
2015-10-08 18:54 ` Grygorii Strashko
2015-10-08 19:20 ` Alan Stern
2015-10-08 19:48 ` Grygorii Strashko
2015-10-08 20:05 ` Alan Stern
2015-10-08 20:46 ` Rafael J. Wysocki
2015-10-09 14:31 ` Grygorii Strashko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).