public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 2.6.23-rc2 1/2] define clk_must_disable()
@ 2007-08-06 18:11 David Brownell
  2007-08-06 20:04 ` Russell King
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2007-08-06 18:11 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Andrew Victor, linux-pm, Russell King

This patch adds a clk_must_disable() operation, exposing the clock constraints
which often distinguish system power states.  Systems with such constraints
include ones using ARM-based AT91, OMAP, and PXA chips.  The new operation
lets driver methods check those constraints.

A common benefit to leaving some device clocks enabled is that a suspended
device may then be able to issue system wakeup events.  RS232, USB, Ethernet,
and other drivers can use driver model wakeup flags as userspace directions
about how to trade off between the lowest power "full off" states and more
functional wakeup-enabled ones.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>

--- at91.orig/include/linux/clk.h	2007-02-16 08:47:11.000000000 -0800
+++ at91/include/linux/clk.h	2007-02-16 08:47:17.000000000 -0800
@@ -121,4 +121,24 @@ int clk_set_parent(struct clk *clk, stru
  */
 struct clk *clk_get_parent(struct clk *clk);
 
+/**
+ * clk_must_disable - report whether a clock's users must disable it
+ * @clk: one node in the clock tree
+ *
+ * This routine returns true only if the upcoming system state requires
+ * disabling the specified clock.
+ *
+ * It's common for platform power states to constrain certain clocks (and
+ * their descendants) to be unavailable, while other states allow that
+ * clock to be active.  A platform's power states often include an "all on"
+ * mode; system wide sleep states like "standby" and "suspend-to-RAM"; and
+ * operating states which sacrifice functionality for lower power usage.
+ *
+ * The constraint value is commonly tested in device driver suspend(), to
+ * leave clocks active if they are needed for features like wakeup events.
+ * On platforms that support reduced functionality operating states, the
+ * constraint may also need to be tested during resume() and probe() calls.
+ */
+int clk_must_disable(struct clk *clk);
+
 #endif

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 18:11 [patch 2.6.23-rc2 1/2] define clk_must_disable() David Brownell
@ 2007-08-06 20:04 ` Russell King
  2007-08-06 20:38   ` David Brownell
  0 siblings, 1 reply; 16+ messages in thread
From: Russell King @ 2007-08-06 20:04 UTC (permalink / raw)
  To: David Brownell; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Mon, Aug 06, 2007 at 11:11:03AM -0700, David Brownell wrote:
> This patch adds a clk_must_disable() operation, exposing the clock constraints
> which often distinguish system power states.  Systems with such constraints
> include ones using ARM-based AT91, OMAP, and PXA chips.  The new operation
> lets driver methods check those constraints.
> 
> A common benefit to leaving some device clocks enabled is that a suspended
> device may then be able to issue system wakeup events.  RS232, USB, Ethernet,
> and other drivers can use driver model wakeup flags as userspace directions
> about how to trade off between the lowest power "full off" states and more
> functional wakeup-enabled ones.
> 
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>

Andrew,

David sent these without giving me a chance to respond to them.  For
your record, below are my comments.  As you can see, I'm of the opinion
that they're not suitable at present.

Message 1:
On Mon, Aug 06, 2007 at 10:23:21AM -0700, David Brownell wrote:
> A better fix is to recognize that the clock API is missing PM hooks;
> some drivers should stay partially active in sleep states that don't
> actually require them to turn off their clocks, and that's not at all
> unique to AT91 hardware.
>
>   https://lists.linux-foundation.org/pipermail/linux-pm/2007-March/011495.html>   https://lists.linux-foundation.org/pipermail/linux-pm/2007-March/011496.html>
> Presumably I should just get those into the MM queue ... I've been
> scrubbing other patches out, it's time for those also.

+ * This routine returns true only if the upcoming system state requires
+ * disabling the specified clock.
...
+int clk_must_disable(struct clk *clk);

It isn't clear how such a function decides whether the clock is available
in this "upcoming system state".  Some SoCs have multiple power states
which they can enter, so without knowledge of what this "upcoming
system state" is, how can this function decide?

Shouldn't it be passed something representing this "upcoming system state" ?

Also "clk_must_disable" is a horrible function name - it seems far too
ambiguous.  "clk_must_suspend()" would be a better hint at what it's
trying to do.

Message 2:
On Mon, Aug 06, 2007 at 11:25:56AM -0700, David Brownell wrote:
> I've sent the two patches to Andrew, with a "please expedite,
> this is a build fix" comment.

Given that there's some concerns about it, please provide only a minimal
fix - in other words the function prototype necessary to fix the build
issue.

Please don't wrap up unreviewed patches as "important build fixes".


-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 20:04 ` Russell King
@ 2007-08-06 20:38   ` David Brownell
  2007-08-06 21:03     ` David Brownell
  2007-08-06 21:48     ` Russell King
  0 siblings, 2 replies; 16+ messages in thread
From: David Brownell @ 2007-08-06 20:38 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Monday 06 August 2007, Russell King wrote:
> On Mon, Aug 06, 2007 at 11:11:03AM -0700, David Brownell wrote:
> > This patch adds a clk_must_disable() operation, exposing the clock constraints
> > which often distinguish system power states.  Systems with such constraints
> > include ones using ARM-based AT91, OMAP, and PXA chips.  The new operation
> > lets driver methods check those constraints.
> > 
> > A common benefit to leaving some device clocks enabled is that a suspended
> > device may then be able to issue system wakeup events.  RS232, USB, Ethernet,
> > and other drivers can use driver model wakeup flags as userspace directions
> > about how to trade off between the lowest power "full off" states and more
> > functional wakeup-enabled ones.
> > 
> > Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
> 
> Andrew,
> 
> David sent these without giving me a chance to respond to them. 

Not at all true.  You've seen them at least two other times since they
were first posted last year against 2.6.17-rc4.  Let's see:

 16-May-2006	http://marc.info/?l=linux-kernel&m=114782690922167&w=2
 22-March-2007	http://marc.info/?l=linux-kernel&m=117458718812017&w=2

And you didn't say a word then.  That's well over a year that you
have been silent.


> For 
> your record, below are my comments.  As you can see, I'm of the opinion
> that they're not suitable at present.

I've responded to these on their original list, but to re-cap:


> Message 1:
> ...
> 
> + * This routine returns true only if the upcoming system state requires
> + * disabling the specified clock.
> ...
> +int clk_must_disable(struct clk *clk);
> 
> It isn't clear how such a function decides whether the clock is available
> in this "upcoming system state".  Some SoCs have multiple power states
> which they can enter, so without knowledge of what this "upcoming
> system state" is, how can this function decide?
> 
> Shouldn't it be passed something representing this "upcoming system state" ?

pm_ops.set_target_state() does that now; pm_ops.prepare() used to
do it before that was redefined to make ACPI happier.


> Also "clk_must_disable" is a horrible function name - it seems far too
> ambiguous.  "clk_must_suspend()" would be a better hint at what it's
> trying to do.

If the relevant action were the non-existent clk_suspend() call I'd
agree.  But instead, it's the same old clk_disable() call that's in
question.  So ... no, that response makes no sense.

 
> Message 2:
> On Mon, Aug 06, 2007 at 11:25:56AM -0700, David Brownell wrote:
> > I've sent the two patches to Andrew, with a "please expedite,
> > this is a build fix" comment.
> 
> Given that there's some concerns about it, please provide only a minimal
> fix - in other words the function prototype necessary to fix the build
> issue.

The preceding times this specific API has come up, *NOBODY* ever
mentioned even one concern beyond "when will this patch merge".


> Please don't wrap up unreviewed patches as "important build fixes".

>From my perspective, they've been reviewed for well over a year and
have just been waiting for me to get off my butt and be extremely
explicit that they need to merge.  (That is, not expect anyone to
just pick them up and merge.)

And since you asked for a build fix ... I have a hard time thinking
that anything else could really be the "right fix".

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 20:38   ` David Brownell
@ 2007-08-06 21:03     ` David Brownell
  2007-08-06 21:48     ` Russell King
  1 sibling, 0 replies; 16+ messages in thread
From: David Brownell @ 2007-08-06 21:03 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Monday 06 August 2007, David Brownell wrote:
> > Please don't wrap up unreviewed patches as "important build fixes".
> 
> From my perspective, they've been reviewed for well over a year and
> have just been waiting for me to get off my butt and be extremely
> explicit that they need to merge.  (That is, not expect anyone to
> just pick them up and merge.)

Oh, and one more point in favor of merging this:  they've been in
use in Andrew Victor's 2.6 AT91 patches since last November.

That would be yet another reason why nobody has noticed this build
problem before.  It's not just me; almost everyone doing AT91 work
is *already using* these two patches, and has been doing so for most
of the last year.


> And since you asked for a build fix ... I have a hard time thinking
> that anything else could really be the "right fix".
 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 20:38   ` David Brownell
  2007-08-06 21:03     ` David Brownell
@ 2007-08-06 21:48     ` Russell King
  2007-08-06 23:46       ` David Brownell
  1 sibling, 1 reply; 16+ messages in thread
From: Russell King @ 2007-08-06 21:48 UTC (permalink / raw)
  To: David Brownell; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Mon, Aug 06, 2007 at 01:38:08PM -0700, David Brownell wrote:
> And since you asked for a build fix ... I have a hard time thinking
> that anything else could really be the "right fix".

Do you have to drag every discussion right down into the shit pile?
Your message isn't even worth this response.

Appologies for trying to do the right thing.  Appologies for missing
your patches earlier this year.  Appologies for even living.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 21:48     ` Russell King
@ 2007-08-06 23:46       ` David Brownell
  2007-08-07  5:23         ` Andrew Morton
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2007-08-06 23:46 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Monday 06 August 2007, Russell King wrote:
> On Mon, Aug 06, 2007 at 01:38:08PM -0700, David Brownell wrote:
> > And since you asked for a build fix ... I have a hard time thinking
> > that anything else could really be the "right fix".
> 
> Do you have to drag every discussion right down into the shit pile?
> Your message isn't even worth this response.

Don't introduce four letter words then.  You know the drill:
good *technical* arguments are what should win.

I agree it would have been easier if I had asked to merge this
earlier; like for 2.6.18 as originally planned, or 2.6.22 ... sigh.
It never got to the top of the priority list until that Makefile
patch forced the issue; and merge windows are filled with stuff
that's higher priority.

Thing is, I've never been one to prefer short term hacks when
a good long-term solution is available.  In this case, that
solution has been used for over 9 months now, and was presented
more than once on LKML.  Even now, there are no good technical
counter-arguments.  So I still think this is the "right fix".

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-06 23:46       ` David Brownell
@ 2007-08-07  5:23         ` Andrew Morton
  2007-08-07 12:50           ` Russell King
  0 siblings, 1 reply; 16+ messages in thread
From: Andrew Morton @ 2007-08-07  5:23 UTC (permalink / raw)
  To: David Brownell; +Cc: Andrew Victor, linux-pm, Russell King


ookkkay.  I'm going to pretend that I had an email malfunction which
deleted all rmk and david-b email for the past 24 hours.  I'd suggest that
others adopt the same pretence.



Russell, I have received the below from David.  Could you please review it
for inclusion?

Thanks.


From: David Brownell <david-b@pacbell.net>

This supports the clk_must_disable() interface for AT91 systems:

 - Implement the call, replacing at91_suspend_entering_slow_clock();

 - Use it in three drivers: USB Host, USB Peripheral, and RS232 serial.

Briefly, those are three of the drivers that need to act differently
when going into deeper sleep states (suspend-to-RAM), where among other
things they can't act as wakeup event sources.

(The at91_ethernet driver would be another such driver, but it doesn't
currently implement wake-on-LAN even in the "standby" mode.)

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 arch/arm/mach-at91/clock.c    |   18 ++++++++++++++++++
 arch/arm/mach-at91/generic.h  |    1 +
 arch/arm/mach-at91/pm.c       |    7 +------
 drivers/serial/atmel_serial.c |    3 ++-
 drivers/usb/gadget/at91_udc.c |    2 +-
 drivers/usb/host/ohci-at91.c  |    2 +-
 6 files changed, 24 insertions(+), 9 deletions(-)

diff -puN arch/arm/mach-at91/clock.c~at91-implements-clk_must_disable arch/arm/mach-at91/clock.c
--- a/arch/arm/mach-at91/clock.c~at91-implements-clk_must_disable
+++ a/arch/arm/mach-at91/clock.c
@@ -32,6 +32,7 @@
 #include <asm/arch/cpu.h>
 
 #include "clock.h"
+#include "generic.h"
 
 
 /*
@@ -254,6 +255,23 @@ EXPORT_SYMBOL(clk_get_rate);
 
 /*------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PM
+
+int clk_must_disable(struct clk *clk)
+{
+	if (!at91_suspend_entering_slow_clock())
+		return 0;
+
+	while (clk->parent)
+		clk = clk->parent;
+	return clk != &clk32k;
+}
+EXPORT_SYMBOL(clk_must_disable);
+
+#endif
+
+/*------------------------------------------------------------------------*/
+
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
 
 /*
diff -puN arch/arm/mach-at91/generic.h~at91-implements-clk_must_disable arch/arm/mach-at91/generic.h
--- a/arch/arm/mach-at91/generic.h~at91-implements-clk_must_disable
+++ a/arch/arm/mach-at91/generic.h
@@ -36,6 +36,7 @@ extern void __init at91_clock_associate(
  /* Power Management */
 extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
+extern int at91_suspend_entering_slow_clock(void);
 
  /* GPIO */
 #define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
diff -puN arch/arm/mach-at91/pm.c~at91-implements-clk_must_disable arch/arm/mach-at91/pm.c
--- a/arch/arm/mach-at91/pm.c~at91-implements-clk_must_disable
+++ a/arch/arm/mach-at91/pm.c
@@ -103,20 +103,15 @@ static int at91_pm_verify_clocks(void)
 }
 
 /*
- * Call this from platform driver suspend() to see how deeply to suspend.
+ * This is called from clk_must_disable(), to see how deeply to suspend.
  * For example, some controllers (like OHCI) need one of the PLL clocks
  * in order to act as a wakeup source, and those are not available when
  * going into slow clock mode.
- *
- * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
- * the very same problem (but not using at91 main_clk), and it'd be better
- * to add one generic API rather than lots of platform-specific ones.
  */
 int at91_suspend_entering_slow_clock(void)
 {
 	return (target_state == PM_SUSPEND_MEM);
 }
-EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
 
 static void (*slow_clock)(void);
diff -puN drivers/serial/atmel_serial.c~at91-implements-clk_must_disable drivers/serial/atmel_serial.c
--- a/drivers/serial/atmel_serial.c~at91-implements-clk_must_disable
+++ a/drivers/serial/atmel_serial.c
@@ -921,7 +921,8 @@ static int atmel_serial_suspend(struct p
 	struct uart_port *port = platform_get_drvdata(pdev);
 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
 
-	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
+	if (device_may_wakeup(&pdev->dev)
+			&& !clk_must_disable(atmel_port->clk))
 		enable_irq_wake(port->irq);
 	else {
 		uart_suspend_port(&atmel_uart, port);
diff -puN drivers/usb/gadget/at91_udc.c~at91-implements-clk_must_disable drivers/usb/gadget/at91_udc.c
--- a/drivers/usb/gadget/at91_udc.c~at91-implements-clk_must_disable
+++ a/drivers/usb/gadget/at91_udc.c
@@ -1782,7 +1782,7 @@ static int at91udc_suspend(struct platfo
 	 */
 	if ((!udc->suspended && udc->addr)
 			|| !wake
-			|| at91_suspend_entering_slow_clock()) {
+			|| clk_must_disable(udc->fclk)) {
 		pullup(udc, 0);
 		wake = 0;
 	} else
diff -puN drivers/usb/host/ohci-at91.c~at91-implements-clk_must_disable drivers/usb/host/ohci-at91.c
--- a/drivers/usb/host/ohci-at91.c~at91-implements-clk_must_disable
+++ a/drivers/usb/host/ohci-at91.c
@@ -299,7 +299,7 @@ ohci_hcd_at91_drv_suspend(struct platfor
 	 *
 	 * REVISIT: some boards will be able to turn VBUS off...
 	 */
-	if (at91_suspend_entering_slow_clock()) {
+	if (clk_must_disable(fclk)) {
 		ohci_usb_reset (ohci);
 		at91_stop_clock();
 	}
_

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07  5:23         ` Andrew Morton
@ 2007-08-07 12:50           ` Russell King
  2007-08-07 17:21             ` Andrew Morton
                               ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Russell King @ 2007-08-07 12:50 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Andrew Victor, linux-pm

I do not think that the clk_must_disable() API is well enough thought out
for the following reasons:

1. the name sucks - it tells you nothing about it's purpose, which as
   the name currently stands can be interpreted in as many ways as there
   are species of animals on this planet.

   While the comments around the prototype help interpret its semantics,
   it is no subsitute for having a good name for the function.

2. it's unclear how this function obtains information about the "upcoming
   system state" and therefore decides whether the particular clock may
   be available.

3. due to the negative semantics, code such as the following is difficult
   to interpret and work out whether it's correct due to the double
   negative:

  +     if (device_may_wakeup(&pdev->dev)
  +                     && !clk_must_disable(atmel_port->clk))
                enable_irq_wake(port->irq);

4. the description of the function implies that this function may be
   called when we are not suspending:

  + * On platforms that support reduced functionality operating states, the
  + * constraint may also need to be tested during resume() and probe() calls.

   With SoCs with multiple power states affecting which clocks are
   available, and the need in point (2) for the architecture code to
   record which PM mode we're entering via the pm_ops set_target method,
   calling clk_must_disable() outside of the suspend methods results in
   this function essentially returning undefined values at driver probe
   time.  Note: there is no locking between driver probing and the
   set_target method.

   Moreover, if used in a driver probe() path, the return value could
   well depend on the _last_ system suspend state entered, and would be
   undefined for a system which hasn't been suspended from boot.

Changing the function name to "clk_available_in_suspend()" addresses at
least two of these points.  The other two points are addressed by
providing a way for the method to be passed the desired system suspend
state, which may be resolved by expanding pm_message_t to contain that
information.

Finally, concerning merging this during the -rc phase, I'd much rather
see the one liner simple build fix of adding the missing function
prototype going into the -rc kernels, and then a similar patch to this
going in during the next merge window.

On Mon, Aug 06, 2007 at 10:23:51PM -0700, Andrew Morton wrote:
> diff -puN arch/arm/mach-at91/clock.c~at91-implements-clk_must_disable arch/arm/mach-at91/clock.c
> --- a/arch/arm/mach-at91/clock.c~at91-implements-clk_must_disable
> +++ a/arch/arm/mach-at91/clock.c
> @@ -32,6 +32,7 @@
>  #include <asm/arch/cpu.h>
>  
>  #include "clock.h"
> +#include "generic.h"
>  
>  
>  /*
> @@ -254,6 +255,23 @@ EXPORT_SYMBOL(clk_get_rate);
>  
>  /*------------------------------------------------------------------------*/
>  
> +#ifdef CONFIG_PM
> +
> +int clk_must_disable(struct clk *clk)
> +{
> +	if (!at91_suspend_entering_slow_clock())
> +		return 0;
> +
> +	while (clk->parent)
> +		clk = clk->parent;
> +	return clk != &clk32k;
> +}
> +EXPORT_SYMBOL(clk_must_disable);
> +
> +#endif
> +
> +/*------------------------------------------------------------------------*/
> +
>  #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
>  
>  /*
> diff -puN arch/arm/mach-at91/generic.h~at91-implements-clk_must_disable arch/arm/mach-at91/generic.h
> --- a/arch/arm/mach-at91/generic.h~at91-implements-clk_must_disable
> +++ a/arch/arm/mach-at91/generic.h
> @@ -36,6 +36,7 @@ extern void __init at91_clock_associate(
>   /* Power Management */
>  extern void at91_irq_suspend(void);
>  extern void at91_irq_resume(void);
> +extern int at91_suspend_entering_slow_clock(void);
>  
>   /* GPIO */
>  #define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
> diff -puN arch/arm/mach-at91/pm.c~at91-implements-clk_must_disable arch/arm/mach-at91/pm.c
> --- a/arch/arm/mach-at91/pm.c~at91-implements-clk_must_disable
> +++ a/arch/arm/mach-at91/pm.c
> @@ -103,20 +103,15 @@ static int at91_pm_verify_clocks(void)
>  }
>  
>  /*
> - * Call this from platform driver suspend() to see how deeply to suspend.
> + * This is called from clk_must_disable(), to see how deeply to suspend.
>   * For example, some controllers (like OHCI) need one of the PLL clocks
>   * in order to act as a wakeup source, and those are not available when
>   * going into slow clock mode.
> - *
> - * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
> - * the very same problem (but not using at91 main_clk), and it'd be better
> - * to add one generic API rather than lots of platform-specific ones.
>   */
>  int at91_suspend_entering_slow_clock(void)
>  {
>  	return (target_state == PM_SUSPEND_MEM);
>  }
> -EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
>  
>  
>  static void (*slow_clock)(void);
> diff -puN drivers/serial/atmel_serial.c~at91-implements-clk_must_disable drivers/serial/atmel_serial.c
> --- a/drivers/serial/atmel_serial.c~at91-implements-clk_must_disable
> +++ a/drivers/serial/atmel_serial.c
> @@ -921,7 +921,8 @@ static int atmel_serial_suspend(struct p
>  	struct uart_port *port = platform_get_drvdata(pdev);
>  	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
>  
> -	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
> +	if (device_may_wakeup(&pdev->dev)
> +			&& !clk_must_disable(atmel_port->clk))
>  		enable_irq_wake(port->irq);
>  	else {
>  		uart_suspend_port(&atmel_uart, port);
> diff -puN drivers/usb/gadget/at91_udc.c~at91-implements-clk_must_disable drivers/usb/gadget/at91_udc.c
> --- a/drivers/usb/gadget/at91_udc.c~at91-implements-clk_must_disable
> +++ a/drivers/usb/gadget/at91_udc.c
> @@ -1782,7 +1782,7 @@ static int at91udc_suspend(struct platfo
>  	 */
>  	if ((!udc->suspended && udc->addr)
>  			|| !wake
> -			|| at91_suspend_entering_slow_clock()) {
> +			|| clk_must_disable(udc->fclk)) {
>  		pullup(udc, 0);
>  		wake = 0;
>  	} else
> diff -puN drivers/usb/host/ohci-at91.c~at91-implements-clk_must_disable drivers/usb/host/ohci-at91.c
> --- a/drivers/usb/host/ohci-at91.c~at91-implements-clk_must_disable
> +++ a/drivers/usb/host/ohci-at91.c
> @@ -299,7 +299,7 @@ ohci_hcd_at91_drv_suspend(struct platfor
>  	 *
>  	 * REVISIT: some boards will be able to turn VBUS off...
>  	 */
> -	if (at91_suspend_entering_slow_clock()) {
> +	if (clk_must_disable(fclk)) {
>  		ohci_usb_reset (ohci);
>  		at91_stop_clock();
>  	}
> _
> 

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
@ 2007-08-07 17:21             ` Andrew Morton
  2007-08-07 17:25               ` Russell King
  2007-08-07 20:15             ` David Brownell
                               ` (4 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Andrew Morton @ 2007-08-07 17:21 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, linux-pm

On Tue, 7 Aug 2007 13:50:54 +0100 Russell King <rmk@arm.linux.org.uk> wrote:

> I do not think that the clk_must_disable() API is well enough thought out
> for the following reasons:
> 
> 1. the name sucks - it tells you nothing about it's purpose, which as
>    the name currently stands can be interpreted in as many ways as there
>    are species of animals on this planet.
> 
>    While the comments around the prototype help interpret its semantics,
>    it is no subsitute for having a good name for the function.
> 
> 2. it's unclear how this function obtains information about the "upcoming
>    system state" and therefore decides whether the particular clock may
>    be available.
> 
> 3. due to the negative semantics, code such as the following is difficult
>    to interpret and work out whether it's correct due to the double
>    negative:
> 
>   +     if (device_may_wakeup(&pdev->dev)
>   +                     && !clk_must_disable(atmel_port->clk))
>                 enable_irq_wake(port->irq);
> 
> 4. the description of the function implies that this function may be
>    called when we are not suspending:
> 
>   + * On platforms that support reduced functionality operating states, the
>   + * constraint may also need to be tested during resume() and probe() calls.
> 
>    With SoCs with multiple power states affecting which clocks are
>    available, and the need in point (2) for the architecture code to
>    record which PM mode we're entering via the pm_ops set_target method,
>    calling clk_must_disable() outside of the suspend methods results in
>    this function essentially returning undefined values at driver probe
>    time.  Note: there is no locking between driver probing and the
>    set_target method.
> 
>    Moreover, if used in a driver probe() path, the return value could
>    well depend on the _last_ system suspend state entered, and would be
>    undefined for a system which hasn't been suspended from boot.
> 
> Changing the function name to "clk_available_in_suspend()" addresses at
> least two of these points.  The other two points are addressed by
> providing a way for the method to be passed the desired system suspend
> state, which may be resolved by expanding pm_message_t to contain that
> information.

I see, thanks.  clk_available_in_suspend() sure is a better name.

> Finally, concerning merging this during the -rc phase, I'd much rather
> see the one liner simple build fix of adding the missing function
> prototype going into the -rc kernels, and then a similar patch to this
> going in during the next merge window.

Here's where confusion sets in.  I have this:

--- at91.orig/include/linux/clk.h	2007-02-16 08:47:11.000000000 -0800
+++ at91/include/linux/clk.h	2007-02-16 08:47:17.000000000 -0800
@@ -121,4 +121,24 @@ int clk_set_parent(struct clk *clk, stru
  */
 struct clk *clk_get_parent(struct clk *clk);
 
+/**
+ * clk_must_disable - report whether a clock's users must disable it
+ * @clk: one node in the clock tree
+ *
+ * This routine returns true only if the upcoming system state requires
+ * disabling the specified clock.
+ *
+ * It's common for platform power states to constrain certain clocks (and
+ * their descendants) to be unavailable, while other states allow that
+ * clock to be active.  A platform's power states often include an "all on"
+ * mode; system wide sleep states like "standby" and "suspend-to-RAM"; and
+ * operating states which sacrifice functionality for lower power usage.
+ *
+ * The constraint value is commonly tested in device driver suspend(), to
+ * leave clocks active if they are needed for features like wakeup events.
+ * On platforms that support reduced functionality operating states, the
+ * constraint may also need to be tested during resume() and probe() calls.
+ */
+int clk_must_disable(struct clk *clk);
+
 #endif

but it's a prototype for a function which doesn't exist.  You must
be referring to a different patch.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 17:21             ` Andrew Morton
@ 2007-08-07 17:25               ` Russell King
  0 siblings, 0 replies; 16+ messages in thread
From: Russell King @ 2007-08-07 17:25 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Andrew Victor, linux-pm

On Tue, Aug 07, 2007 at 10:21:06AM -0700, Andrew Morton wrote:
> On Tue, 7 Aug 2007 13:50:54 +0100 Russell King <rmk@arm.linux.org.uk> wrote:
> 
> > I do not think that the clk_must_disable() API is well enough thought out
> > for the following reasons:
> > 
> > 1. the name sucks - it tells you nothing about it's purpose, which as
> >    the name currently stands can be interpreted in as many ways as there
> >    are species of animals on this planet.
> > 
> >    While the comments around the prototype help interpret its semantics,
> >    it is no subsitute for having a good name for the function.
> > 
> > 2. it's unclear how this function obtains information about the "upcoming
> >    system state" and therefore decides whether the particular clock may
> >    be available.
> > 
> > 3. due to the negative semantics, code such as the following is difficult
> >    to interpret and work out whether it's correct due to the double
> >    negative:
> > 
> >   +     if (device_may_wakeup(&pdev->dev)
> >   +                     && !clk_must_disable(atmel_port->clk))
> >                 enable_irq_wake(port->irq);
> > 
> > 4. the description of the function implies that this function may be
> >    called when we are not suspending:
> > 
> >   + * On platforms that support reduced functionality operating states, the
> >   + * constraint may also need to be tested during resume() and probe() calls.
> > 
> >    With SoCs with multiple power states affecting which clocks are
> >    available, and the need in point (2) for the architecture code to
> >    record which PM mode we're entering via the pm_ops set_target method,
> >    calling clk_must_disable() outside of the suspend methods results in
> >    this function essentially returning undefined values at driver probe
> >    time.  Note: there is no locking between driver probing and the
> >    set_target method.
> > 
> >    Moreover, if used in a driver probe() path, the return value could
> >    well depend on the _last_ system suspend state entered, and would be
> >    undefined for a system which hasn't been suspended from boot.
> > 
> > Changing the function name to "clk_available_in_suspend()" addresses at
> > least two of these points.  The other two points are addressed by
> > providing a way for the method to be passed the desired system suspend
> > state, which may be resolved by expanding pm_message_t to contain that
> > information.
> 
> I see, thanks.  clk_available_in_suspend() sure is a better name.
> 
> > Finally, concerning merging this during the -rc phase, I'd much rather
> > see the one liner simple build fix of adding the missing function
> > prototype going into the -rc kernels, and then a similar patch to this
> > going in during the next merge window.
> 
> Here's where confusion sets in.  I have this:

See 2/2.  Both patches need to be looked at together.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
  2007-08-07 17:21             ` Andrew Morton
@ 2007-08-07 20:15             ` David Brownell
  2007-08-07 20:18             ` David Brownell
                               ` (3 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: David Brownell @ 2007-08-07 20:15 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

Replying to points individually, to avoid excessively long emails.

On Tuesday 07 August 2007, Russell King wrote:
> 
> 1. the name sucks - it tells you nothing about it's purpose,

What -- that when it returns true, you "must disable" the clock?

I have a hard time with this claim.  The purpose could hardly become
more clear.  It seems to me that there is some other issue that's not
yet been surfaced here.  (I'll refrain from guessing.)

That said, it seems like this item reflects your core issue.


> 		which as 
>    the name currently stands can be interpreted in as many ways as there
>    are species of animals on this planet.
> 
>    While the comments around the prototype help interpret its semantics,
>    it is no subsitute for having a good name for the function.

Again, the semantics are exactly what the name says.  Hyperbole aside,
I'm in the dark about your real objection here.

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
  2007-08-07 17:21             ` Andrew Morton
  2007-08-07 20:15             ` David Brownell
@ 2007-08-07 20:18             ` David Brownell
  2007-08-07 21:04             ` David Brownell
                               ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: David Brownell @ 2007-08-07 20:18 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Tuesday 07 August 2007, Russell King wrote:
> 2. it's unclear how this function obtains information about the "upcoming
>    system state" and therefore decides whether the particular clock may
>    be available.

Why should any such *implementation detail* matter to an interface spec?

Especially to the clock framework, which has already gone to great
lengths to avoid constraining implementations, and allow them to do
whatever the platform needs.  (Admittedly, some people don't think
of that as a feature.)

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
                               ` (2 preceding siblings ...)
  2007-08-07 20:18             ` David Brownell
@ 2007-08-07 21:04             ` David Brownell
  2007-08-07 21:17             ` David Brownell
  2007-08-07 21:20             ` David Brownell
  5 siblings, 0 replies; 16+ messages in thread
From: David Brownell @ 2007-08-07 21:04 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Tuesday 07 August 2007, Russell King wrote:

> 3. due to the negative semantics, code such as the following is difficult
>    to interpret and work out whether it's correct due to the double
>    negative:

In terms of pure patch review, the "-" bit you omitted sure helps me
to see that it's an "obviously" correct transformation:

  -       if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
>   +     if (device_may_wakeup(&pdev->dev)
>   +                     && !clk_must_disable(atmel_port->clk))
>                 enable_irq_wake(port->irq);

In the case of nutball configurations like clocking UART from 32KiHz,
it's more correct.  Likewise, it can work with AVR32 platforms, once
they support PM.


There are numerous idioms that one could allege are confusing -- especially
when looking at them without any context! -- but which in practice are not.
The whole "if" statement is:

        if (device_may_wakeup(&pdev->dev) 
                        && !clk_must_disable(atmel_port->clk))
                enable_irq_wake(port->irq);
        else {
                uart_suspend_port(&atmel_uart, port);
                atmel_port->suspended = 1;
        }

That's a lot more clear then the fragment you showed -- suspend, or
keep it active with wakeup enabled -- with the main confusion coming
from the serial stack itself:  the way clk_disable() gets hidden
deep inside uart_suspend_port().
 
If you're saying that should be rewritten, something like:

	if (!device_may_wakeup(...) || clk_must_disable(...)) {
		suspend port
	} else
		leave it active, with wakeup enabled

That might be true, but it's not a new issue or attributable to
this patch.  Likewise with (potentially) adding comments.

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
                               ` (3 preceding siblings ...)
  2007-08-07 21:04             ` David Brownell
@ 2007-08-07 21:17             ` David Brownell
  2007-08-07 22:20               ` Rafael J. Wysocki
  2007-08-07 21:20             ` David Brownell
  5 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2007-08-07 21:17 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Tuesday 07 August 2007, Russell King wrote:

> 4. the description of the function implies that this function may be
>    called when we are not suspending:
> 
>   + * On platforms that support reduced functionality operating states, the
>   + * constraint may also need to be tested during resume() and probe() calls.

Right ... support for multiple "run" states will imply this same kind
of predicate, and I couldn't justify chosing a name which forces the
existence of more than one such predicate.  Ergo a generic name.

However, right now no platforms support them (cpufreq aside), so this
text could be rather harmlessly removed:  the second half of the sentence
doesn't apply to anything yet.  And maybe it *should* be removed, since
such platforms might do arbitrarily surprising stuff ... they might use
driver-level "reclock yourself" callbacks/notifiers (like the original
DPM stuff).


>    With SoCs with multiple power states affecting which clocks are
>    available, and the need in point (2) for the architecture code to
>    record which PM mode we're entering via the pm_ops set_target method,

Your point (2) was that it's "unclear" how that information becomes
available.  But the presumption of (4) here is that it's set_target().
So either it's clear enough, and (2) was wrong; or (4) has a false
premise; or both.  From false premises, anything can be proven...

I'd certainly not expect pm_ops.set_target() to apply in any context
other than the start of a suspend sequence.  Any platform choosing
to implement multiple run states necessarily provides some more
mechanisms...

(Purely as an example ... this is much the same kind of thing that goes
on with cpufreq updating a CPU clock that's also exposed through the
clock API:  multiple interfaces to the same PM-related state.  In both
cases, the public interface doesn't say how the implementation might
be done; it doesn't even care.)


>    calling clk_must_disable() outside of the suspend methods results in
>    this function essentially returning undefined values at driver probe
>    time.  Note: there is no locking between driver probing and the
>    set_target method.
> 
>    Moreover, if used in a driver probe() path, the return value could
>    well depend on the _last_ system suspend state entered, and would be
>    undefined for a system which hasn't been suspended from boot.

No, this platform maintains an invariant that the target PM state is
always PM_SUSPEND_ON except while suspending.  (So does ACPI, as I
recall.)  You're presuming a broken platform; but it's not broken...

Re locking, that issue would be addressed as part of supporting
multiple run states.  I still don't see suspend ops being involved
in non-suspend transitions.  But if a state change is in progress as
probe() is called, then suspend() should probably be called later.

- Dave

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 12:50           ` Russell King
                               ` (4 preceding siblings ...)
  2007-08-07 21:17             ` David Brownell
@ 2007-08-07 21:20             ` David Brownell
  5 siblings, 0 replies; 16+ messages in thread
From: David Brownell @ 2007-08-07 21:20 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Victor, Andrew Morton, linux-pm

On Tuesday 07 August 2007, Russell King wrote:

> Changing the function name to "clk_available_in_suspend()" addresses at
> least two of these points.

Except that it would

 (a) Preclude using this function in non-suspend contexts, including the
     "multiple run states" PM support that's regularly requested (and
     is thus IMO in the "why not plan on it" category).  The mechanism
     doesn't *NEED* to be constrained to be usable only from suspend().

 (b) Beg the question of which suspend state is involved ... something
     which has to date been intentionally hidden, since such states are
     so extremely system-specific (and since drivers misused that info).
     Drivers can care about *attributes* of an upcoming state (like
     whether a clock will be available, or a power domain, etc); fine.

The original notion for a name was of course clk_will_be_available(clk),
but that seemed too darn unwieldy to use.  Plus, logic like

	if (clk_must_disable(clk))
		clk_disable(clk);

(and similar) just seems inherently less likely to confuse ... it doesn't
need to introduce even one new term or concept, and focusses exclusively
on the key point:  whether clk_disable() is mandatory.


> The other two points are addressed by 
> providing a way for the method to be passed the desired system suspend
> state, which may be resolved by expanding pm_message_t to contain that
> information.

You do realize that pm_message_t was created to move *AWAY* from
passing an ID for the target system state down to the drivers?
The PM core previously passed down PM_SUSPEND_* integer codes.

Personally I detest pm_message_t ... "struct pm_message *" would
have been better, much less costly to expand (if needed), no new
typedefs, no pass-struct-by-value.  And in any case, there's work
afoot to have different methods for each different PM event, and
thus finally abolish pm_message_t.


> Finally, concerning merging this during the -rc phase, I'd much rather
> see the one liner simple build fix of adding the missing function
> prototype going into the -rc kernels, and then a similar patch to this
> going in during the next merge window.

If clk_must_disable() hadn't been "the plan of record" for over a
year, and already in use, I'd have been more in accord with that.

- Dave


> >  /*
> > - * Call this from platform driver suspend() to see how deeply to suspend.
> > + * This is called from clk_must_disable(), to see how deeply to suspend.
> >   * For example, some controllers (like OHCI) need one of the PLL clocks
> >   * in order to act as a wakeup source, and those are not available when
> >   * going into slow clock mode.
> > - *
> > - * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
> > - * the very same problem (but not using at91 main_clk), and it'd be better
> > - * to add one generic API rather than lots of platform-specific ones.
> >   */
> >  int at91_suspend_entering_slow_clock(void)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()
  2007-08-07 21:17             ` David Brownell
@ 2007-08-07 22:20               ` Rafael J. Wysocki
  0 siblings, 0 replies; 16+ messages in thread
From: Rafael J. Wysocki @ 2007-08-07 22:20 UTC (permalink / raw)
  To: David Brownell; +Cc: Andrew Victor, linux-pm, Andrew Morton, Russell King

On Tuesday, 7 August 2007 23:17, David Brownell wrote:
> On Tuesday 07 August 2007, Russell King wrote:
> 
> > 4. the description of the function implies that this function may be
> >    called when we are not suspending:
> > 
> >   + * On platforms that support reduced functionality operating states, the
> >   + * constraint may also need to be tested during resume() and probe() calls.
> 
> Right ... support for multiple "run" states will imply this same kind
> of predicate, and I couldn't justify chosing a name which forces the
> existence of more than one such predicate.  Ergo a generic name.
> 
> However, right now no platforms support them (cpufreq aside), so this
> text could be rather harmlessly removed:  the second half of the sentence
> doesn't apply to anything yet.  And maybe it *should* be removed, since
> such platforms might do arbitrarily surprising stuff ... they might use
> driver-level "reclock yourself" callbacks/notifiers (like the original
> DPM stuff).
> 
> 
> >    With SoCs with multiple power states affecting which clocks are
> >    available, and the need in point (2) for the architecture code to
> >    record which PM mode we're entering via the pm_ops set_target method,
> 
> Your point (2) was that it's "unclear" how that information becomes
> available.  But the presumption of (4) here is that it's set_target().
> So either it's clear enough, and (2) was wrong; or (4) has a false
> premise; or both.  From false premises, anything can be proven...
> 
> I'd certainly not expect pm_ops.set_target() to apply in any context
> other than the start of a suspend sequence.  Any platform choosing
> to implement multiple run states necessarily provides some more
> mechanisms...
> 
> (Purely as an example ... this is much the same kind of thing that goes
> on with cpufreq updating a CPU clock that's also exposed through the
> clock API:  multiple interfaces to the same PM-related state.  In both
> cases, the public interface doesn't say how the implementation might
> be done; it doesn't even care.)
> 
> 
> >    calling clk_must_disable() outside of the suspend methods results in
> >    this function essentially returning undefined values at driver probe
> >    time.  Note: there is no locking between driver probing and the
> >    set_target method.
> > 
> >    Moreover, if used in a driver probe() path, the return value could
> >    well depend on the _last_ system suspend state entered, and would be
> >    undefined for a system which hasn't been suspended from boot.
> 
> No, this platform maintains an invariant that the target PM state is
> always PM_SUSPEND_ON except while suspending.  (So does ACPI, as I
> recall.)  You're presuming a broken platform; but it's not broken...
> 
> Re locking, that issue would be addressed as part of supporting
> multiple run states.  I still don't see suspend ops being involved
> in non-suspend transitions.

Well, I'll go further and say that in principle the .suspend() callbacks have
nothing to do with non-suspend transitions.  In some situations they may
perform similar operations, but in that case the common code should be put
into a separate function and called _explicitly_ from the two places, to avoid
confusion.

Greetings,
Rafael


-- 
"Premature optimization is the root of all evil." - Donald Knuth

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-08-07 22:20 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-06 18:11 [patch 2.6.23-rc2 1/2] define clk_must_disable() David Brownell
2007-08-06 20:04 ` Russell King
2007-08-06 20:38   ` David Brownell
2007-08-06 21:03     ` David Brownell
2007-08-06 21:48     ` Russell King
2007-08-06 23:46       ` David Brownell
2007-08-07  5:23         ` Andrew Morton
2007-08-07 12:50           ` Russell King
2007-08-07 17:21             ` Andrew Morton
2007-08-07 17:25               ` Russell King
2007-08-07 20:15             ` David Brownell
2007-08-07 20:18             ` David Brownell
2007-08-07 21:04             ` David Brownell
2007-08-07 21:17             ` David Brownell
2007-08-07 22:20               ` Rafael J. Wysocki
2007-08-07 21:20             ` David Brownell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox