SUPERH platform development
 help / color / mirror / Atom feed
* [PATCH] PM / Domains: Fix default system suspend/resume operations
From: Rafael J. Wysocki @ 2011-12-04 20:59 UTC (permalink / raw)
  To: Linux PM list; +Cc: LKML, Linux-sh list, Magnus Damm

From: Rafael J. Wysocki <rjw@sisk.pl>

Commit d23b9b00cdde5c93b914a172cecd57d5625fcd04 (PM / Domains: Rework
system suspend callback routines (v2)) broke the system suspend and
resume handling by devices belonging to generic PM domains, because
it used freeze/thaw callbacks instead of suspend/resume ones and
didn't initialize device callbacks for system suspend/resume
properly at all.  Fix those problems.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

This patch is on top of linux-pm/pm-domains.

Thanks,
Rafael

---
 drivers/base/power/domain.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

Index: linux/drivers/base/power/domain.c
=================================--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -1360,7 +1360,7 @@ static int pm_genpd_default_restore_stat
  */
 static int pm_genpd_default_suspend(struct device *dev)
 {
-	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze;
+	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.suspend;
 
 	return cb ? cb(dev) : pm_generic_suspend(dev);
 }
@@ -1371,7 +1371,7 @@ static int pm_genpd_default_suspend(stru
  */
 static int pm_genpd_default_suspend_late(struct device *dev)
 {
-	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze_late;
+	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.suspend_late;
 
 	return cb ? cb(dev) : pm_generic_suspend_noirq(dev);
 }
@@ -1382,7 +1382,7 @@ static int pm_genpd_default_suspend_late
  */
 static int pm_genpd_default_resume_early(struct device *dev)
 {
-	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw_early;
+	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.resume_early;
 
 	return cb ? cb(dev) : pm_generic_resume_noirq(dev);
 }
@@ -1393,7 +1393,7 @@ static int pm_genpd_default_resume_early
  */
 static int pm_genpd_default_resume(struct device *dev)
 {
-	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw;
+	int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.resume;
 
 	return cb ? cb(dev) : pm_generic_resume(dev);
 }
@@ -1487,10 +1487,10 @@ void pm_genpd_init(struct generic_pm_dom
 	genpd->domain.ops.complete = pm_genpd_complete;
 	genpd->dev_ops.save_state = pm_genpd_default_save_state;
 	genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
-	genpd->dev_ops.freeze = pm_genpd_default_suspend;
-	genpd->dev_ops.freeze_late = pm_genpd_default_suspend_late;
-	genpd->dev_ops.thaw_early = pm_genpd_default_resume_early;
-	genpd->dev_ops.thaw = pm_genpd_default_resume;
+	genpd->dev_ops.suspend = pm_genpd_default_suspend;
+	genpd->dev_ops.suspend_late = pm_genpd_default_suspend_late;
+	genpd->dev_ops.resume_early = pm_genpd_default_resume_early;
+	genpd->dev_ops.resume = pm_genpd_default_resume;
 	genpd->dev_ops.freeze = pm_genpd_default_freeze;
 	genpd->dev_ops.freeze_late = pm_genpd_default_freeze_late;
 	genpd->dev_ops.thaw_early = pm_genpd_default_thaw_early;

^ permalink raw reply

* Re: [PATCH-RFC 09/10] sh: switch to GENERIC_PCI_IOMAP
From: Michael S. Tsirkin @ 2011-12-04 10:48 UTC (permalink / raw)
  To: linux-sh

On Thu, Nov 24, 2011 at 10:20:37PM +0200, Michael S. Tsirkin wrote:
> sh copied pci_iomap from generic code, probably to avoid
> pulling the rest of iomap.c in.  Since that's in
> a separate file now, we can reuse the common implementation.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Sorry to nag, any ACKs/NACKs on the sh changes?
I intend to send this to Linus if there are no
objections. Thanks!

> ---
>  arch/sh/Kconfig           |    1 +
>  arch/sh/drivers/pci/pci.c |   23 -----------------------
>  2 files changed, 1 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
> index 5aeab58..ead1640 100644
> --- a/arch/sh/Kconfig
> +++ b/arch/sh/Kconfig
> @@ -857,6 +857,7 @@ config PCI
>  	bool "PCI support"
>  	depends on SYS_SUPPORTS_PCI
>  	select PCI_DOMAINS
> +	select GENERIC_PCI_IOMAP
>  	help
>  	  Find out whether you have a PCI motherboard. PCI is the name of a
>  	  bus system, i.e. the way the CPU talks to the other stuff inside
> diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
> index c2691af..11aaf2f 100644
> --- a/arch/sh/drivers/pci/pci.c
> +++ b/arch/sh/drivers/pci/pci.c
> @@ -393,29 +393,6 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
>  	return (void __iomem *)(chan->io_map_base + port);
>  }
>  
> -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
> -{
> -	resource_size_t start = pci_resource_start(dev, bar);
> -	resource_size_t len = pci_resource_len(dev, bar);
> -	unsigned long flags = pci_resource_flags(dev, bar);
> -
> -	if (unlikely(!len || !start))
> -		return NULL;
> -	if (maxlen && len > maxlen)
> -		len = maxlen;
> -
> -	if (flags & IORESOURCE_IO)
> -		return ioport_map_pci(dev, start, len);
> -	if (flags & IORESOURCE_MEM) {
> -		if (flags & IORESOURCE_CACHEABLE)
> -			return ioremap(start, len);
> -		return ioremap_nocache(start, len);
> -	}
> -
> -	return NULL;
> -}
> -EXPORT_SYMBOL(pci_iomap);
> -
>  void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
>  {
>  	iounmap(addr);
> -- 
> 1.7.5.53.gc233e

^ permalink raw reply

* RE: [PATCH 6/7] ARM: restart: only perform setup for restart when
From: Kukjin Kim @ 2011-12-03  9:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111203093012.GM9581@n2100.arm.linux.org.uk>

Russell King - ARM Linux wrote:
> 
> On Sat, Dec 03, 2011 at 06:23:09PM +0900, Kukjin Kim wrote:
> > Russell King - ARM Linux wrote:
> > >
> > > Ack?
> > >
> > > (If you're in the To: list I'm expecting a reply because this patch is
> > > touching something you're responsible for.  Thanks.)
> > >
> > > On Sun, Nov 06, 2011 at 05:33:35PM +0000, Russell King - ARM Linux
> wrote:
> > > > We only need to set the system up for a soft-restart if we're going
> to
> > > > be doing a soft-restart.  Provide a new function (soft_restart())
> which
> > > > does the setup and final call for this, and make platforms use it.
> > > > Eliminate the call to setup_restart() from the default handler.
> > > >
> > > > This means that platforms arch_reset() function is no longer called
> with
> > > > the page tables prepared for a soft-restart, and caches will still
> be
> > > > enabled.
> > > >
> > > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> >
> > Sorry for late response...
> >
> > For Samsung stuff:
> > Acked-by: Kukjin Kim <kgene.kim@samsung.com>
> 
> Too late, it's now part of devel-stable so I can't accept any more acks
> for this.  Sorry.

OK, I see.

But I did send my ack in the beginning of Nov on cover [0/7] like
following...
http://lists.infradead.org/pipermail/linux-arm-kernel/2011-November/071800.h
tml

So I didn't send my ack on this...

As a note, I'm sorting out header files, local headers in Samsung stuff as
per your suggestion and you can see them in the next week.

Anyway, thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply

* Re: [PATCH 6/7] ARM: restart: only perform setup for restart when
From: Russell King - ARM Linux @ 2011-12-03  9:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <000001ccb19d$2f9c5c60$8ed51520$%kim@samsung.com>

On Sat, Dec 03, 2011 at 06:23:09PM +0900, Kukjin Kim wrote:
> Russell King - ARM Linux wrote:
> > 
> > Ack?
> > 
> > (If you're in the To: list I'm expecting a reply because this patch is
> > touching something you're responsible for.  Thanks.)
> > 
> > On Sun, Nov 06, 2011 at 05:33:35PM +0000, Russell King - ARM Linux wrote:
> > > We only need to set the system up for a soft-restart if we're going to
> > > be doing a soft-restart.  Provide a new function (soft_restart()) which
> > > does the setup and final call for this, and make platforms use it.
> > > Eliminate the call to setup_restart() from the default handler.
> > >
> > > This means that platforms arch_reset() function is no longer called with
> > > the page tables prepared for a soft-restart, and caches will still be
> > > enabled.
> > >
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> 
> Sorry for late response...
> 
> For Samsung stuff:
> Acked-by: Kukjin Kim <kgene.kim@samsung.com>

Too late, it's now part of devel-stable so I can't accept any more acks
for this.  Sorry.

^ permalink raw reply

* RE: [PATCH 6/7] ARM: restart: only perform setup for restart when
From: Kukjin Kim @ 2011-12-03  9:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111117174247.GF9581@n2100.arm.linux.org.uk>

Russell King - ARM Linux wrote:
> 
> Ack?
> 
> (If you're in the To: list I'm expecting a reply because this patch is
> touching something you're responsible for.  Thanks.)
> 
> On Sun, Nov 06, 2011 at 05:33:35PM +0000, Russell King - ARM Linux wrote:
> > We only need to set the system up for a soft-restart if we're going to
> > be doing a soft-restart.  Provide a new function (soft_restart()) which
> > does the setup and final call for this, and make platforms use it.
> > Eliminate the call to setup_restart() from the default handler.
> >
> > This means that platforms arch_reset() function is no longer called with
> > the page tables prepared for a soft-restart, and caches will still be
> > enabled.
> >
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Sorry for late response...

For Samsung stuff:
Acked-by: Kukjin Kim <kgene.kim@samsung.com>

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

> > ---
> >  arch/arm/include/asm/system.h                     |    1 +
> >  arch/arm/kernel/process.c                         |   13 +++++++++++--
> >  arch/arm/mach-clps711x/include/mach/system.h      |    2 +-
> >  arch/arm/mach-ebsa110/include/mach/system.h       |    2 +-
> >  arch/arm/mach-footbridge/include/mach/system.h    |    2 +-
> >  arch/arm/mach-iop32x/include/mach/system.h        |    2 +-
> >  arch/arm/mach-iop33x/include/mach/system.h        |    2 +-
> >  arch/arm/mach-ixp4xx/include/mach/system.h        |    2 +-
> >  arch/arm/mach-ks8695/include/mach/system.h        |    2 +-
> >  arch/arm/mach-mmp/include/mach/system.h           |    4 ++--
> >  arch/arm/mach-mxs/system.c                        |    2 +-
> >  arch/arm/mach-pnx4008/include/mach/system.h       |    2 +-
> >  arch/arm/mach-pxa/reset.c                         |    2 +-
> >  arch/arm/mach-rpc/include/mach/system.h           |    2 +-
> >  arch/arm/mach-s3c2410/include/mach/system-reset.h |    4 ++--
> >  arch/arm/mach-s3c64xx/include/mach/system.h       |    2 +-
> >  arch/arm/mach-sa1100/include/mach/system.h        |    2 +-
> >  arch/arm/mach-shmobile/include/mach/system.h      |    2 +-
> >  arch/arm/mach-w90x900/include/mach/system.h       |    2 +-
> >  arch/arm/plat-mxc/system.c                        |    2 +-
> >  arch/arm/plat-spear/include/plat/system.h         |    2 +-
> >  21 files changed, 33 insertions(+), 23 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/system.h
> b/arch/arm/include/asm/system.h
> > index 984014b..fe7de75 100644
> > --- a/arch/arm/include/asm/system.h
> > +++ b/arch/arm/include/asm/system.h
> > @@ -101,6 +101,7 @@ extern int __pure cpu_architecture(void);
> >  extern void cpu_init(void);
> >
> >  void arm_machine_restart(char mode, const char *cmd);
> > +void soft_restart(unsigned long);
> >  extern void (*arm_pm_restart)(char str, const char *cmd);
> >
> >  #define UDBG_UNDEFINED	(1 << 0)
> > diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
> > index dca7971..52b4306 100644
> > --- a/arch/arm/kernel/process.c
> > +++ b/arch/arm/kernel/process.c
> > @@ -92,7 +92,7 @@ static int __init hlt_setup(char *__unused)
> >  __setup("nohlt", nohlt_setup);
> >  __setup("hlt", hlt_setup);
> >
> > -void arm_machine_restart(char mode, const char *cmd)
> > +void soft_restart(unsigned long addr)
> >  {
> >  	/* Disable interrupts first */
> >  	local_irq_disable();
> > @@ -114,7 +114,16 @@ void arm_machine_restart(char mode, const char
*cmd)
> >  	/* Push out any further dirty data, and ensure cache is empty */
> >  	flush_cache_all();
> >
> > -	/* Now call the architecture specific reboot code. */
> > +	cpu_reset(addr);
> > +}
> > +
> > +void arm_machine_restart(char mode, const char *cmd)
> > +{
> > +	/* Disable interrupts first */
> > +	local_irq_disable();
> > +	local_fiq_disable();
> > +
> > +	/* Call the architecture specific reboot code. */
> >  	arch_reset(mode, cmd);
> >  }
> >
> > diff --git a/arch/arm/mach-clps711x/include/mach/system.h
> b/arch/arm/mach-clps711x/include/mach/system.h
> > index f916cd7..6c11993 100644
> > --- a/arch/arm/mach-clps711x/include/mach/system.h
> > +++ b/arch/arm/mach-clps711x/include/mach/system.h
> > @@ -34,7 +34,7 @@ static inline void arch_idle(void)
> >
> >  static inline void arch_reset(char mode, const char *cmd)
> >  {
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  #endif
> > diff --git a/arch/arm/mach-ebsa110/include/mach/system.h
> b/arch/arm/mach-ebsa110/include/mach/system.h
> > index 9a26245..0d5df72 100644
> > --- a/arch/arm/mach-ebsa110/include/mach/system.h
> > +++ b/arch/arm/mach-ebsa110/include/mach/system.h
> > @@ -34,6 +34,6 @@ static inline void arch_idle(void)
> >  	asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc");
> >  }
> >
> > -#define arch_reset(mode, cmd)	cpu_reset(0x80000000)
> > +#define arch_reset(mode, cmd)	soft_restart(0x80000000)
> >
> >  #endif
> > diff --git a/arch/arm/mach-footbridge/include/mach/system.h
> b/arch/arm/mach-footbridge/include/mach/system.h
> > index 0b29315..249f895 100644
> > --- a/arch/arm/mach-footbridge/include/mach/system.h
> > +++ b/arch/arm/mach-footbridge/include/mach/system.h
> > @@ -24,7 +24,7 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  		/*
> >  		 * Jump into the ROM
> >  		 */
> > -		cpu_reset(0x41000000);
> > +		soft_restart(0x41000000);
> >  	} else {
> >  		if (machine_is_netwinder()) {
> >  			/* open up the SuperIO chip
> > diff --git a/arch/arm/mach-iop32x/include/mach/system.h b/arch/arm/mach-
> iop32x/include/mach/system.h
> > index a4b808f..4865a9b 100644
> > --- a/arch/arm/mach-iop32x/include/mach/system.h
> > +++ b/arch/arm/mach-iop32x/include/mach/system.h
> > @@ -30,5 +30,5 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  	*IOP3XX_PCSR = 0x30;
> >
> >  	/* Jump into ROM at address 0 */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> > diff --git a/arch/arm/mach-iop33x/include/mach/system.h b/arch/arm/mach-
> iop33x/include/mach/system.h
> > index f192a34..86d1b20 100644
> > --- a/arch/arm/mach-iop33x/include/mach/system.h
> > +++ b/arch/arm/mach-iop33x/include/mach/system.h
> > @@ -19,5 +19,5 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  	*IOP3XX_PCSR = 0x30;
> >
> >  	/* Jump into ROM at address 0 */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> > diff --git a/arch/arm/mach-ixp4xx/include/mach/system.h b/arch/arm/mach-
> ixp4xx/include/mach/system.h
> > index 54c0af7..24337d9 100644
> > --- a/arch/arm/mach-ixp4xx/include/mach/system.h
> > +++ b/arch/arm/mach-ixp4xx/include/mach/system.h
> > @@ -26,7 +26,7 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  {
> >  	if ( 1 && mode = 's') {
> >  		/* Jump into ROM at address 0 */
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  	} else {
> >  		/* Use on-chip reset capability */
> >
> > diff --git a/arch/arm/mach-ks8695/include/mach/system.h b/arch/arm/mach-
> ks8695/include/mach/system.h
> > index fb1dda9..ceb19c9 100644
> > --- a/arch/arm/mach-ks8695/include/mach/system.h
> > +++ b/arch/arm/mach-ks8695/include/mach/system.h
> > @@ -32,7 +32,7 @@ static void arch_reset(char mode, const char *cmd)
> >  	unsigned int reg;
> >
> >  	if (mode = 's')
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >
> >  	/* disable timer0 */
> >  	reg = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
> > diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-
> mmp/include/mach/system.h
> > index 1a8a25e..cb06379 100644
> > --- a/arch/arm/mach-mmp/include/mach/system.h
> > +++ b/arch/arm/mach-mmp/include/mach/system.h
> > @@ -19,8 +19,8 @@ static inline void arch_idle(void)
> >  static inline void arch_reset(char mode, const char *cmd)
> >  {
> >  	if (cpu_is_pxa168())
> > -		cpu_reset(0xffff0000);
> > +		soft_restart(0xffff0000);
> >  	else
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  }
> >  #endif /* __ASM_MACH_SYSTEM_H */
> > diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
> > index 20ec3bd..cab8836 100644
> > --- a/arch/arm/mach-mxs/system.c
> > +++ b/arch/arm/mach-mxs/system.c
> > @@ -53,7 +53,7 @@ void arch_reset(char mode, const char *cmd)
> >  	mdelay(50);
> >
> >  	/* We'll take a jump through zero as a poor second */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  static int __init mxs_arch_reset_init(void)
> > diff --git a/arch/arm/mach-pnx4008/include/mach/system.h
> b/arch/arm/mach-pnx4008/include/mach/system.h
> > index 5dda2bb..5d6384a 100644
> > --- a/arch/arm/mach-pnx4008/include/mach/system.h
> > +++ b/arch/arm/mach-pnx4008/include/mach/system.h
> > @@ -32,7 +32,7 @@ static void arch_idle(void)
> >
> >  static inline void arch_reset(char mode, const char *cmd)
> >  {
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  #endif
> > diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
> > index 01e9d64..b8bcda1 100644
> > --- a/arch/arm/mach-pxa/reset.c
> > +++ b/arch/arm/mach-pxa/reset.c
> > @@ -88,7 +88,7 @@ void arch_reset(char mode, const char *cmd)
> >  	switch (mode) {
> >  	case 's':
> >  		/* Jump into ROM at address 0 */
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  		break;
> >  	case 'g':
> >  		do_gpio_reset();
> > diff --git a/arch/arm/mach-rpc/include/mach/system.h b/arch/arm/mach-
> rpc/include/mach/system.h
> > index 45c7b93..a354f4d 100644
> > --- a/arch/arm/mach-rpc/include/mach/system.h
> > +++ b/arch/arm/mach-rpc/include/mach/system.h
> > @@ -23,5 +23,5 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  	/*
> >  	 * Jump into the ROM
> >  	 */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> > diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h
> b/arch/arm/mach-s3c2410/include/mach/system-reset.h
> > index 6faadce..913893d 100644
> > --- a/arch/arm/mach-s3c2410/include/mach/system-reset.h
> > +++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h
> > @@ -19,7 +19,7 @@ static void
> >  arch_reset(char mode, const char *cmd)
> >  {
> >  	if (mode = 's') {
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  	}
> >
> >  	if (s3c24xx_reset_hook)
> > @@ -28,5 +28,5 @@ arch_reset(char mode, const char *cmd)
> >  	arch_wdt_reset();
> >
> >  	/* we'll take a jump through zero as a poor second */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> > diff --git a/arch/arm/mach-s3c64xx/include/mach/system.h
> b/arch/arm/mach-s3c64xx/include/mach/system.h
> > index 2e58cb7..d8ca578 100644
> > --- a/arch/arm/mach-s3c64xx/include/mach/system.h
> > +++ b/arch/arm/mach-s3c64xx/include/mach/system.h
> > @@ -24,7 +24,7 @@ static void arch_reset(char mode, const char *cmd)
> >  		arch_wdt_reset();
> >
> >  	/* if all else fails, or mode was for soft, jump to 0 */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  #endif /* __ASM_ARCH_IRQ_H */
> > diff --git a/arch/arm/mach-sa1100/include/mach/system.h b/arch/arm/mach-
> sa1100/include/mach/system.h
> > index ba9da9f..345d35b 100644
> > --- a/arch/arm/mach-sa1100/include/mach/system.h
> > +++ b/arch/arm/mach-sa1100/include/mach/system.h
> > @@ -14,7 +14,7 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  {
> >  	if (mode = 's') {
> >  		/* Jump into ROM at address 0 */
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  	} else {
> >  		/* Use on-chip reset capability */
> >  		RSRR = RSRR_SWR;
> > diff --git a/arch/arm/mach-shmobile/include/mach/system.h
> b/arch/arm/mach-shmobile/include/mach/system.h
> > index 76a687e..956ac18 100644
> > --- a/arch/arm/mach-shmobile/include/mach/system.h
> > +++ b/arch/arm/mach-shmobile/include/mach/system.h
> > @@ -8,7 +8,7 @@ static inline void arch_idle(void)
> >
> >  static inline void arch_reset(char mode, const char *cmd)
> >  {
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  #endif
> > diff --git a/arch/arm/mach-w90x900/include/mach/system.h
> b/arch/arm/mach-w90x900/include/mach/system.h
> > index ce228bd..68875a1 100644
> > --- a/arch/arm/mach-w90x900/include/mach/system.h
> > +++ b/arch/arm/mach-w90x900/include/mach/system.h
> > @@ -33,7 +33,7 @@ static void arch_reset(char mode, const char *cmd)
> >  {
> >  	if (mode = 's') {
> >  		/* Jump into ROM at address 0 */
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  	} else {
> >  		__raw_writel(WTE | WTRE | WTCLK, WTCR);
> >  	}
> > diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
> > index 9dad8dc..b1cfc6a 100644
> > --- a/arch/arm/plat-mxc/system.c
> > +++ b/arch/arm/plat-mxc/system.c
> > @@ -70,7 +70,7 @@ void arch_reset(char mode, const char *cmd)
> >  	mdelay(50);
> >
> >  	/* we'll take a jump through zero as a poor second */
> > -	cpu_reset(0);
> > +	soft_restart(0);
> >  }
> >
> >  void mxc_arch_reset_init(void __iomem *base)
> > diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-
> spear/include/plat/system.h
> > index a235fa0..1171f22 100644
> > --- a/arch/arm/plat-spear/include/plat/system.h
> > +++ b/arch/arm/plat-spear/include/plat/system.h
> > @@ -31,7 +31,7 @@ static inline void arch_reset(char mode, const char
> *cmd)
> >  {
> >  	if (mode = 's') {
> >  		/* software reset, Jump into ROM at address 0 */
> > -		cpu_reset(0);
> > +		soft_restart(0);
> >  	} else {
> >  		/* hardware reset, Use on-chip reset capability */
> >  		sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
> > --
> > 1.7.4.4
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


^ permalink raw reply

* Hello
From: grace bugiba @ 2011-12-03  1:33 UTC (permalink / raw)
  To: linux-sh

Hello
My name is GRACE. i am a young girl from west Africa. I saw your email when i was browsing in internet and found out that we can make a good match and i will like you to contact me through my email address so that i can tell you more about myself. please my dear i will like you to contact me at my mail box Waiting for your mail, Your GRACE.

^ permalink raw reply

* Re: [PATCH] mmc: sh_mmcif: process requests asynchronously
From: Guennadi Liakhovetski @ 2011-12-02 15:54 UTC (permalink / raw)
  To: Magnus Damm; +Cc: linux-mmc, linux-sh, Chris Ball
In-Reply-To: <CANqRtoRvqZCuVQF0zeh9kyCnanfjA6k6ttWLOcf1y+-b4OcM_Q@mail.gmail.com>

Hi Magnus

On Sat, 3 Dec 2011, Magnus Damm wrote:

> Hi Guennadi,
> 
> On Thu, Dec 1, 2011 at 12:07 AM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > This patch converts the sh_mmcif MMC host driver to process requests
> > asynchronously instead of waiting in its .request() method for completion.
> > This is achieved by using threaded IRQs.
> >
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> 
> Thanks for your work on this! Interesting with threaded IRQ support.
> 
> Would it be possible to split this up into smaller chunks somehow?
> This rather big patch is more or less a rewrite of the driver - so it
> somehow looks to me like you're implementing multiple functional
> changes in a single commit. Maybe you're not doing that, but if so
> then at least the new code flow needs some documentation.

Yes, the diff is, unfortunately, pretty large. But so far I don't see a 
good way to split it. Essentially this patch introduces two changes:

1. asynchronous request processing
2. threaded IRQ

but, I don't think, splitting these changes would make sense. You don't 
want to implement (1) by another means, other than (2), because that'd be 
a double work. And if you already do (2) - you practically arrive at (1) 
too.

I'm not that much rewriting the driver either - most low-level functions 
are preserved, but many of them have to be rearranged. E.g., functions to 
process specific requests - single block read / write, multiple block r/w, 
etc., are split into to - the part before going to sleep, and the part 
after the hardware interrupt, which is now called from the IRQ thread. But 
the diff cannot show that as moved code, so, it looks huge.

But I'll spend some more time, thinking about possibilities to split or 
reduce the diff, maybe I get an idea...

> How about including some ascii-art style charts of the different
> states involved in reads and writes both for PIO and DMA? I'm thinking
> of something similar to the comments that describe the bus transaction
> and interrupts in drivers/i2c/busses/i2c-sh_mobile.c.

Ok, I'll try to add some documentation to the next version of the patch.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* Re: [PATCH] mmc: sh_mmcif: process requests asynchronously
From: Magnus Damm @ 2011-12-02 15:24 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: linux-mmc, linux-sh, Chris Ball
In-Reply-To: <Pine.LNX.4.64.1111301553330.22197@axis700.grange>

Hi Guennadi,

On Thu, Dec 1, 2011 at 12:07 AM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> This patch converts the sh_mmcif MMC host driver to process requests
> asynchronously instead of waiting in its .request() method for completion.
> This is achieved by using threaded IRQs.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks for your work on this! Interesting with threaded IRQ support.

Would it be possible to split this up into smaller chunks somehow?
This rather big patch is more or less a rewrite of the driver - so it
somehow looks to me like you're implementing multiple functional
changes in a single commit. Maybe you're not doing that, but if so
then at least the new code flow needs some documentation.

How about including some ascii-art style charts of the different
states involved in reads and writes both for PIO and DMA? I'm thinking
of something similar to the comments that describe the bus transaction
and interrupts in drivers/i2c/busses/i2c-sh_mobile.c.

Cheers,

/ magnus

^ permalink raw reply

* Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: Paul Mundt @ 2011-12-02  6:03 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <1322637713-15227-1-git-send-email-phil.edworthy@renesas.com>

On Wed, Nov 30, 2011 at 09:56:35AM +0000, phil.edworthy@renesas.com wrote:
> It's worth mentioning that this patch is essentially a work around for an 
> issue with write-back mode. sh2a_flush_icache_range is passed a large 
> address range which takes ages to flush/invalidate. For write-back mode, 
> instead of indexing on the address, perhaps we can walk through all the 
> cache entries and check for an address match. That's for another day...
> 
That's a common pitfall for anything using the address array for clearing
the entries. We have some simple heuristics in the cache-sh4.c code:

..
        /* If there are too many pages then just blow away the caches */
        if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
                local_flush_cache_all(NULL);
                return;
        }
..

A similar thing should probably be done for the SH-2/2A cases simply utilizing
CCR-based global invalidation.

> I agree that the other functions can be improved. I ignored them as the 
> main performance issue is with sh2a_flush_icache_range. I wasn't entirely 
> sure when some of the other functions are used. Are 
> sh2a__flush_wback_region and sh2a__flush_purge_region purely OC related? 
> And sh2a__flush_invalidate_region and sh2a_flush_icache_range work on both 
> the IC and OC?
> 
All of __flush_wback/purge/invalidate_region() are region based routines for OC
management. You get an idea of the abstraction from arch/sh/mm/flush-sh4.c. In general:

	__flush_wback_region - OC writeback
	__flush_invalidate_region - OC invalidate
	__flush_purge_region - OC writeback & invalidate

You can see a trivial usage example through the consistent DMA's
dma_cache_sync() and so on, relative to DMA direction.

flush_icache_range() handles I-cache invalidation for non-snoopable stores, and also
contends with things like I-cache aliases and the like. While semantically it's
not terribly complex, it's a bit of a sledgehammer given the different cases in
which it gets used. Whether the D-cache handling needs to be implemented or not
is likewise CPU dependent. In cases where the I-cache is not able to snoop
D-cache accesses we also need to deal with the D-cache explicitly. On the SMP
parts it's also further complicated by the fact that the bulk of the parts do
not broadcast I-cache block invalidates, and the snoop controller only handles
the D-cache (though the same I/D race exists given that the I-cache doesn't
have any connection to the snoop controller).

You can get a bit of an overview in Documentation/cachetlb.txt if you're
interested in some of the requirements.

^ permalink raw reply

* Re: [PATCH] mmc: sh_mmcif: simplify clock divisor calculation
From: Chris Ball @ 2011-12-01 18:24 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Andrew Morton, Andrei Warkentin, linux-mmc, linux-sh
In-Reply-To: <Pine.LNX.4.64.1111231551100.5635@axis700.grange>

Hi,

On Wed, Nov 23 2011, Guennadi Liakhovetski wrote:
> Replace ilog2(__rounddown_pow_of_two(x)) with the equivalent but much
> simpler fls(x) - 1.
>
> Reported-by: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>  drivers/mmc/host/sh_mmcif.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
> index c021482..824fee5 100644
> --- a/drivers/mmc/host/sh_mmcif.c
> +++ b/drivers/mmc/host/sh_mmcif.c
> @@ -16,6 +16,7 @@
>   *
>   */
>  
> +#include <linux/bitops.h>
>  #include <linux/clk.h>
>  #include <linux/completion.h>
>  #include <linux/delay.h>
> @@ -386,7 +387,7 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
>  		sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
>  	else
>  		sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
> -			(ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16));
> +				((fls(host->clk / clk) - 1) << 16));
>  
>  	sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
>  }

Thanks, pushed to mmc-next for 3.3.

- Chris.
-- 
Chris Ball   <cjb@laptop.org>   <http://printf.net/>
One Laptop Per Child

^ permalink raw reply

* Re: [PATCH] ARM: Kota2 mach-type update fix
From: Rafael J. Wysocki @ 2011-12-01  9:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111122060857.23951.50598.sendpatchset@w520>

On Tuesday, November 22, 2011, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
> 
> This patch adds kota2 to the in-kernel ARM mach-type file.
> 
> Basic board support is included in 3.2-rc and the mach-type
> has been registered in the ARM machine repository as
> 
> 3616 Renesas SH-Mobile kota2.x Board kota2 Yusuke Goda mainlined
> 
> The file arch/arm/tools/mach-types is however missing Kota2
> which makes build of sh73a0 based boards fail with:
> 
> arch/arm/mach-shmobile/platsmp.c: In function 'shmobile_smp_get_core_count':
> arch/arm/mach-shmobile/platsmp.c:28:2: error: implicit declaration of function 'machine_is_kota2'
> make[1]: *** [arch/arm/mach-shmobile/platsmp.o] Error 1
> 
> arch/arm/mach-shmobile/board-kota2.c:448:136: error: 'MACH_TYPE_KOTA2' undeclared here (not in a function)
> make[1]: *** [arch/arm/mach-shmobile/board-kota2.o] Error 1
> make: *** [arch/arm/mach-shmobile] Error 2
> 
> Signed-off-by: Magnus Damm <damm@opensource.se>

This patch is necessary to fix build of the Linus' tree for me with both
CONFIG_ARCH_SH73A0 and CONFIG_SMP set.

Tested-by: Rafael J. Wysocki <rjw@sisk.pl>

Thanks,
Rafael


> ---
> 
>  I propose that Paul Mundt merges this patch together with other
>  SH-Mobile ARM related fixes.
> 
>  arch/arm/tools/mach-types |    1 +
>  1 file changed, 1 insertion(+)
> 
> --- 0001/arch/arm/tools/mach-types
> +++ work/arch/arm/tools/mach-types	2011-11-14 16:55:38.000000000 +0900
> @@ -1123,5 +1123,6 @@ blissc			MACH_BLISSC		BLISSC			3491
>  thales_adc		MACH_THALES_ADC		THALES_ADC		3492
>  ubisys_p9d_evp		MACH_UBISYS_P9D_EVP	UBISYS_P9D_EVP		3493
>  atdgp318		MACH_ATDGP318		ATDGP318		3494
> +kota2			MACH_KOTA2		KOTA2			3616
>  smdk4212		MACH_SMDK4212		SMDK4212		3638
>  smdk4412		MACH_SMDK4412		SMDK4412		3765
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


^ permalink raw reply

* [Update 3x][PATCH 4/7] PM / Runtime: Use device PM QoS constraints (v2)
From: Rafael J. Wysocki @ 2011-11-30 23:20 UTC (permalink / raw)
  To: Linux PM list
  Cc: LKML, Linux-sh list, Magnus Damm, Guennadi Liakhovetski,
	Kevin Hilman, jean.pihet
In-Reply-To: <201111191500.34517.rjw@sisk.pl>

From: Rafael J. Wysocki <rjw@sisk.pl>

Make the runtime PM core use device PM QoS constraints to check if
it is allowed to suspend a given device, so that an error code is
returned if the device's own PM QoS constraint is negative or one of
its children has already been suspended for too long.  If this is
not the case, the maximum estimated time the device is allowed to be
suspended, computed as the minimum of the device's PM QoS constraint
and the PM QoS constraints of its children (reduced by the difference
between the current time and their suspend times) is stored in a new
device's PM field power.max_time_suspended_ns that can be used by
the device's subsystem or PM domain to decide whether or not to put
the device into lower-power (and presumably higher-latency) states
later (if the constraint is 0, which means "no constraint", the
power.max_time_suspended_ns is set to -1).

Additionally, the time of execution of the subsystem-level
.runtime_suspend() callback for the device is recorded in the new
power.suspend_time field for later use by the device's subsystem or
PM domain along with power.max_time_suspended_ns (it also is used
by the core code when the device's parent is suspended).

Introduce a new helper function,
pm_runtime_update_max_time_suspended(), allowing subsystems and PM
domains (or device drivers) to update the power.max_time_suspended_ns
field, for example after changing the power state of a suspended
device.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

Hi,

I had to rework the patch so that device_for_each_child() was not
run under dev->power.lock, which caused lockdep to complain loudly.

Thanks,
Rafael

---
 drivers/base/power/qos.c     |   24 ++++--
 drivers/base/power/runtime.c |  148 +++++++++++++++++++++++++++++++++++++------
 include/linux/pm.h           |    2 
 include/linux/pm_qos.h       |    3 
 include/linux/pm_runtime.h   |    5 +
 5 files changed, 154 insertions(+), 28 deletions(-)

Index: linux/include/linux/pm.h
=================================--- linux.orig/include/linux/pm.h
+++ linux/include/linux/pm.h
@@ -521,6 +521,8 @@ struct dev_pm_info {
 	unsigned long		active_jiffies;
 	unsigned long		suspended_jiffies;
 	unsigned long		accounting_timestamp;
+	ktime_t			suspend_time;
+	s64			max_time_suspended_ns;
 #endif
 	struct pm_subsys_data	*subsys_data;  /* Owned by the subsystem. */
 	struct pm_qos_constraints *constraints;
Index: linux/drivers/base/power/runtime.c
=================================--- linux.orig/drivers/base/power/runtime.c
+++ linux/drivers/base/power/runtime.c
@@ -279,6 +279,47 @@ static int rpm_callback(int (*cb)(struct
 	return retval != -EACCES ? retval : -EIO;
 }
 
+struct rpm_qos_data {
+	ktime_t time_now;
+	s64 constraint_ns;
+};
+
+/**
+ * rpm_update_qos_constraint - Update a given PM QoS constraint data.
+ * @dev: Device whose timing data to use.
+ * @data: PM QoS constraint data to update.
+ *
+ * Use the suspend timing data of @dev to update PM QoS constraint data pointed
+ * to by @data.
+ */
+static int rpm_update_qos_constraint(struct device *dev, void *data)
+{
+	struct rpm_qos_data *qos = data;
+	unsigned long flags;
+	s64 delta_ns;
+	int ret = 0;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	if (dev->power.max_time_suspended_ns < 0)
+		goto out;
+
+	delta_ns = dev->power.max_time_suspended_ns -
+		ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time));
+	if (delta_ns <= 0) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (qos->constraint_ns > delta_ns || qos->constraint_ns = 0)
+		qos->constraint_ns = delta_ns;
+
+ out:
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
+	return ret;
+}
+
 /**
  * rpm_suspend - Carry out runtime suspend of given device.
  * @dev: Device to suspend.
@@ -305,6 +346,7 @@ static int rpm_suspend(struct device *de
 {
 	int (*callback)(struct device *);
 	struct device *parent = NULL;
+	struct rpm_qos_data qos;
 	int retval;
 
 	trace_rpm_suspend(dev, rpmflags);
@@ -400,8 +442,38 @@ static int rpm_suspend(struct device *de
 		goto out;
 	}
 
+	qos.constraint_ns = __dev_pm_qos_read_value(dev);
+	if (qos.constraint_ns < 0) {
+		/* Negative constraint means "never suspend". */
+		retval = -EPERM;
+		goto out;
+	}
+	qos.constraint_ns *= NSEC_PER_USEC;
+	qos.time_now = ktime_get();
+
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
+	if (!dev->power.ignore_children) {
+		if (dev->power.irq_safe)
+			spin_unlock(&dev->power.lock);
+		else
+			spin_unlock_irq(&dev->power.lock);
+
+		retval = device_for_each_child(dev, &qos,
+					       rpm_update_qos_constraint);
+
+		if (dev->power.irq_safe)
+			spin_lock(&dev->power.lock);
+		else
+			spin_lock_irq(&dev->power.lock);
+
+		if (retval)
+			goto fail;
+	}
+
+	dev->power.suspend_time = qos.time_now;
+	dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1;
+
 	if (dev->pm_domain)
 		callback = dev->pm_domain->ops.runtime_suspend;
 	else if (dev->type && dev->type->pm)
@@ -414,27 +486,9 @@ static int rpm_suspend(struct device *de
 		callback = NULL;
 
 	retval = rpm_callback(callback, dev);
-	if (retval) {
-		__update_runtime_status(dev, RPM_ACTIVE);
-		dev->power.deferred_resume = false;
-		if (retval = -EAGAIN || retval = -EBUSY) {
-			dev->power.runtime_error = 0;
+	if (retval)
+		goto fail;
 
-			/*
-			 * If the callback routine failed an autosuspend, and
-			 * if the last_busy time has been updated so that there
-			 * is a new autosuspend expiration time, automatically
-			 * reschedule another autosuspend.
-			 */
-			if ((rpmflags & RPM_AUTO) &&
-			    pm_runtime_autosuspend_expiration(dev) != 0)
-				goto repeat;
-		} else {
-			pm_runtime_cancel_pending(dev);
-		}
-		wake_up_all(&dev->power.wait_queue);
-		goto out;
-	}
  no_callback:
 	__update_runtime_status(dev, RPM_SUSPENDED);
 	pm_runtime_deactivate_timer(dev);
@@ -466,6 +520,29 @@ static int rpm_suspend(struct device *de
 	trace_rpm_return_int(dev, _THIS_IP_, retval);
 
 	return retval;
+
+ fail:
+	__update_runtime_status(dev, RPM_ACTIVE);
+	dev->power.suspend_time = ktime_set(0, 0);
+	dev->power.max_time_suspended_ns = -1;
+	dev->power.deferred_resume = false;
+	if (retval = -EAGAIN || retval = -EBUSY) {
+		dev->power.runtime_error = 0;
+
+		/*
+		 * If the callback routine failed an autosuspend, and
+		 * if the last_busy time has been updated so that there
+		 * is a new autosuspend expiration time, automatically
+		 * reschedule another autosuspend.
+		 */
+		if ((rpmflags & RPM_AUTO) &&
+		    pm_runtime_autosuspend_expiration(dev) != 0)
+			goto repeat;
+	} else {
+		pm_runtime_cancel_pending(dev);
+	}
+	wake_up_all(&dev->power.wait_queue);
+	goto out;
 }
 
 /**
@@ -620,6 +697,9 @@ static int rpm_resume(struct device *dev
 	if (dev->power.no_callbacks)
 		goto no_callback;	/* Assume success. */
 
+	dev->power.suspend_time = ktime_set(0, 0);
+	dev->power.max_time_suspended_ns = -1;
+
 	__update_runtime_status(dev, RPM_RESUMING);
 
 	if (dev->pm_domain)
@@ -1279,6 +1359,9 @@ void pm_runtime_init(struct device *dev)
 	setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
 			(unsigned long)dev);
 
+	dev->power.suspend_time = ktime_set(0, 0);
+	dev->power.max_time_suspended_ns = -1;
+
 	init_waitqueue_head(&dev->power.wait_queue);
 }
 
@@ -1296,3 +1379,28 @@ void pm_runtime_remove(struct device *de
 	if (dev->power.irq_safe && dev->parent)
 		pm_runtime_put_sync(dev->parent);
 }
+
+/**
+ * pm_runtime_update_max_time_suspended - Update device's suspend time data.
+ * @dev: Device to handle.
+ * @delta_ns: Value to subtract from the device's max_time_suspended_ns field.
+ *
+ * Update the device's power.max_time_suspended_ns field by subtracting
+ * @delta_ns from it.  The resulting value of power.max_time_suspended_ns is
+ * never negative.
+ */
+void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) {
+		if (dev->power.max_time_suspended_ns > delta_ns)
+			dev->power.max_time_suspended_ns -= delta_ns;
+		else
+			dev->power.max_time_suspended_ns = 0;
+	}
+
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
Index: linux/include/linux/pm_runtime.h
=================================--- linux.orig/include/linux/pm_runtime.h
+++ linux/include/linux/pm_runtime.h
@@ -45,6 +45,8 @@ extern void pm_runtime_irq_safe(struct d
 extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
 extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
 extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+extern void pm_runtime_update_max_time_suspended(struct device *dev,
+						 s64 delta_ns);
 
 static inline bool pm_children_suspended(struct device *dev)
 {
@@ -148,6 +150,9 @@ static inline void pm_runtime_set_autosu
 static inline unsigned long pm_runtime_autosuspend_expiration(
 				struct device *dev) { return 0; }
 
+static inline void pm_runtime_update_max_time_suspended(struct device *dev,
+							s64 delta_ns) {}
+
 #endif /* !CONFIG_PM_RUNTIME */
 
 static inline int pm_runtime_idle(struct device *dev)
Index: linux/drivers/base/power/qos.c
=================================--- linux.orig/drivers/base/power/qos.c
+++ linux/drivers/base/power/qos.c
@@ -47,21 +47,29 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
 /**
- * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ *
+ * This routine must be called with dev->power.lock held.
+ */
+s32 __dev_pm_qos_read_value(struct device *dev)
+{
+	struct pm_qos_constraints *c = dev->power.constraints;
+
+	return c ? pm_qos_read_value(c) : 0;
+}
+
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
  * @dev: Device to get the PM QoS constraint value for.
  */
 s32 dev_pm_qos_read_value(struct device *dev)
 {
-	struct pm_qos_constraints *c;
 	unsigned long flags;
-	s32 ret = 0;
+	s32 ret;
 
 	spin_lock_irqsave(&dev->power.lock, flags);
-
-	c = dev->power.constraints;
-	if (c)
-		ret = pm_qos_read_value(c);
-
+	ret = __dev_pm_qos_read_value(dev);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
 
 	return ret;
Index: linux/include/linux/pm_qos.h
=================================--- linux.orig/include/linux/pm_qos.h
+++ linux/include/linux/pm_qos.h
@@ -78,6 +78,7 @@ int pm_qos_remove_notifier(int pm_qos_cl
 int pm_qos_request_active(struct pm_qos_request *req);
 s32 pm_qos_read_value(struct pm_qos_constraints *c);
 
+s32 __dev_pm_qos_read_value(struct device *dev);
 s32 dev_pm_qos_read_value(struct device *dev);
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 			   s32 value);
@@ -119,6 +120,8 @@ static inline int pm_qos_request_active(
 static inline s32 pm_qos_read_value(struct pm_qos_constraints *c)
 			{ return 0; }
 
+static inline s32 __dev_pm_qos_read_value(struct device *dev)
+			{ return 0; }
 static inline s32 dev_pm_qos_read_value(struct device *dev)
 			{ return 0; }
 static inline int dev_pm_qos_add_request(struct device *dev,


^ permalink raw reply

* Re: [PATCH (sh-2.6)] sh: do not export syscalls that are actually not implemented
From: Mike Frysinger @ 2011-11-30 20:56 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <1322685809-15587-1-git-send-email-carmelo.amoroso@st.com>

[-- Attachment #1: Type: Text/Plain, Size: 273 bytes --]

On Wednesday 30 November 2011 15:43:29 Carmelo AMOROSO wrote:
> Avoid user space to erroneously assume that a syscall is implemented
> by picking __NR_xxx from kernel headers that are actually mapped
> to sys_ni_syscall.

Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH (sh-2.6)] sh: do not export syscalls that are actually not implemented
From: Carmelo AMOROSO @ 2011-11-30 20:43 UTC (permalink / raw)
  To: linux-sh

Avoid user space to erroneously assume that a syscall is implemented
by picking __NR_xxx from kernel headers that are actually mapped
to sys_ni_syscall.

The following interfaces have been removed

sycall               | #
---------------------------
__NR_break           |  17
__NR_stty            |  31
__NR_gtty            |  32
__NR_prof            |  44
__NR_lock            |  53
__NR_mpxi            |  56
__NR_ulimit          |  58
__NR_oldolduname     |  59
__NR_select          |  82
__NR_profil          |  98
__NR_ioperm          | 101
__NR_iopl            | 110
__NR_idle            | 112
__NR_vm86old         | 113
__NR_create_module   | 127
__NR_get_kernel_syms | 130
__NR_afs_syscall     | 137
__NR_vm86            | 166
__NR_query_module    | 167
__NR_streams1        | 188
__NR_streams2        | 189
__NR_set_thread_area | 243
__NR_get_thread_area | 244
__NR_vserver         | 273
---------------------------

Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
---
 arch/sh/include/asm/unistd_32.h |   53 ++++++++++++++++++++-------------------
 1 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index 3432008..c7ee965 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -26,7 +26,7 @@
 #define __NR_mknod		 14
 #define __NR_chmod		 15
 #define __NR_lchown		 16
-#define __NR_break		 17
+		/* 17 __NR_break obsolete */
 #define __NR_oldstat		 18
 #define __NR_lseek		 19
 #define __NR_getpid		 20
@@ -40,11 +40,11 @@
 #define __NR_oldfstat		 28
 #define __NR_pause		 29
 #define __NR_utime		 30
-#define __NR_stty		 31
-#define __NR_gtty		 32
+		/* 31 __NR_stty obsolete */
+		/* 32 __NR_gtty	obsolete */
 #define __NR_access		 33
 #define __NR_nice		 34
-#define __NR_ftime		 35
+		/* 35 __NR_ftime 35 obsolete */
 #define __NR_sync		 36
 #define __NR_kill		 37
 #define __NR_rename		 38
@@ -53,7 +53,7 @@
 #define __NR_dup		 41
 #define __NR_pipe		 42
 #define __NR_times		 43
-#define __NR_prof		 44
+		/* 44 __NR_prof obsolete */
 #define __NR_brk		 45
 #define __NR_setgid		 46
 #define __NR_getgid		 47
@@ -62,13 +62,13 @@
 #define __NR_getegid		 50
 #define __NR_acct		 51
 #define __NR_umount2		 52
-#define __NR_lock		 53
+		/* 53 __NR_lock obsolete */
 #define __NR_ioctl		 54
 #define __NR_fcntl		 55
-#define __NR_mpx		 56
+		/* 56 __NR_mpxi obsolete */
 #define __NR_setpgid		 57
-#define __NR_ulimit		 58
-#define __NR_oldolduname	 59
+		/* 58 __NR_ulimit obsolete */
+		/* 59 __NR_oldolduname obsolete */
 #define __NR_umask		 60
 #define __NR_chroot		 61
 #define __NR_ustat		 62
@@ -91,7 +91,7 @@
 #define __NR_settimeofday	 79
 #define __NR_getgroups		 80
 #define __NR_setgroups		 81
-#define __NR_select		 82
+		/* 82 __NR_select obsolete */
 #define __NR_symlink		 83
 #define __NR_oldlstat		 84
 #define __NR_readlink		 85
@@ -107,10 +107,10 @@
 #define __NR_fchown		 95
 #define __NR_getpriority	 96
 #define __NR_setpriority	 97
-#define __NR_profil		 98
+		/* 98 __NR_profil obsolete */
 #define __NR_statfs		 99
 #define __NR_fstatfs		100
-#define __NR_ioperm		101
+		/* 101 __NR_ioperm obsolete */
 #define __NR_socketcall		102
 #define __NR_syslog		103
 #define __NR_setitimer		104
@@ -119,10 +119,10 @@
 #define __NR_lstat		107
 #define __NR_fstat		108
 #define __NR_olduname		109
-#define __NR_iopl		110
+		/* 110 __NR_iopl obsolete */
 #define __NR_vhangup		111
-#define __NR_idle		112
-#define __NR_vm86old		113
+		/* 112 __NR_idle obsolete */
+		/* 113 __NR_vm86old	obsolete */
 #define __NR_wait4		114
 #define __NR_swapoff		115
 #define __NR_sysinfo		116
@@ -136,17 +136,17 @@
 #define __NR_adjtimex		124
 #define __NR_mprotect		125
 #define __NR_sigprocmask	126
-#define __NR_create_module	127
+		/* 127 __NR_create_module obsolete */
 #define __NR_init_module	128
 #define __NR_delete_module	129
-#define __NR_get_kernel_syms	130
+		/* 130 __NR_get_kernel_syms obsolete */
 #define __NR_quotactl		131
 #define __NR_getpgid		132
 #define __NR_fchdir		133
 #define __NR_bdflush		134
 #define __NR_sysfs		135
 #define __NR_personality	136
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+		/* 137 __NR_afs_syscall	obsolete */
 #define __NR_setfsuid		138
 #define __NR_setfsgid		139
 #define __NR__llseek		140
@@ -175,8 +175,8 @@
 #define __NR_mremap		163
 #define __NR_setresuid		164
 #define __NR_getresuid		165
-#define __NR_vm86		166
-#define __NR_query_module	167
+		/* 166 __NR_vm86 obsolete */
+		/* 167 __NR_query_module obsolete */
 #define __NR_poll		168
 #define __NR_nfsservctl		169
 #define __NR_setresgid		170
@@ -197,8 +197,8 @@
 #define __NR_capset		185
 #define __NR_sigaltstack	186
 #define __NR_sendfile		187
-#define __NR_streams1		188	/* some people actually want it */
-#define __NR_streams2		189	/* some people actually want it */
+		/* 188 __NR_streams1 obsolete */
+		/* 189 __NR_streams2 obsolete */
 #define __NR_vfork		190
 #define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
 #define __NR_mmap2		192
@@ -231,6 +231,7 @@
 #define __NR_madvise		219
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
+/* 222 is unused */
 /* 223 is unused */
 #define __NR_gettid		224
 #define __NR_readahead		225
@@ -251,15 +252,15 @@
 #define __NR_futex		240
 #define __NR_sched_setaffinity	241
 #define __NR_sched_getaffinity	242
-#define __NR_set_thread_area	243
-#define __NR_get_thread_area	244
+		/* 243 __NR_set_thread_area obsolete */
+		/* 244 __NR_get_thread_area obsolete */
 #define __NR_io_setup		245
 #define __NR_io_destroy		246
 #define __NR_io_getevents	247
 #define __NR_io_submit		248
 #define __NR_io_cancel		249
 #define __NR_fadvise64		250
-
+/* 251 unused */
 #define __NR_exit_group		252
 #define __NR_lookup_dcookie	253
 #define __NR_epoll_create	254
@@ -281,7 +282,7 @@
 #define __NR_tgkill		270
 #define __NR_utimes		271
 #define __NR_fadvise64_64	272
-#define __NR_vserver		273
+		/* 273 __NR_vserver obsolete */
 #define __NR_mbind              274
 #define __NR_get_mempolicy      275
 #define __NR_set_mempolicy      276
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH] mmc: sh_mmcif: process requests asynchronously
From: Guennadi Liakhovetski @ 2011-11-30 15:07 UTC (permalink / raw)
  To: linux-mmc; +Cc: linux-sh, Chris Ball, Magnus Damm

This patch converts the sh_mmcif MMC host driver to process requests 
asynchronously instead of waiting in its .request() method for completion. 
This is achieved by using threaded IRQs.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 824fee5..d077da4 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -123,6 +124,11 @@
 #define MASK_MRBSYTO		(1 << 1)
 #define MASK_MRSPTO		(1 << 0)
 
+#define START_CMD_MASK		(MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
+				 MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
+				 MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
+				 MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
+
 /* CE_HOST_STS1 */
 #define STS1_CMDSEQ		(1 << 31)
 
@@ -162,19 +169,38 @@ enum mmcif_state {
 	STATE_IOS,
 };
 
+enum mmcif_wait_for {
+	MMCIF_WAIT_FOR_REQUEST,
+	MMCIF_WAIT_FOR_CMD,
+	MMCIF_WAIT_FOR_MREAD,
+	MMCIF_WAIT_FOR_MWRITE,
+	MMCIF_WAIT_FOR_READ,
+	MMCIF_WAIT_FOR_WRITE,
+	MMCIF_WAIT_FOR_READ_END,
+	MMCIF_WAIT_FOR_WRITE_END,
+	MMCIF_WAIT_FOR_STOP,
+};
+
 struct sh_mmcif_host {
 	struct mmc_host *mmc;
 	struct mmc_data *data;
+	struct mmc_request *mrq;
 	struct platform_device *pd;
 	struct clk *hclk;
 	unsigned int clk;
 	int bus_width;
 	bool sd_error;
+	bool dying;
 	long timeout;
 	void __iomem *addr;
-	struct completion intr_wait;
+	u32 *pio_ptr;
+	spinlock_t lock;		/* protect host->state */
 	enum mmcif_state state;
-	spinlock_t lock;
+	enum mmcif_wait_for wait_for;
+	struct delayed_work timeout_work;
+	size_t blocksize;
+	int sg_idx;
+	int sg_blkidx;
 	bool power;
 	bool card_present;
 
@@ -409,7 +435,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
 static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
 {
 	u32 state1, state2;
-	int ret, timeout = 10000000;
+	int ret, timeout;
 
 	host->sd_error = false;
 
@@ -421,155 +447,97 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
 	if (state1 & STS1_CMDSEQ) {
 		sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
 		sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK);
-		while (1) {
-			timeout--;
-			if (timeout < 0) {
-				dev_err(&host->pd->dev,
-					"Forceed end of command sequence timeout err\n");
-				return -EIO;
-			}
+		for (timeout = 10000000; timeout; timeout--) {
 			if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
-								& STS1_CMDSEQ))
+			      & STS1_CMDSEQ))
 				break;
 			mdelay(1);
 		}
+		if (!timeout) {
+			dev_err(&host->pd->dev,
+				"Forceed end of command sequence timeout err\n");
+			return -EIO;
+		}
 		sh_mmcif_sync_reset(host);
 		dev_dbg(&host->pd->dev, "Forced end of command sequence\n");
 		return -EIO;
 	}
 
 	if (state2 & STS2_CRC_ERR) {
-		dev_dbg(&host->pd->dev, ": Happened CRC error\n");
+		dev_dbg(&host->pd->dev, ": CRC error\n");
 		ret = -EIO;
 	} else if (state2 & STS2_TIMEOUT_ERR) {
-		dev_dbg(&host->pd->dev, ": Happened Timeout error\n");
+		dev_dbg(&host->pd->dev, ": Timeout\n");
 		ret = -ETIMEDOUT;
 	} else {
-		dev_dbg(&host->pd->dev, ": Happened End/Index error\n");
+		dev_dbg(&host->pd->dev, ": End/Index error\n");
 		ret = -EIO;
 	}
 	return ret;
 }
 
-static int sh_mmcif_single_read(struct sh_mmcif_host *host,
-					struct mmc_request *mrq)
+static void sh_mmcif_single_read(struct sh_mmcif_host *host,
+				 struct mmc_request *mrq)
 {
-	struct mmc_data *data = mrq->data;
-	long time;
-	u32 blocksize, i, *p = sg_virt(data->sg);
+	host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+			   BLOCK_SIZE_MASK) + 3;
+
+	host->wait_for = MMCIF_WAIT_FOR_READ;
+	schedule_delayed_work(&host->timeout_work, host->timeout);
 
 	/* buf read enable */
 	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-			host->timeout);
-	if (time <= 0 || host->sd_error)
-		return sh_mmcif_error_manage(host);
-
-	blocksize = (BLOCK_SIZE_MASK &
-			sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
-	for (i = 0; i < blocksize / 4; i++)
-		*p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
-
-	/* buffer read end */
-	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-			host->timeout);
-	if (time <= 0 || host->sd_error)
-		return sh_mmcif_error_manage(host);
-
-	return 0;
 }
 
-static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
-					struct mmc_request *mrq)
+static void sh_mmcif_multi_read(struct sh_mmcif_host *host,
+				struct mmc_request *mrq)
 {
 	struct mmc_data *data = mrq->data;
-	long time;
-	u32 blocksize, i, j, sec, *p;
-
-	blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
-						     MMCIF_CE_BLOCK_SET);
-	for (j = 0; j < data->sg_len; j++) {
-		p = sg_virt(data->sg);
-		for (sec = 0; sec < data->sg->length / blocksize; sec++) {
-			sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
-			/* buf read enable */
-			time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-				host->timeout);
-
-			if (time <= 0 || host->sd_error)
-				return sh_mmcif_error_manage(host);
-
-			for (i = 0; i < blocksize / 4; i++)
-				*p++ = sh_mmcif_readl(host->addr,
-						      MMCIF_CE_DATA);
-		}
-		if (j < data->sg_len - 1)
-			data->sg++;
-	}
-	return 0;
+
+	if (!data->sg_len || !data->sg->length)
+		return;
+
+	host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+		BLOCK_SIZE_MASK;
+
+	host->wait_for = MMCIF_WAIT_FOR_MREAD;
+	host->sg_idx = 0;
+	host->sg_blkidx = 0;
+	host->pio_ptr = sg_virt(data->sg);
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
 }
 
-static int sh_mmcif_single_write(struct sh_mmcif_host *host,
+static void sh_mmcif_single_write(struct sh_mmcif_host *host,
 					struct mmc_request *mrq)
 {
-	struct mmc_data *data = mrq->data;
-	long time;
-	u32 blocksize, i, *p = sg_virt(data->sg);
+	host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+			   BLOCK_SIZE_MASK) + 3;
 
-	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+	host->wait_for = MMCIF_WAIT_FOR_WRITE;
+	schedule_delayed_work(&host->timeout_work, host->timeout);
 
 	/* buf write enable */
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-			host->timeout);
-	if (time <= 0 || host->sd_error)
-		return sh_mmcif_error_manage(host);
-
-	blocksize = (BLOCK_SIZE_MASK &
-			sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
-	for (i = 0; i < blocksize / 4; i++)
-		sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
-
-	/* buffer write end */
-	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
-
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-			host->timeout);
-	if (time <= 0 || host->sd_error)
-		return sh_mmcif_error_manage(host);
-
-	return 0;
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
 }
 
-static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
-						struct mmc_request *mrq)
+static void sh_mmcif_multi_write(struct sh_mmcif_host *host,
+				struct mmc_request *mrq)
 {
 	struct mmc_data *data = mrq->data;
-	long time;
-	u32 i, sec, j, blocksize, *p;
 
-	blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
-						     MMCIF_CE_BLOCK_SET);
-
-	for (j = 0; j < data->sg_len; j++) {
-		p = sg_virt(data->sg);
-		for (sec = 0; sec < data->sg->length / blocksize; sec++) {
-			sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
-			/* buf write enable*/
-			time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-				host->timeout);
+	if (!data->sg_len || !data->sg->length)
+		return;
 
-			if (time <= 0 || host->sd_error)
-				return sh_mmcif_error_manage(host);
+	host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+		BLOCK_SIZE_MASK;
 
-			for (i = 0; i < blocksize / 4; i++)
-				sh_mmcif_writel(host->addr,
-						MMCIF_CE_DATA, *p++);
-		}
-		if (j < data->sg_len - 1)
-			data->sg++;
-	}
-	return 0;
+	host->wait_for = MMCIF_WAIT_FOR_MWRITE;
+	host->sg_idx = 0;
+	host->sg_blkidx = 0;
+	host->pio_ptr = sg_virt(data->sg);
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
 }
 
 static void sh_mmcif_get_response(struct sh_mmcif_host *host,
@@ -666,57 +634,48 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
 }
 
 static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
-				struct mmc_request *mrq, u32 opc)
+			       struct mmc_request *mrq, u32 opc)
 {
-	int ret;
-
 	switch (opc) {
 	case MMC_READ_MULTIPLE_BLOCK:
-		ret = sh_mmcif_multi_read(host, mrq);
-		break;
+		sh_mmcif_multi_read(host, mrq);
+		return 0;
 	case MMC_WRITE_MULTIPLE_BLOCK:
-		ret = sh_mmcif_multi_write(host, mrq);
-		break;
+		sh_mmcif_multi_write(host, mrq);
+		return 0;
 	case MMC_WRITE_BLOCK:
-		ret = sh_mmcif_single_write(host, mrq);
-		break;
+		sh_mmcif_single_write(host, mrq);
+		return 0;
 	case MMC_READ_SINGLE_BLOCK:
 	case MMC_SEND_EXT_CSD:
-		ret = sh_mmcif_single_read(host, mrq);
-		break;
-	default:
-		dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
-		ret = -EINVAL;
-		break;
+		sh_mmcif_single_read(host, mrq);
+		return 0;
 	}
-	return ret;
+	dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
+	return -EINVAL;
 }
 
 static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
-			struct mmc_request *mrq, struct mmc_command *cmd)
+			       struct mmc_request *mrq)
 {
-	long time;
-	int ret = 0, mask = 0;
+	struct mmc_command *cmd = mrq->cmd;
 	u32 opc = cmd->opcode;
+	u32 mask;
 
 	switch (opc) {
-	/* respons busy check */
+	/* response busy check */
 	case MMC_SWITCH:
 	case MMC_STOP_TRANSMISSION:
 	case MMC_SET_WRITE_PROT:
 	case MMC_CLR_WRITE_PROT:
 	case MMC_ERASE:
 	case MMC_GEN_CMD:
-		mask = MASK_MRBSYE;
+		mask = START_CMD_MASK | MASK_MRBSYE;
 		break;
 	default:
-		mask = MASK_MCRSPE;
+		mask = START_CMD_MASK | MASK_MCRSPE;
 		break;
 	}
-	mask |=	MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
-		MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
-		MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
-		MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
 
 	if (host->data) {
 		sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
@@ -732,61 +691,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
 	/* set cmd */
 	sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
 
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-		host->timeout);
-	if (time <= 0) {
-		cmd->error = sh_mmcif_error_manage(host);
-		return;
-	}
-	if (host->sd_error) {
-		switch (cmd->opcode) {
-		case MMC_ALL_SEND_CID:
-		case MMC_SELECT_CARD:
-		case MMC_APP_CMD:
-			cmd->error = -ETIMEDOUT;
-			break;
-		default:
-			dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n",
-					cmd->opcode);
-			cmd->error = sh_mmcif_error_manage(host);
-			break;
-		}
-		host->sd_error = false;
-		return;
-	}
-	if (!(cmd->flags & MMC_RSP_PRESENT)) {
-		cmd->error = 0;
-		return;
-	}
-	sh_mmcif_get_response(host, cmd);
-	if (host->data) {
-		if (!host->dma_active) {
-			ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
-		} else {
-			long time -				wait_for_completion_interruptible_timeout(&host->dma_complete,
-									  host->timeout);
-			if (!time)
-				ret = -ETIMEDOUT;
-			else if (time < 0)
-				ret = time;
-			sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
-					BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
-			host->dma_active = false;
-		}
-		if (ret < 0)
-			mrq->data->bytes_xfered = 0;
-		else
-			mrq->data->bytes_xfered -				mrq->data->blocks * mrq->data->blksz;
-	}
-	cmd->error = ret;
+	host->wait_for = MMCIF_WAIT_FOR_CMD;
+	schedule_delayed_work(&host->timeout_work, host->timeout);
 }
 
 static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
-		struct mmc_request *mrq, struct mmc_command *cmd)
+			      struct mmc_request *mrq)
 {
-	long time;
+	struct mmc_command *cmd = mrq->stop;
 
 	if (mrq->cmd->opcode = MMC_READ_MULTIPLE_BLOCK)
 		sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
@@ -798,14 +710,8 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
 		return;
 	}
 
-	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
-			host->timeout);
-	if (time <= 0 || host->sd_error) {
-		cmd->error = sh_mmcif_error_manage(host);
-		return;
-	}
-	sh_mmcif_get_cmd12response(host, cmd);
-	cmd->error = 0;
+	host->wait_for = MMCIF_WAIT_FOR_STOP;
+	schedule_delayed_work(&host->timeout_work, host->timeout);
 }
 
 static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -813,6 +719,8 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	struct sh_mmcif_host *host = mmc_priv(mmc);
 	unsigned long flags;
 
+	dev_info(mmc->parent, "%s(%u), data %p\n", __func__, mrq->cmd->opcode, mrq->data);
+
 	spin_lock_irqsave(&host->lock, flags);
 	if (host->state != STATE_IDLE) {
 		spin_unlock_irqrestore(&host->lock, flags);
@@ -844,23 +752,11 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	default:
 		break;
 	}
+
+	host->mrq = mrq;
 	host->data = mrq->data;
-	if (mrq->data) {
-		if (mrq->data->flags & MMC_DATA_READ) {
-			if (host->chan_rx)
-				sh_mmcif_start_dma_rx(host);
-		} else {
-			if (host->chan_tx)
-				sh_mmcif_start_dma_tx(host);
-		}
-	}
-	sh_mmcif_start_cmd(host, mrq, mrq->cmd);
-	host->data = NULL;
 
-	if (!mrq->cmd->error && mrq->stop)
-		sh_mmcif_stop_cmd(host, mrq, mrq->stop);
-	host->state = STATE_IDLE;
-	mmc_request_done(mmc, mrq);
+	sh_mmcif_start_cmd(host, mrq);
 }
 
 static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -935,9 +831,268 @@ static struct mmc_host_ops sh_mmcif_ops = {
 	.get_cd		= sh_mmcif_get_cd,
 };
 
-static void sh_mmcif_detect(struct mmc_host *mmc)
+static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
+{
+	struct mmc_command *cmd = host->mrq->cmd;
+	long time;
+
+	if (host->sd_error) {
+		switch (cmd->opcode) {
+		case MMC_ALL_SEND_CID:
+		case MMC_SELECT_CARD:
+		case MMC_APP_CMD:
+			cmd->error = -ETIMEDOUT;
+			host->sd_error = false;
+			break;
+		default:
+			cmd->error = sh_mmcif_error_manage(host);
+			dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n",
+				cmd->opcode, cmd->error);
+			break;
+		}
+		return false;
+	}
+	if (!(cmd->flags & MMC_RSP_PRESENT)) {
+		cmd->error = 0;
+		return false;
+	}
+
+	sh_mmcif_get_response(host, cmd);
+
+	if (!host->data)
+		return false;
+
+	if (host->mrq->data->flags & MMC_DATA_READ) {
+		if (host->chan_rx)
+			sh_mmcif_start_dma_rx(host);
+	} else {
+		if (host->chan_tx)
+			sh_mmcif_start_dma_tx(host);
+	}
+
+	if (!host->dma_active) {
+		host->data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode);
+		if (!host->data->error)
+			return true;
+		return false;
+	}
+
+	/* Running in the IRQ thread, can sleep */
+	time = wait_for_completion_interruptible_timeout(&host->dma_complete,
+							 host->timeout);
+	if (host->sd_error) {
+		/* Woken up by an error IRQ: abort DMA */
+		if (host->data->flags & MMC_DATA_READ)
+			dmaengine_terminate_all(host->chan_rx);
+		else
+			dmaengine_terminate_all(host->chan_tx);
+		host->data->error = sh_mmcif_error_manage(host);
+	} else if (!time) {
+		host->data->error = -ETIMEDOUT;
+	} else if (time < 0) {
+		host->data->error = time;
+	}
+	sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
+			BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+	host->dma_active = false;
+
+	if (host->data->error)
+		host->data->bytes_xfered = 0;
+
+	return false;
+}
+
+static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p)
 {
-	mmc_detect_change(mmc, 0);
+	struct mmc_data *data = host->mrq->data;
+
+	host->sg_blkidx += host->blocksize;
+
+	/* data->sg->length must be a multiple of host->blocksize? */
+	BUG_ON(host->sg_blkidx > data->sg->length);
+
+	if (host->sg_blkidx = data->sg->length) {
+		host->sg_blkidx = 0;
+		if (++host->sg_idx < data->sg_len)
+			host->pio_ptr = sg_virt(++data->sg);
+	} else {
+		host->pio_ptr = p;
+	}
+
+	if (host->sg_idx = data->sg_len)
+		return false;
+
+	return true;
+}
+
+static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
+{
+	struct mmc_data *data = host->mrq->data;
+	u32 *p = host->pio_ptr;
+	int i;
+
+	if (host->sd_error) {
+		data->error = sh_mmcif_error_manage(host);
+		return false;
+	}
+
+	BUG_ON(!data->sg->length);
+
+	for (i = 0; i < host->blocksize / 4; i++)
+		*p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
+
+	if (!sh_mmcif_next_block(host, p))
+		return false;
+
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
+
+	return true;
+}
+
+static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
+{
+	struct mmc_data *data = host->mrq->data;
+	u32 *p = host->pio_ptr;
+	int i;
+
+	if (host->sd_error) {
+		data->error = sh_mmcif_error_manage(host);
+		return false;
+	}
+
+	BUG_ON(!data->sg->length);
+
+	for (i = 0; i < host->blocksize / 4; i++)
+		sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
+
+	if (!sh_mmcif_next_block(host, p))
+		return false;
+
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+
+	return true;
+}
+
+static bool sh_mmcif_read_block(struct sh_mmcif_host *host)
+{
+	struct mmc_data *data = host->mrq->data;
+	u32 *p = sg_virt(data->sg);
+	int i;
+
+	if (host->sd_error) {
+		data->error = sh_mmcif_error_manage(host);
+		return false;
+	}
+
+	for (i = 0; i < host->blocksize / 4; i++)
+		*p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
+
+	/* buffer read end */
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
+	host->wait_for = MMCIF_WAIT_FOR_READ_END;
+
+	return true;
+}
+
+static bool sh_mmcif_write_block(struct sh_mmcif_host *host)
+{
+	struct mmc_data *data = host->mrq->data;
+	u32 *p = sg_virt(data->sg);
+	int i;
+
+	if (host->sd_error) {
+		data->error = sh_mmcif_error_manage(host);
+		return false;
+	}
+
+	for (i = 0; i < host->blocksize / 4; i++)
+		sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
+
+	/* buffer write end */
+	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
+	host->wait_for = MMCIF_WAIT_FOR_WRITE_END;
+
+	return true;
+}
+
+static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
+{
+	struct sh_mmcif_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+
+	cancel_delayed_work_sync(&host->timeout_work);
+
+	/*
+	 * All handlers return true, if processing continues, and false, if the
+	 * request has to be completed - successfully or not
+	 */
+	switch (host->wait_for) {
+	case MMCIF_WAIT_FOR_REQUEST:
+		/* We're too late, the timeout has already kicked in */
+		return IRQ_HANDLED;
+	case MMCIF_WAIT_FOR_CMD:
+		if (sh_mmcif_end_cmd(host))
+			/* Wait for data */
+			return IRQ_HANDLED;
+		break;
+	case MMCIF_WAIT_FOR_MREAD:
+		if (sh_mmcif_mread_block(host))
+			/* Wait for more data */
+			return IRQ_HANDLED;
+		break;
+	case MMCIF_WAIT_FOR_READ:
+		if (sh_mmcif_read_block(host))
+			/* Wait for data end */
+			return IRQ_HANDLED;
+		break;
+	case MMCIF_WAIT_FOR_MWRITE:
+		if (sh_mmcif_mwrite_block(host))
+			/* Wait data to write */
+			return IRQ_HANDLED;
+		break;
+	case MMCIF_WAIT_FOR_WRITE:
+		if (sh_mmcif_write_block(host))
+			/* Wait for data end */
+			return IRQ_HANDLED;
+		break;
+	case MMCIF_WAIT_FOR_STOP:
+		if (host->sd_error) {
+			mrq->stop->error = sh_mmcif_error_manage(host);
+			break;
+		}
+		sh_mmcif_get_cmd12response(host, mrq->stop);
+		mrq->stop->error = 0;
+		break;
+	case MMCIF_WAIT_FOR_READ_END:
+	case MMCIF_WAIT_FOR_WRITE_END:
+		if (host->sd_error)
+			mrq->data->error = sh_mmcif_error_manage(host);
+		break;
+	default:
+		BUG();
+	}
+
+	if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
+		host->data = NULL;
+
+		if (!mrq->cmd->error && mrq->data && !mrq->data->error)
+			mrq->data->bytes_xfered +				mrq->data->blocks * mrq->data->blksz;
+
+		if (mrq->stop && !mrq->cmd->error && (!mrq->data || !mrq->data->error)) {
+			sh_mmcif_stop_cmd(host, mrq);
+			if (!mrq->stop->error)
+				return IRQ_HANDLED;
+		}
+	}
+
+	host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+	host->state = STATE_IDLE;
+	mmc_request_done(host->mmc, mrq);
+
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
@@ -991,14 +1146,58 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
 		host->sd_error = true;
 		dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
 	}
-	if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
-		complete(&host->intr_wait);
-	else
+	if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
+		if (host->dma_active)
+			mmcif_dma_complete(host);
+		else
+			return IRQ_WAKE_THREAD;
+	} else {
 		dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
+	}
 
 	return IRQ_HANDLED;
 }
 
+static void mmcif_timeout_work(struct work_struct *work)
+{
+	struct delayed_work *d = container_of(work, struct delayed_work, work);
+	struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work);
+	struct mmc_request *mrq = host->mrq;
+
+	if (host->dying)
+		/* Don't run after mmc_remove_host() */
+		return;
+
+	/*
+	 * Handle races with cancel_delayed_work(), unless
+	 * cancel_delayed_work_sync() is used
+	 */
+	switch (host->wait_for) {
+	case MMCIF_WAIT_FOR_CMD:
+		mrq->cmd->error = sh_mmcif_error_manage(host);
+		break;
+	case MMCIF_WAIT_FOR_STOP:
+		mrq->stop->error = sh_mmcif_error_manage(host);
+		break;
+	case MMCIF_WAIT_FOR_MREAD:
+	case MMCIF_WAIT_FOR_MWRITE:
+	case MMCIF_WAIT_FOR_READ:
+	case MMCIF_WAIT_FOR_WRITE:
+	case MMCIF_WAIT_FOR_READ_END:
+	case MMCIF_WAIT_FOR_WRITE_END:
+		host->data->error = sh_mmcif_error_manage(host);
+		break;
+	default:
+		BUG();
+	}
+
+	host->state = STATE_IDLE;
+	host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+	host->data = NULL;
+	host->mrq = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
 static int __devinit sh_mmcif_probe(struct platform_device *pdev)
 {
 	int ret = 0, irq[2];
@@ -1052,7 +1251,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
 	host->clk = clk_get_rate(host->hclk);
 	host->pd = pdev;
 
-	init_completion(&host->intr_wait);
 	spin_lock_init(&host->lock);
 
 	mmc->ops = &sh_mmcif_ops;
@@ -1089,19 +1287,21 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
 
 	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
-	ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
+	ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
 		goto clean_up3;
 	}
-	ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
+	ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
 	if (ret) {
 		free_irq(irq[0], host);
 		dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
 		goto clean_up3;
 	}
 
-	sh_mmcif_detect(host->mmc);
+	INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
+
+	mmc_detect_change(host->mmc, 0);
 
 	dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
 	dev_dbg(&pdev->dev, "chip ver H'%04x\n",
@@ -1127,11 +1327,19 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 	int irq[2];
 
+	host->dying = true;
 	pm_runtime_get_sync(&pdev->dev);
 
 	mmc_remove_host(host->mmc);
 	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
+	/*
+	 * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the
+	 * mmc_remove_host() call above. But swapping order doesn't help either
+	 * (a query on the linux-mmc mailing list didn't bring any replies).
+	 */
+	cancel_delayed_work_sync(&host->timeout_work);
+
 	if (host->addr)
 		iounmap(host->addr);
 

^ permalink raw reply related

* Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: phil.edworthy @ 2011-11-30  9:56 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <1322637713-15227-1-git-send-email-phil.edworthy@renesas.com>

Hi Paul,

> Subject: Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough 
mode.
> 
> On Wed, Nov 30, 2011 at 07:21:53AM +0000, Phil Edworthy wrote:
> > When the operand cache is set to writethough mode, there is no
> > need to flush data.
> > 
> > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> 
> What about the other routines?
> 
> You are presumably stipulating that any access to the OC address array
> outside of cacheline invalidation should be omitted for write-through
> cache mode, which suggests that quite a lot of the file in question can
> simply be nopped out.
> 
> At the very least sh2a__flush_wback_region() could deal with the same
> treatment. For the invalidation routines you presumably still need the
> V-bit clearing, though.
> 
> sh2a__flush_invalidate_region() also bears closer inspection.

It's worth mentioning that this patch is essentially a work around for an 
issue with write-back mode. sh2a_flush_icache_range is passed a large 
address range which takes ages to flush/invalidate. For write-back mode, 
instead of indexing on the address, perhaps we can walk through all the 
cache entries and check for an address match. That's for another day...

I agree that the other functions can be improved. I ignored them as the 
main performance issue is with sh2a_flush_icache_range. I wasn't entirely 
sure when some of the other functions are used. Are 
sh2a__flush_wback_region and sh2a__flush_purge_region purely OC related? 
And sh2a__flush_invalidate_region and sh2a_flush_icache_range work on both 
the IC and OC?

Phil

^ permalink raw reply

* Re: [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: Paul Mundt @ 2011-11-30  9:17 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <1322637713-15227-1-git-send-email-phil.edworthy@renesas.com>

On Wed, Nov 30, 2011 at 07:21:53AM +0000, Phil Edworthy wrote:
> When the operand cache is set to writethough mode, there is no
> need to flush data.
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>

What about the other routines?

You are presumably stipulating that any access to the OC address array
outside of cacheline invalidation should be omitted for write-through
cache mode, which suggests that quite a lot of the file in question can
simply be nopped out.

At the very least sh2a__flush_wback_region() could deal with the same
treatment. For the invalidation routines you presumably still need the
V-bit clearing, though.

sh2a__flush_invalidate_region() also bears closer inspection.

^ permalink raw reply

* [PATCH] sh: sh2a: Optimise cache flush for writethrough mode.
From: Phil Edworthy @ 2011-11-30  7:21 UTC (permalink / raw)
  To: linux-sh

When the operand cache is set to writethough mode, there is no
need to flush data.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/sh/mm/cache-sh2a.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 1f51225..56bb5f2 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -112,6 +112,7 @@ static void sh2a_flush_icache_range(void *args)
 
 	for (v = start; v < end; v+=L1_CACHE_BYTES) {
 		unsigned long addr = (v & 0x000007f0);
+#ifdef CONFIG_CACHE_WRITEBACK
 		int way;
 		/* O-Cache writeback */
 		for (way = 0; way < 4; way++) {
@@ -121,6 +122,7 @@ static void sh2a_flush_icache_range(void *args)
 				__raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
 			}
 		}
+#endif
 		/* I-Cache invalidate */
 		__raw_writel(addr,
 			  CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH 2/2 v5] net/smsc911x: Add regulator support
From: David Miller @ 2011-11-29 23:37 UTC (permalink / raw)
  To: robert.marklund
  Cc: netdev, steve.glendinning, mathieu.poirier, lethal, linux-sh,
	s.hauer, tony, linux-omap, vapier, uclinux-dist-devel,
	linus.walleij
In-Reply-To: <1322132587-2049-1-git-send-email-robert.marklund@stericsson.com>

From: Robert Marklund <robert.marklund@stericsson.com>
Date: Thu, 24 Nov 2011 12:03:07 +0100

> Add some basic regulator support for the power pins, as needed
> by the ST-Ericsson Snowball platform that powers up the SMSC911
> chip using an external regulator.
> 
> Platforms that use regulators and the smsc911x and have no defined
> regulator for the smsc911x and claim complete regulator
> constraints with no dummy regulators will need to provide it, for
> example using a fixed voltage regulator. It appears that this may
> affect (apart from Ux500 Snowball) possibly these archs/machines
> that from some grep:s appear to define both CONFIG_SMSC911X and
> CONFIG_REGULATOR:
> 
> - ARM Freescale mx3 and OMAP 2 plus, Raumfeld machines
> - Blackfin
> - Super-H
> 
> Cc: Paul Mundt <lethal@linux-sh.org>
> Cc: linux-sh@vger.kernel.org
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: linux-omap@vger.kernel.org
> Cc: Mike Frysinger <vapier@gentoo.org>
> Cc: uclinux-dist-devel@blackfin.uclinux.org
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Robert Marklund <robert.marklund@stericsson.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Russell King - ARM Linux @ 2011-11-29  9:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdY-YL0RSY4+nL36sM9WwX+VbMkJP54djrCwYCQmw9AFEw@mail.gmail.com>

On Tue, Nov 29, 2011 at 09:40:27AM +0100, Linus Walleij wrote:
> On Tue, Nov 29, 2011 at 7:46 AM, Peter De Schrijver
> <pdeschrijver@nvidia.com> wrote:
> > On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
> >> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
> >> Russel King. It also converts some platforms to the new model.
> >>
> >> Peter De Schrijver (3):
> >>   ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
> >>   ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
> >>   ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO
> >
> > Ping? What should we do with this?
> 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Put it into Russell's patch tracker.

Or we could wait for Grant to reappear and take it.

^ permalink raw reply

* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Linus Walleij @ 2011-11-29  8:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111129064630.GW19069@tbergstrom-lnx.Nvidia.com>

On Tue, Nov 29, 2011 at 7:46 AM, Peter De Schrijver
<pdeschrijver@nvidia.com> wrote:
> On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
>> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
>> Russel King. It also converts some platforms to the new model.
>>
>> Peter De Schrijver (3):
>>   ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
>>   ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
>>   ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO
>
> Ping? What should we do with this?

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Put it into Russell's patch tracker.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH 0/3] Change ARCH_NR_GPIO into a Kconfig variable
From: Peter De Schrijver @ 2011-11-29  6:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1320339647-30255-1-git-send-email-pdeschrijver@nvidia.com>

On Thu, Nov 03, 2011 at 06:00:44PM +0100, Peter De Schrijver wrote:
> This patchset converts ARCH_NR_GPIO to a Kconfig variable as suggested by
> Russel King. It also converts some platforms to the new model.
> 
> Peter De Schrijver (3):
>   ARM: ARCH_NR_GPIO: Make ARCH_NR_GPIO a Kconfig variable
>   ARM: mach-shmobile: Use CONFIG_ARCH_NR_GPIO
>   ARM: mach-ux500 Use CONFIG_ARCH_NR_GPIO

Ping? What should we do with this?

Cheers,

Peter.

^ permalink raw reply

* [Update][PATCH] PM / Domains: Make it possible to assign names to generic PM domains
From: Rafael J. Wysocki @ 2011-11-28 21:38 UTC (permalink / raw)
  To: Linux PM list; +Cc: LKML, Linux-sh list, Magnus Damm
In-Reply-To: <201111272153.53008.rjw@sisk.pl>

From: Rafael J. Wysocki <rjw@sisk.pl>

Add a name member pointer to struct generic_pm_domain and use it in
diagnostic messages regarding the domain power-off and power-on
latencies.  Update the ARM shmobile SH7372 code to assign names to
the PM domains used by it.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

Hi,

This version of the patch avoids adding a new member to
struct generic_pm_domain.

Thanks,
Rafael

---
 arch/arm/mach-shmobile/pm-sh7372.c |   16 ++++++++++++----
 drivers/base/power/domain.c        |   14 ++++++++++++--
 include/linux/pm_domain.h          |    1 +
 3 files changed, 25 insertions(+), 6 deletions(-)

Index: linux/drivers/base/power/domain.c
=================================--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -209,8 +209,13 @@ int __pm_genpd_poweron(struct generic_pm
 			goto err;
 
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-		if (elapsed_ns > genpd->power_on_latency_ns)
+		if (elapsed_ns > genpd->power_on_latency_ns) {
 			genpd->power_on_latency_ns = elapsed_ns;
+			if (genpd->name)
+				pr_warning("%s: Power-on latency exceeded, "
+					"new value %lld ns\n", genpd->name,
+					elapsed_ns);
+		}
 	}
 
 	genpd_set_active(genpd);
@@ -428,8 +433,13 @@ static int pm_genpd_poweroff(struct gene
 		}
 
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-		if (elapsed_ns > genpd->power_off_latency_ns)
+		if (elapsed_ns > genpd->power_off_latency_ns) {
 			genpd->power_off_latency_ns = elapsed_ns;
+			if (genpd->name)
+				pr_warning("%s: Power-off latency exceeded, "
+					"new value %lld ns\n", genpd->name,
+					elapsed_ns);
+		}
 	}
 
 	genpd->status = GPD_STATE_POWER_OFF;
Index: linux/include/linux/pm_domain.h
=================================--- linux.orig/include/linux/pm_domain.h
+++ linux/include/linux/pm_domain.h
@@ -49,6 +49,7 @@ struct generic_pm_domain {
 	struct mutex lock;
 	struct dev_power_governor *gov;
 	struct work_struct power_off_work;
+	char *name;
 	unsigned int in_progress;	/* Number of devices being suspended now */
 	atomic_t sd_count;	/* Number of subdomains with power "on" */
 	enum gpd_status status;	/* Current state of the domain */
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -101,8 +101,8 @@ static int pd_power_down(struct generic_
 	}
 
 	if (!sh7372_pd->no_debug)
-		pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
-			 mask, __raw_readl(PSTR));
+		pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+			 genpd->name, mask, __raw_readl(PSTR));
 
 	return 0;
 }
@@ -133,8 +133,8 @@ static int __pd_power_up(struct sh7372_p
 		ret = -EIO;
 
 	if (!sh7372_pd->no_debug)
-		pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
-			 mask, __raw_readl(PSTR));
+		pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+			 sh7372_pd->genpd.name, mask, __raw_readl(PSTR));
 
  out:
 	if (ret = 0 && sh7372_pd->resume && do_resume)
@@ -233,18 +233,22 @@ void sh7372_pm_add_subdomain(struct sh73
 }
 
 struct sh7372_pm_domain sh7372_a4lc = {
+	.genpd.name = "A4LC",
 	.bit_shift = 1,
 };
 
 struct sh7372_pm_domain sh7372_a4mp = {
+	.genpd.name = "A4MP",
 	.bit_shift = 2,
 };
 
 struct sh7372_pm_domain sh7372_d4 = {
+	.genpd.name = "D4",
 	.bit_shift = 3,
 };
 
 struct sh7372_pm_domain sh7372_a4r = {
+	.genpd.name = "A4R",
 	.bit_shift = 5,
 	.gov = &sh7372_always_on_gov,
 	.suspend = sh7372_a4r_suspend,
@@ -253,14 +257,17 @@ struct sh7372_pm_domain sh7372_a4r = {
 };
 
 struct sh7372_pm_domain sh7372_a3rv = {
+	.genpd.name = "A3RV",
 	.bit_shift = 6,
 };
 
 struct sh7372_pm_domain sh7372_a3ri = {
+	.genpd.name = "A3RI",
 	.bit_shift = 8,
 };
 
 struct sh7372_pm_domain sh7372_a3sp = {
+	.genpd.name = "A3SP",
 	.bit_shift = 11,
 	.gov = &sh7372_always_on_gov,
 	.no_debug = true,
@@ -275,6 +282,7 @@ static void sh7372_a3sp_init(void)
 }
 
 struct sh7372_pm_domain sh7372_a3sg = {
+	.genpd.name = "A3SG",
 	.bit_shift = 13,
 };
 


^ permalink raw reply

* [PATCH 17/23] SuperH: Use HAVE_MEMBLOCK_NODE_MAP
From: Tejun Heo @ 2011-11-28 19:31 UTC (permalink / raw)
  To: benh, yinghai, hpa, tony.luck, ralf, schwidefsky, liqin.chen,
	lethal, davem, linux-kernel, linux-arch, mingo, jonas, lennox.wu
  Cc: Tejun Heo, linux-sh
In-Reply-To: <1322508685-32532-1-git-send-email-tj@kernel.org>

sh doesn't access early_node_map[] directly and enabling
HAVE_MEMBLOCK_NODE_MAP is trivial - replacing add_active_range() calls
with memblock_set_node() and selecting HAVE_MEMBLOCK_NODE_MAP is
enough.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: linux-sh@vger.kernel.org
---
 arch/sh/Kconfig        |    1 +
 arch/sh/kernel/setup.c |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 5629e20..47a2f1c 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -4,6 +4,7 @@ config SUPERH
 	select CLKDEV_LOOKUP
 	select HAVE_IDE if HAS_IOPORT
 	select HAVE_MEMBLOCK
+	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_OPROFILE
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_ARCH_TRACEHOOK
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 1a0e946..7b57bf1 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -230,7 +230,8 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
 	pmb_bolt_mapping((unsigned long)__va(start), start, end - start,
 			 PAGE_KERNEL);
 
-	add_active_range(nid, start_pfn, end_pfn);
+	memblock_set_node(PFN_PHYS(start_pfn),
+			  PFN_PHYS(end_pfn - start_pfn), nid);
 }
 
 void __init __weak plat_early_device_setup(void)
-- 
1.7.3.1


^ permalink raw reply related

* [PATCH] PM / Domains: Make it possible to assign names to generic PM domains
From: Rafael J. Wysocki @ 2011-11-27 20:53 UTC (permalink / raw)
  To: Linux PM list; +Cc: LKML, Linux-sh list, Magnus Damm

From: Rafael J. Wysocki <rjw@sisk.pl>

Add a name member pointer to struct generic_pm_domain and use it in
diagnostic messages regarding the domain power-off and power-on
latencies.  Update the ARM shmobile SH7372 code to assign names to
the PM domains used by it.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

Hi,

This patch is on top of linux-pm/linux-next.

Thanks,
Rafael

---
 arch/arm/mach-shmobile/include/mach/sh7372.h |    1 +
 arch/arm/mach-shmobile/pm-sh7372.c           |   17 +++++++++++++----
 drivers/base/power/domain.c                  |   14 ++++++++++++--
 include/linux/pm_domain.h                    |    1 +
 4 files changed, 27 insertions(+), 6 deletions(-)

Index: linux/drivers/base/power/domain.c
=================================--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -209,8 +209,13 @@ int __pm_genpd_poweron(struct generic_pm
 			goto err;
 
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-		if (elapsed_ns > genpd->power_on_latency_ns)
+		if (elapsed_ns > genpd->power_on_latency_ns) {
 			genpd->power_on_latency_ns = elapsed_ns;
+			if (genpd->name)
+				pr_warning("%s: Power-on latency exceeded, "
+					"new value %lld ns\n", genpd->name,
+					elapsed_ns);
+		}
 	}
 
 	genpd_set_active(genpd);
@@ -428,8 +433,13 @@ static int pm_genpd_poweroff(struct gene
 		}
 
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-		if (elapsed_ns > genpd->power_off_latency_ns)
+		if (elapsed_ns > genpd->power_off_latency_ns) {
 			genpd->power_off_latency_ns = elapsed_ns;
+			if (genpd->name)
+				pr_warning("%s: Power-off latency exceeded, "
+					"new value %lld ns\n", genpd->name,
+					elapsed_ns);
+		}
 	}
 
 	genpd->status = GPD_STATE_POWER_OFF;
Index: linux/include/linux/pm_domain.h
=================================--- linux.orig/include/linux/pm_domain.h
+++ linux/include/linux/pm_domain.h
@@ -49,6 +49,7 @@ struct generic_pm_domain {
 	struct mutex lock;
 	struct dev_power_governor *gov;
 	struct work_struct power_off_work;
+	char *name;
 	unsigned int in_progress;	/* Number of devices being suspended now */
 	atomic_t sd_count;	/* Number of subdomains with power "on" */
 	enum gpd_status status;	/* Current state of the domain */
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -101,8 +101,8 @@ static int pd_power_down(struct generic_
 	}
 
 	if (!sh7372_pd->no_debug)
-		pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
-			 mask, __raw_readl(PSTR));
+		pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+			 sh7372_pd->name, mask, __raw_readl(PSTR));
 
 	return 0;
 }
@@ -133,8 +133,8 @@ static int __pd_power_up(struct sh7372_p
 		ret = -EIO;
 
 	if (!sh7372_pd->no_debug)
-		pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
-			 mask, __raw_readl(PSTR));
+		pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+			 sh7372_pd->name, mask, __raw_readl(PSTR));
 
  out:
 	if (ret = 0 && sh7372_pd->resume && do_resume)
@@ -207,6 +207,7 @@ void sh7372_init_pm_domain(struct sh7372
 	struct dev_power_governor *gov = sh7372_pd->gov;
 
 	pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
+	genpd->name = sh7372_pd->name;
 	genpd->dev_ops.stop = sh7372_stop_dev;
 	genpd->dev_ops.start = sh7372_start_dev;
 	genpd->dev_ops.active_wakeup = pd_active_wakeup;
@@ -233,18 +234,22 @@ void sh7372_pm_add_subdomain(struct sh73
 }
 
 struct sh7372_pm_domain sh7372_a4lc = {
+	.name = "A4LC",
 	.bit_shift = 1,
 };
 
 struct sh7372_pm_domain sh7372_a4mp = {
+	.name = "A4MP",
 	.bit_shift = 2,
 };
 
 struct sh7372_pm_domain sh7372_d4 = {
+	.name = "D4",
 	.bit_shift = 3,
 };
 
 struct sh7372_pm_domain sh7372_a4r = {
+	.name = "A4R",
 	.bit_shift = 5,
 	.gov = &sh7372_always_on_gov,
 	.suspend = sh7372_a4r_suspend,
@@ -253,14 +258,17 @@ struct sh7372_pm_domain sh7372_a4r = {
 };
 
 struct sh7372_pm_domain sh7372_a3rv = {
+	.name = "A3RV",
 	.bit_shift = 6,
 };
 
 struct sh7372_pm_domain sh7372_a3ri = {
+	.name = "A3RI",
 	.bit_shift = 8,
 };
 
 struct sh7372_pm_domain sh7372_a3sp = {
+	.name = "A3SP",
 	.bit_shift = 11,
 	.gov = &sh7372_always_on_gov,
 	.no_debug = true,
@@ -275,6 +283,7 @@ static void sh7372_a3sp_init(void)
 }
 
 struct sh7372_pm_domain sh7372_a3sg = {
+	.name = "A3SG",
 	.bit_shift = 13,
 };
 
Index: linux/arch/arm/mach-shmobile/include/mach/sh7372.h
=================================--- linux.orig/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ linux/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,6 +480,7 @@ struct platform_device;
 struct sh7372_pm_domain {
 	struct generic_pm_domain genpd;
 	struct dev_power_governor *gov;
+	char *name;
 	void (*suspend)(void);
 	void (*resume)(void);
 	unsigned int bit_shift;

^ permalink raw reply


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