Skip to contentSkip to conversation

arm: sched: stop sched_clock() during suspend

PATCH Superseded Felipe Balbi 4 participants 11 messages Oct 22, 2012 – Oct 23, 2012 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 arm: sched: stop sched_clock() during suspend

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that IRQ threads will be rescheduled in the future which might cause transfers to timeout depending on how driver is written.

This became an issue on OMAP when we converted omap-i2c.c to use threaded IRQs, it turned out that depending on how much time we spent on suspend, the I2C IRQ thread would end up being rescheduled so far in the future that I2C transfers would timeout and, because omap_hsmmc depends on an I2C-connected device to detect if an MMC card is inserted in the slot, our rootfs would just vanish.

arch/arm/kernel/sched_clock.c already had an optional implementation (sched_clock_needs_suspend()) which would handle scheduler's requirement properly, what this patch does is simply to make that implementation non-optional.

This has been tested with beagleboard XM (OMAP3630) and pandaboard rev A3 (OMAP4430). Suspend to RAM is now working after this patch.

---
 arch/arm/include/asm/sched_clock.h |  2 --
 arch/arm/kernel/sched_clock.c      | 18 ++++--------------
 2 files changed, 4 insertions(+), 16 deletions(-)
arch/arm/include/asm/sched_clock.h +0 -2
index 05b8e82..e3f7572 100644
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate);
 
 #endif
arch/arm/kernel/sched_clock.c +4 -14
index e21bac2..fc6692e 100644
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
 	update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate)
-{
-	setup_sched_clock(read, bits, rate);
-	cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
 	unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
 	sched_clock_poll(sched_clock_timer.data);
-	if (cd.needs_suspend)
-		cd.suspended = true;
+	cd.suspended = true;
 	return 0;
 }
 
 static void sched_clock_resume(void)
 {
-	if (cd.needs_suspend) {
-		cd.epoch_cyc = read_sched_clock();
-		cd.epoch_cyc_copy = cd.epoch_cyc;
-		cd.suspended = false;
-	}
+	cd.epoch_cyc = read_sched_clock();
+	cd.epoch_cyc_copy = cd.epoch_cyc;
+	cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
Signature · 1 line
1.8.0.rc0
#1 lore raw

Hi,

Quoted 19 lines · Felipe Balbi

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that IRQ threads will be rescheduled in the future which might cause transfers to timeout depending on how driver is written.

This became an issue on OMAP when we converted omap-i2c.c to use threaded IRQs, it turned out that depending on how much time we spent on suspend, the I2C IRQ thread would end up being rescheduled so far in the future that I2C transfers would timeout and, because omap_hsmmc depends on an I2C-connected device to detect if an MMC card is inserted in the slot, our rootfs would just vanish.

arch/arm/kernel/sched_clock.c already had an optional implementation (sched_clock_needs_suspend()) which would handle scheduler's requirement properly, what this patch does is simply to make that implementation non-optional.

Quoted 5 lines

This has been tested with beagleboard XM (OMAP3630) and pandaboard rev A3 (OMAP4430). Suspend to RAM is now working after this patch.

just adding more guys to Cc. Please add more if I have missed someone.

Quoted 61 lines
---
 arch/arm/include/asm/sched_clock.h |  2 --
 arch/arm/kernel/sched_clock.c      | 18 ++++--------------
 2 files changed, 4 insertions(+), 16 deletions(-)
arch/arm/include/asm/sched_clock.h +0 -2
index 05b8e82..e3f7572 100644
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate);
 
 #endif
arch/arm/kernel/sched_clock.c +4 -14
index e21bac2..fc6692e 100644
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
 	update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate)
-{
-	setup_sched_clock(read, bits, rate);
-	cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
 	unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
 	sched_clock_poll(sched_clock_timer.data);
-	if (cd.needs_suspend)
-		cd.suspended = true;
+	cd.suspended = true;
 	return 0;
 }
 
 static void sched_clock_resume(void)
 {
-	if (cd.needs_suspend) {
-		cd.epoch_cyc = read_sched_clock();
-		cd.epoch_cyc_copy = cd.epoch_cyc;
-		cd.suspended = false;
-	}
+	cd.epoch_cyc = read_sched_clock();
+	cd.epoch_cyc_copy = cd.epoch_cyc;
+	cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
Signature · 1 line
1.8.0.rc0
Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/01b6c272/attachment.sig>
#2 lore raw
In reply to Felipe Balbi

+Colin Cross, Barry Song also

Quoted 5 lines · Felipe Balbi

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that IRQ threads will be rescheduled in the future which might cause transfers to timeout depending on how driver is written.

It's not just about IRQ threads, it's about RT throttling. IOW, not just IRQ threads will be postponed, but all RT tasks will be throttled temporarily as well.

The changelog should also mention that this has an inconvenient side effect of stopping the printk times during suspend. Based on the original thread where this feature was discussed and introduced, some platforms wanted to opt out of this behavior[1], so the optional API was added.

However, in light of RT throttling, this a correctness issue for process accounting, so I agree that this should be done for all platforms instead of providing an optional 'needs suspend' version of the API, even though it means printk times no longer reflect time spent suspended.

After a discussion with peterz on this topic, it seems that x86 already ensures that sched_clock stops during suspend for similar reasons[2].

The question then is whether this is a fix that belongs in v3.7. Technically, it is not a regression, so I think this should probably be v3.8 material. If that's the decision, then the threaded IRQ support for the OMAP I2C driver needs to be reverted for v3.7 until this fix is merged.

Kevin

[1] http://marc.info/?l=linux-arm-kernel&m=134307004508708&w=2
[2] http://marc.info/?l=linux-arm-kernel&m=135065529907297&w=2

#3 lore raw
Quoted 5 lines · Kevin Hilman

However, in light of RT throttling, this a correctness issue for process accounting, so I agree that this should be done for all platforms instead of providing an optional 'needs suspend' version of the API, even though it means printk times no longer reflect time spent suspended.

Maybe we should get printk() to use the best clocksource instead.

The reason AFAICT that printk() is using sched_clock() is that it's supposed to be fast. But now it seems that it's not going to return what printk() needs anymore.

(Dragging Stultz & Gleixner into this...)

Yours,
Linus Walleij

#4 lore raw

PATCH 1/1 arm: sched: stop sched_clock() during suspend

Quoted 9 lines · Linus Walleij
Quoted 5 lines · Kevin Hilman

However, in light of RT throttling, this a correctness issue for process accounting, so I agree that this should be done for all platforms instead of providing an optional 'needs suspend' version of the API, even though it means printk times no longer reflect time spent suspended.

Quoted 6 lines

Maybe we should get printk() to use the best clocksource instead.

The reason AFAICT that printk() is using sched_clock() is that it's supposed to be fast. But now it seems that it's not going to return what printk() needs anymore.

No, printk() does not need this. You think it does, but it doesn't. What we have is a difference between ARM and x86, and this difference is breaking the scheduler.

The fact that the printk timestamp increments while suspended is a bug. It doesn't on x86.

There's three other functions in the kernel which do return updated time. I'm sure one of those can be used to printk() the time passed in suspend at resume time, which would give the information required.

#5 lore raw

PATCH 1/1 arm: sched: stop sched_clock() during suspend

Quoted 17 lines · Russell King - ARM Linux
Quoted 9 lines · Linus Walleij
Quoted 5 lines · Kevin Hilman

However, in light of RT throttling, this a correctness issue for process accounting, so I agree that this should be done for all platforms instead of providing an optional 'needs suspend' version of the API, even though it means printk times no longer reflect time spent suspended.

Quoted 6 lines

Maybe we should get printk() to use the best clocksource instead.

The reason AFAICT that printk() is using sched_clock() is that it's supposed to be fast. But now it seems that it's not going to return what printk() needs anymore.

Quoted 6 lines

No, printk() does not need this. You think it does, but it doesn't. What we have is a difference between ARM and x86, and this difference is breaking the scheduler.

The fact that the printk timestamp increments while suspended is a bug. It doesn't on x86.

Russell, I agree that it's a bug, but does it qualify as a something you're willing to take for v3.7-rc?

For OMAP, we need to know if this will go for v3.7 or not because there's a regression in the OMAP I2C driver, and if this doesn't go in, we'll need to revert something in the I2C driver until it does.

Thanks,

Kevin

#6 lore raw

PATCH 1/1 arm: sched: stop sched_clock() during suspend

Quoted 10 lines · Kevin Hilman
Quoted 6 lines · Russell King - ARM Linux

No, printk() does not need this. You think it does, but it doesn't. What we have is a difference between ARM and x86, and this difference is breaking the scheduler.

The fact that the printk timestamp increments while suspended is a bug. It doesn't on x86.

Russell, I agree that it's a bug, but does it qualify as a something you're willing to take for v3.7-rc?

Definitely. Our current behaviour across suspend for the scheduler is wrong. This is one of the questions I had when I created the sched_clock stuff - but no one at the time could answer. So, now that we have our answer, let's get it fixed to conform.

#7 lore raw

PATCH 1/1 arm: sched: stop sched_clock() during suspend

Hi,

Quoted 9 lines · Russell King - ARM Linux
Quoted 8 lines · Kevin Hilman
Quoted 6 lines · Russell King - ARM Linux

No, printk() does not need this. You think it does, but it doesn't. What we have is a difference between ARM and x86, and this difference is breaking the scheduler.

The fact that the printk timestamp increments while suspended is a bug. It doesn't on x86.

Quoted 7 lines
Quoted 2 lines

Russell, I agree that it's a bug, but does it qualify as a something you're willing to take for v3.7-rc?

Definitely. Our current behaviour across suspend for the scheduler is wrong. This is one of the questions I had when I created the sched_clock stuff - but no one at the time could answer. So, now that we have our answer, let's get it fixed to conform.

I have just pushed the patch the your patch system, hope I did it all right.

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121023/827d4ccb/attachment-0001.sig>
#8 lore raw

PATCH v2 1/1 arm: sched: stop sched_clock() during suspend

In reply to Kevin Hilman

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that any RT thread will be rescheduled in the future which might cause any sort of problems.

This became an issue on OMAP when we converted omap-i2c.c to use threaded IRQs, it turned out that depending on how much time we spent on suspend, the I2C IRQ thread would end up being rescheduled so far in the future that I2C transfers would timeout and, because omap_hsmmc depends on an I2C-connected device to detect if an MMC card is inserted in the slot, our rootfs would just vanish.

arch/arm/kernel/sched_clock.c already had an optional implementation (sched_clock_needs_suspend()) which would handle scheduler's requirement properly, what this patch does is simply to make that implementation non-optional.

Note that this has the side-effect that printk timings won't reflect the actual time spent on suspend so other methods to measure that will have to be used.

This has been tested with beagleboard XM (OMAP3630) and pandaboard rev A3 (OMAP4430). Suspend to RAM is now working after this patch.

---

Changes since v1:
- changed commit log to mention that all RT threads will be rescheduled to the future.
- changed commit log to mention the side effect on printk timings

 arch/arm/include/asm/sched_clock.h |  2 --
 arch/arm/kernel/sched_clock.c      | 18 ++++--------------
 2 files changed, 4 insertions(+), 16 deletions(-)
arch/arm/include/asm/sched_clock.h +0 -2
index 05b8e82..e3f7572 100644
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate);
 
 #endif
arch/arm/kernel/sched_clock.c +4 -14
index e21bac2..fc6692e 100644
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
 	update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-		unsigned long rate)
-{
-	setup_sched_clock(read, bits, rate);
-	cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
 	unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
 	sched_clock_poll(sched_clock_timer.data);
-	if (cd.needs_suspend)
-		cd.suspended = true;
+	cd.suspended = true;
 	return 0;
 }
 
 static void sched_clock_resume(void)
 {
-	if (cd.needs_suspend) {
-		cd.epoch_cyc = read_sched_clock();
-		cd.epoch_cyc_copy = cd.epoch_cyc;
-		cd.suspended = false;
-	}
+	cd.epoch_cyc = read_sched_clock();
+	cd.epoch_cyc_copy = cd.epoch_cyc;
+	cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
Signature · 1 line
1.8.0.rc0
#9 lore raw

PATCH v2 1/1 arm: sched: stop sched_clock() during suspend

Quoted 22 lines · Felipe Balbi

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that any RT thread will be rescheduled in the future which might cause any sort of problems.

This became an issue on OMAP when we converted omap-i2c.c to use threaded IRQs, it turned out that depending on how much time we spent on suspend, the I2C IRQ thread would end up being rescheduled so far in the future that I2C transfers would timeout and, because omap_hsmmc depends on an I2C-connected device to detect if an MMC card is inserted in the slot, our rootfs would just vanish.

arch/arm/kernel/sched_clock.c already had an optional implementation (sched_clock_needs_suspend()) which would handle scheduler's requirement properly, what this patch does is simply to make that implementation non-optional.

Note that this has the side-effect that printk timings won't reflect the actual time spent on suspend so other methods to measure that will have to be used.

Quoted 5 lines

This has been tested with beagleboard XM (OMAP3630) and pandaboard rev A3 (OMAP4430). Suspend to RAM is now working after this patch.

Acked-by on v1 1/1
#10 lore raw
In reply to Felipe Balbi
Quoted 19 lines · Felipe Balbi

The scheduler imposes a requirement to sched_clock() which is to stop the clock during suspend, if we don't do that IRQ threads will be rescheduled in the future which might cause transfers to timeout depending on how driver is written.

This became an issue on OMAP when we converted omap-i2c.c to use threaded IRQs, it turned out that depending on how much time we spent on suspend, the I2C IRQ thread would end up being rescheduled so far in the future that I2C transfers would timeout and, because omap_hsmmc depends on an I2C-connected device to detect if an MMC card is inserted in the slot, our rootfs would just vanish.

arch/arm/kernel/sched_clock.c already had an optional implementation (sched_clock_needs_suspend()) which would handle scheduler's requirement properly, what this patch does is simply to make that implementation non-optional.

Quoted 5 lines

This has been tested with beagleboard XM (OMAP3630) and pandaboard rev A3 (OMAP4430). Suspend to RAM is now working after this patch.

After Russell explains so I get it:

Yours,
Linus Walleij