Re: [patch 2.6.23-rc2 1/2] define clk_must_disable()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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:
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux