Re: [PATCH] powerpc/mpc85xx: fix non-bootcpu cannot up after hibernation resume

2013-05-23 Thread Anton Vorontsov
Hi!

On Tue, May 14, 2013 at 08:59:13AM +, Wang Dongsheng-B40534 wrote:
> I send to a wrong email address "Anton Vorontsov "
> 
> Add Anton Vorontsov  to this email.

I don't have any means to test it, but the patch itself looks good and the
description makes sense. So,

Reviewed-by: Anton Vorontsov 

Thanks!

> 
> Thanks all.
> 
> > -Original Message-
> > From: Wang Dongsheng-B40534
> > Sent: Tuesday, May 14, 2013 4:06 PM
> > To: avoront...@ru.mvista.com
> > Cc: pau...@samba.org; r...@sisk.pl; b...@kernel.crashing.org;
> > johan...@sipsolutions.net; Wood Scott-B07421; Li Yang-R58472; Zhao
> > Chenhui-B35336; linuxppc-dev@lists.ozlabs.org; Wang Dongsheng-B40534
> > Subject: [PATCH] powerpc/mpc85xx: fix non-bootcpu cannot up after
> > hibernation resume
> > 
> > This problem belongs to the core synchronization issues.
> > The cpu1 already updated spin_table values, but bootcore cannot get
> > this value in time.
> > 
> > After bootcpu hibiernation restore the pages. we are now running
> > with the kernel data of the old kernel fully restored. if we reset
> > the non-bootcpus that will be reset cache(tlb), the non-bootcpus
> > will get new address(map virtual and physical address spaces).
> > but bootcpu tlb cache still use boot kernel data, so we need to
> > invalidate the bootcpu tlb cache make it to get new main memory data.
> > 
> > log:
> > Enabling non-boot CPUs ...
> > smp_85xx_kick_cpu: timeout waiting for core 1 to reset
> > smp: failed starting cpu 1 (rc -2)
> > Error taking CPU1 up: -2
> > 
> > Signed-off-by: Wang Dongsheng 
> > 
> > diff --git a/arch/powerpc/kernel/swsusp_booke.S
> > b/arch/powerpc/kernel/swsusp_booke.S
> > index 11a3930..9503249 100644
> > --- a/arch/powerpc/kernel/swsusp_booke.S
> > +++ b/arch/powerpc/kernel/swsusp_booke.S
> > @@ -141,6 +141,19 @@ _GLOBAL(swsusp_arch_resume)
> > lis r11,swsusp_save_area@h
> > ori r11,r11,swsusp_save_area@l
> > 
> > +   /*
> > +* The boot core get a virtual address, when the boot process,
> > +* the virtual address corresponds to a physical address. After
> > +* hibernation resume memory snapshots, The corresponding
> > +* relationship between the virtual memory and physical memory
> > +* might change again. We need to get a new page table. So we
> > +* need to invalidate TLB after resume pages.
> > +*
> > +* Invalidations TLB Using tlbilx/tlbivax/MMUCSR0.
> > +* tlbilx used here.
> > +*/
> > +   bl  _tlbil_all
> > +
> > lwz r4,SL_SPRG0(r11)
> > mtsprg  0,r4
> > lwz r4,SL_SPRG1(r11)
> > --
> > 1.8.0
> 
> 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 3/4 V2] mmc: esdhc: Add quirks to support T4240QDS board

2013-07-12 Thread Anton Vorontsov
On Mon, Jul 08, 2013 at 12:18:39PM -0500, Scott Wood wrote:
> On 07/08/2013 02:16:04 AM, Haijun Zhang wrote:
> >On T4240QDS board controllers has an unusable ADMA engine, so use
> >SDMA instead.
> >Also 3.0v is support on T4240QDS board even if the capacity
> >detailed only 1.8v
> >support. Without this quirk SD card will declare voltage not
> >support and
> >
> >Signed-off-by: Haijun Zhang 
> 
> ...and what?
> 
> Why is this board-specific?  Isn't the controller part of the SoC,
> not part of the board?  If it really is board-specific, could you be
> more detailed about why (ideally with an erratum number), and check
> the toplevel board compatible (or get the information from platform
> code) rather than modify the device tree?

Yup, and if anything, I would recommend to reuse voltage-ranges property,
it is already implemented for mmc spi driver,

drivers/mmc/host/of_mmc_spi.c
Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt

Thanks,

Anton
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 3/4 V2] mmc: esdhc: Add quirks to support T4240QDS board

2013-07-15 Thread Anton Vorontsov
On Tue, Jul 16, 2013 at 03:11:47AM +, Zhang Haijun-B42677 wrote:
> Hi, Anton
> 
> You mean get voltage support from DTS?
> Or get voltage both from DTS and host capacity register?

The logic might be that you first check device-tree, if it specifies
voltage ranges, assume that DTS knows better, otherwise read capabilities
from the register.

Anton

> Thanks.
> 
> Regards
> Haijun.
> 
> 
> > -Original Message-
> > From: linux-mmc-ow...@vger.kernel.org [mailto:linux-mmc-
> > ow...@vger.kernel.org] On Behalf Of Anton Vorontsov
> > Sent: Saturday, July 13, 2013 2:35 AM
> > To: Wood Scott-B07421
> > Cc: Zhang Haijun-B42677; linux-...@vger.kernel.org; linuxppc-
> > d...@lists.ozlabs.org; c...@laptop.org; Fleming Andy-AFLEMING; Wrobel
> > Heinz-R39252
> > Subject: Re: [PATCH 3/4 V2] mmc: esdhc: Add quirks to support T4240QDS
> > board
> > 
> > On Mon, Jul 08, 2013 at 12:18:39PM -0500, Scott Wood wrote:
> > > On 07/08/2013 02:16:04 AM, Haijun Zhang wrote:
> > > >On T4240QDS board controllers has an unusable ADMA engine, so use
> > > >SDMA instead.
> > > >Also 3.0v is support on T4240QDS board even if the capacity detailed
> > > >only 1.8v support. Without this quirk SD card will declare voltage
> > > >not support and
> > > >
> > > >Signed-off-by: Haijun Zhang 
> > >
> > > ...and what?
> > >
> > > Why is this board-specific?  Isn't the controller part of the SoC, not
> > > part of the board?  If it really is board-specific, could you be more
> > > detailed about why (ideally with an erratum number), and check the
> > > toplevel board compatible (or get the information from platform
> > > code) rather than modify the device tree?
> > 
> > Yup, and if anything, I would recommend to reuse voltage-ranges property,
> > it is already implemented for mmc spi driver,
> > 
> > drivers/mmc/host/of_mmc_spi.c
> > Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
> > 
> > Thanks,
> > 
> > Anton
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> > the body of a message to majord...@vger.kernel.org More majordomo info at
> > http://vger.kernel.org/majordomo-info.html
> 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] mmc: esdhc: get voltage from dts file

2013-07-26 Thread Anton Vorontsov
On Mon, Jul 22, 2013 at 09:41:34PM -0500, Scott Wood wrote:
[...]
> >> > +static void esdhc_get_voltage(struct sdhci_host *host,
> >> > +struct platform_device *pdev)
> >> > +{

> >> > +}
> >>
> >> Don't duplicate this code.  Move it somewhere common and share it.
> >[Haijun Wrote:] So, move it drivers/mmc/host/sdhci-pltfm.c and
> >share it as
> >Sdhc_get_voltage()?
> 
> I'll let the MMC maintainer say what the appropriate place would
> be...  Don't capitalize the function name, though. :-)

Somewhere in drivers/mmc/core/core.c, near mmc_vddrange_to_ocrmask() would
be most appropriate, IMO. #ifdef CONFIG_OF would be needed, though.

Thanks,

Anton
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2 V2] mmc: esdhc: get voltage from dts file

2013-07-26 Thread Anton Vorontsov
On Thu, Jul 25, 2013 at 08:38:11AM +0800, Haijun Zhang wrote:
> Add voltage-range support in esdhc of T4, So we can choose
> to read voltages from dts file as one optional.
> If we can get a valid voltage-range from device node, we use
> this voltage as the final voltage support. Else we still read
> from capacity or from other provider.
> 
> Signed-off-by: Haijun Zhang 
> Signed-off-by: Anton Vorontsov 

Development process nitpick...

The code originated from me, but I did not sign off this patch...

Per Documentation/SubmittingPatches:

  The Signed-off-by: tag indicates that the signer was involved in the
  development of the patch, or that he/she was in the patch's delivery path.

The order of the sign-off lines also has a meaning. Putting my sign off
below yours means that I was not only involved in the development of the
patch but also somehow approved the patch (but I did not :).

[..]
> +void sdhci_get_voltage(struct platform_device *pdev)

You still duplicate the code... Per my previous email, this should
probably go into mmc/core (with the function renamed to something more
generic, of course.)

Thanks,

Anton
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] mmc:of_spi: Update the code of getting voltage-ranges

2013-08-08 Thread Anton Vorontsov
On Wed, Jul 31, 2013 at 02:25:27PM +0800, Haijun Zhang wrote:
>   int num_ranges;
> + u32 ocr_mask;
>   int i;
>   int ret = -EINVAL;
>  
> @@ -102,26 +103,11 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct 
> spi_device *spi)
>   if (!oms)
>   return NULL;
>  
> - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
> - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
> - if (!voltage_ranges || !num_ranges) {
> - dev_err(dev, "OF: voltage-ranges unspecified\n");
> + ocr_mask = mmc_of_parse_voltage(np);
> + if (ocr_mask <= 0)

'< 0' check for an unsigned type? :) I'd write just !ocr_mask...

But other than that the patch looks good to me...

Reviewed-by: Anton Vorontsov 

Thanks!

>   goto err_ocr;
> - }
> -
> - for (i = 0; i < num_ranges; i++) {
> - const int j = i * 2;
> - u32 mask;
>  
> - mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
> -be32_to_cpu(voltage_ranges[j + 
> 1]));
> - if (!mask) {
> - ret = -EINVAL;
> - dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
> - goto err_ocr;
> - }
> - oms->pdata.ocr_mask |= mask;
> - }
> + oms->pdata.ocr_mask |= ocr_mask;
>  
>   for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
>   enum of_gpio_flags gpio_flags;
> -- 
> 1.8.0
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/3 V2] mmc:core: parse voltage from device-tree

2013-08-08 Thread Anton Vorontsov
On Wed, Jul 31, 2013 at 02:25:25PM +0800, Haijun Zhang wrote:
> Add function to support get voltage from device-tree.
> If there are voltage-range specified in device-tree node, this function
> will parse it and return the avail voltage mask.
> 
> Signed-off-by: Haijun Zhang 
> ---
> changes for v2:
>   - Update the parameters of function
> 
>  drivers/mmc/core/core.c  | 46 ++
>  include/linux/mmc/core.h |  1 +
>  2 files changed, 47 insertions(+)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 49a5bca..ce9c957 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -27,6 +27,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -1196,6 +1197,51 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
>  }
>  EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
>  
> +#ifdef CONFIG_OF
> +
> +/*

This is not kernel-doc formatted comment for the function.. it should
start with /**...

> + * mmc_of_parse_voltage - return mask of supported voltages
> + * @np: The device node need to be parsed.
> + *
> + * 1. Return zero: voltage-ranges unspecified in device-tree.
> + * 2. Return negative errno: voltage-range is invalid.

This doesn't seem right... the function returns the unsigned mask... You
can change the prototype of this func to something like this:

int mmc_of_parse_voltage(struct device_node *np, u32 *mask);

So the function will fill the mask and return 0 on success, and will
return negtive errno on errors.

> + * 3. Return ocr_mask: a mask of voltages that parse from device-tree
> + * node can be provided to MMC/SD/SDIO devices.
> + */
> +

No need for this empty line...

> +u32 mmc_of_parse_voltage(struct device_node *np)
> +{
> + const u32 *voltage_ranges;
> + int num_ranges, i;
> + u32 ocr_mask = 0;
> +
> + voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
> + num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
> + if (!voltage_ranges || !num_ranges) {
> + pr_info("%s: voltage-ranges unspecified\n", np->full_name);
> + return 0;
> + }
> +
> + for (i = 0; i < num_ranges; i++) {
> + const int j = i * 2;
> + u32 mask;
> +
> + mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
> + be32_to_cpu(voltage_ranges[j + 1]));

You lost some [pretty] formatting to line up the two arguments. :)

> + if (!mask) {
> + pr_err("%s: voltage-range #%d is invalid\n",
> + np->full_name, i);
> + return -EINVAL;
> + }
> + ocr_mask |= mask;
> + }
> +
> + return ocr_mask;
> +}
> +EXPORT_SYMBOL(mmc_of_parse_voltage);
> +
> +#endif /* CONFIG_OF */
> +
>  #ifdef CONFIG_REGULATOR
>  
>  /**
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 443243b..e3f8fe3 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -209,5 +209,6 @@ static inline void mmc_claim_host(struct mmc_host *host)
>  }
>  
>  extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
> +extern u32 mmc_of_parse_voltage(struct device_node *np);

You need to add a 'struct device_node;' forward-declaration, otherwise
non-OF code might fail to compile...

Thanks,

Anton
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/3 V5] mmc:core: parse voltage from device-tree

2013-08-22 Thread Anton Vorontsov
On Wed, Aug 14, 2013 at 01:46:11PM +0800, Haijun Zhang wrote:
> Add function to support get voltage from device-tree.
> If there are voltage-range specified in device-tree node, this function
> will parse it and return the available voltage mask.
> 
> Signed-off-by: Haijun Zhang 

Acked-by: Anton Vorontsov 

Thanks a lot!

Anton
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH V3] mmc:of_spi: Update the code of getting voltage-ranges

2013-08-22 Thread Anton Vorontsov
On Mon, Aug 12, 2013 at 09:39:05AM +0800, Haijun Zhang wrote:
> Using function mmc_of_parse_voltage() to get voltage-ranges.
> 
> Signed-off-by: Haijun Zhang 
> ---

Acked-by: Anton Vorontsov 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 3/3 V3] mmc:esdhc: add support to get voltage from device-tree

2013-08-22 Thread Anton Vorontsov
On Mon, Aug 12, 2013 at 09:39:04AM +0800, Haijun Zhang wrote:
> Add suppport to get voltage from device-tree node for esdhc host,
> if voltage-ranges was specified in device-tree node we can get
> ocr_mask instead of read from host capacity register. If not voltages
> still can be get from host capacity register.
> 
> Signed-off-by: Haijun Zhang 

Acked-by: Anton Vorontsov 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/3 V3] mmc:sdhc: get voltage from sdhc host

2013-08-22 Thread Anton Vorontsov
On Mon, Aug 12, 2013 at 09:39:06AM +0800, Haijun Zhang wrote:
> We use host->ocr_mask to hold the voltage get from device-tree
> node, In case host->ocr_mask was available, we use host->ocr_mask
> as the final available voltage can be used by MMC/SD/SDIO card.
> 
> Signed-off-by: Haijun Zhang 
> ---

Reviewed-by: Anton Vorontsov 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [RFC PATCH 1/7] mmc: sdhci: add quirk for broken 3.0V support

2014-06-20 Thread Anton Vorontsov
On Fri, Jun 20, 2014 at 05:35:22PM +0800, Vincent Yang wrote:
> This patch defines a quirk for platforms unable
> to enable 3.0V support.
> It is a preparation and will be used by Fujitsu
> SDHCI controller f_sdh30 driver.
> 
> Signed-off-by: Vincent Yang 

I don't think you need this patch. Instead, you can exclude 3V using the
voltage-ranges = <> in the device tree.

Thanks,

Anton

>  drivers/mmc/host/sdhci.c  | 3 +++
>  include/linux/mmc/sdhci.h | 2 ++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 47055f3..523075f 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -3069,6 +3069,9 @@ int sdhci_add_host(struct sdhci_host *host)
>   }
>  #endif /* CONFIG_REGULATOR */
>  
> + if (host->quirks2 & SDHCI_QUIRK2_NO_3_0_V)
> + caps[0] &= ~SDHCI_CAN_VDD_300;
> +
>   /*
>* According to SD Host Controller spec v3.00, if the Host System
>* can afford more than 150mA, Host Driver should set XPC to 1. Also
> diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
> index 08abe99..cac0958 100644
> --- a/include/linux/mmc/sdhci.h
> +++ b/include/linux/mmc/sdhci.h
> @@ -98,6 +98,8 @@ struct sdhci_host {
>  #define SDHCI_QUIRK2_BROKEN_HS200(1<<6)
>  /* Controller does not support DDR50 */
>  #define SDHCI_QUIRK2_BROKEN_DDR50(1<<7)
> +/* The system physically doesn't support 3.0v, even if the host does */
> +#define SDHCI_QUIRK2_NO_3_0_V(1<<8)
>  
>   int irq;/* Device IRQ */
>   void __iomem *ioaddr;   /* Mapped address */
> -- 
> 1.9.0
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit

2011-09-09 Thread Anton Vorontsov
On Fri, Sep 09, 2011 at 08:05:46PM +0800, Roy Zang wrote:
> From: Xu lei 
> 
> Freescale eSDHC registers only support 32-bit accesses,
> this patch ensures that all Freescale eSDHC register accesses
> are 32-bit.
> 
> Signed-off-by: Xu lei 
> Signed-off-by: Roy Zang 
> Signed-off-by: Kumar Gala 
> ---

The patch looks OK.

Acked-by: Anton Vorontsov 

[...]
> +static u8 esdhc_readb(struct sdhci_host *host, int reg)
> +{
> + int base = reg & ~0x3;
> + int shift = (reg & 0x3) * 8;
> + u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
>   return ret;
>  }

Though, I wonder if we could change sdhci_be32bs_read{b,w}, instead
of making this local to eSDHC.

The thing is: sdhci_be32bs_writeb() is using clrsetbits_be32,
so the write variant already uses 32-bit accessors, so nothing should
break if we switch sdhci_be32bs_readb() to in_be32().

But maybe it's safer if we do this in a separate patch, so that it
could be easily reverted without impacting eSDHC if something actually
breaks.

You decide. :-)

Thanks!

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/3] powerpc/esdhc: add property to disable the CMD23

2012-09-11 Thread Anton Vorontsov
On Tue, Sep 11, 2012 at 12:54:29AM -0700, Anton Vorontsov wrote:
> On Tue, Sep 11, 2012 at 03:12:44PM +0800, chang-ming.hu...@freescale.com 
> wrote:
> > From: Jerry Huang 
> > 
> > Below SOCs don't support the cmd23 command for MMC card,
> > therefore, disable it in device tree:
> > P1020, P1021, P1022, P1024, P1025 and P4080
> > 
> > Signed-off-by: Jerry Huang 
> 
> Acked-by: Anton Vorontsov 

Btw, although the patch is trivial, I guess you still want to let know
PowerPC folks about it. Adding Cc and copying the patch:

- - - -
From: Jerry Huang 

Below SOCs don't support the cmd23 command for MMC card,
therefore, disable it in device tree:
P1020, P1021, P1022, P1024, P1025 and P4080

Signed-off-by: Jerry Huang 
CC: Anton Vorontsov 
---
 arch/powerpc/boot/dts/fsl/p1020si-post.dtsi |1 +
 arch/powerpc/boot/dts/fsl/p1021si-post.dtsi |1 +
 arch/powerpc/boot/dts/fsl/p1022si-post.dtsi |1 +
 arch/powerpc/boot/dts/fsl/p4080si-post.dtsi |1 +
 4 files changed, 4 insertions(+)

diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
index 68cc5e7..793a30b 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
@@ -154,6 +154,7 @@
sdhc@2e000 {
compatible = "fsl,p1020-esdhc", "fsl,esdhc";
sdhci,auto-cmd12;
+   sdhci,no-cmd23;
};
 /include/ "pq3-sec3.3-0.dtsi"
 
diff --git a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
index adb82fd..2b7fd2a 100644
--- a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
@@ -149,6 +149,7 @@
 /include/ "pq3-esdhc-0.dtsi"
sdhc@2e000 {
sdhci,auto-cmd12;
+   sdhci,no-cmd23;
};
 
 /include/ "pq3-sec3.3-0.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
index 06216b8..2334a52 100644
--- a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
@@ -215,6 +215,7 @@
sdhc@2e000 {
compatible = "fsl,p1022-esdhc", "fsl,esdhc";
sdhci,auto-cmd12;
+   sdhci,no-cmd23;
};
 
 /include/ "pq3-sec3.3-0.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
index 8d35d2c..5b39952 100644
--- a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
@@ -337,6 +337,7 @@
sdhc@114000 {
voltage-ranges = <3300 3300>;
sdhci,auto-cmd12;
+   sdhci,no-cmd23;
};
 
 /include/ "qoriq-i2c-0.dtsi"
-- 
1.7.9.5
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/3] powerpc/esdhc: add property to disable the CMD23

2012-09-11 Thread Anton Vorontsov
On Wed, Sep 12, 2012 at 03:19:18AM +, Huang Changming-R66093 wrote:
[...]
> I don't think it is the best way to do it.  For the VVN2.2 or older,
> some silicon support this feature (mpc8536 and p2020), but other
> silicones don't support it (e.g. p4080, p102x).  Though, the current
> p5/p4/p3 has supported this feature, can we sure the future silicon
> support it?  So I think the best way is to specify it in device tree
> as 'sdhci,auto-cmd12'

In addition to your current patches, you could just add another patch
that blacklists affected SOC revisions based on the info from PVR/SVR.

For example, see gfar_detect_errata() in
drivers/net/ethernet/freescale/gianfar.c.

That way you could help users that don't have the newest device trees.

Thanks,
Anton.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] powerpc/esdhc: enable the card insert/remove interrupt

2012-10-23 Thread Anton Vorontsov
On Tue, Oct 23, 2012 at 03:01:17PM +0800, r66...@freescale.com wrote:
> From: Jerry Huang 
> 
> The current eSDHC driver use the poll mode to detect
> if the SD/MMC card is inserted or removed, which will generate
> many interrupts and impact the performance. 
> Therefore, change the default card detect to interrupt mode,
> if the board can't support this mode, we still use the poll mode.
> 
> Signed-off-by: Jerry Huang 
> CC: Anton Vorontsov 
> CC: Chris Ball 
> ---

IIRC, the card detection is broken SOC-revision-wise, not board-wise. So
the change seems wrong.

Also, take a look at this:

http://lkml.org/lkml/2010/7/14/127

I started the work but never finished, unfortunately it caused some
regressions for non-FSL hardware...

>  drivers/mmc/host/sdhci-of-esdhc.c |7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c 
> b/drivers/mmc/host/sdhci-of-esdhc.c
> index ffc1226..5dc362f 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -196,6 +196,11 @@ static void esdhc_of_detect_limitation(struct 
> platform_device *pdev,
>   if (vvn == VENDOR_V_22)
>   pdata->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
>  
> + /* P4080DS and MPC837XMDS board don't support interrupt mode */
> + if (of_machine_is_compatible("fsl,mpc837xmds") ||
> + of_machine_is_compatible("fsl,P4080DS"))
> + pdata->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
> +
>   iounmap(ioaddr);
>  end:
>   return;
> @@ -223,7 +228,7 @@ static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
>* card detection could be handled via GPIO
>* eSDHC cannot support End Attribute in NOP ADMA descriptor
>*/
> - .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
> + .quirks = ESDHC_DEFAULT_QUIRKS
>   | SDHCI_QUIRK_NO_CARD_NO_RESET
>   | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
>   .ops = &sdhci_esdhc_ops,
> -- 
> 1.7.9.5
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] powerpc/esdhc: enable the card insert/remove interrupt

2012-10-25 Thread Anton Vorontsov
On Thu, Oct 25, 2012 at 10:05:44AM +, Huang Changming-R66093 wrote:
> Hi, Anton.
> Could you have any comment about it?
> If not, I will resend this patch with v2.

Technically, the patch looks fine.

But again, as far as I recall, the card detection logic was broken on the
SOC level (it's actually very hard to break it on the board level -- it
would either work or not, but in the eSDHC case it was just unreliable,
again, if I recall everything correctly -- I might be wrong).

Of course you know the hardware much better, so your words weight more, so
you don't need my ack on the patch. :)

Although there's a second issue: for P4080DS and mpc837x boards you still
have the same problem with polling method, right? It is causing
performance drops/freezes every like 100 ms, and that's why you want to
avoid the polling.

So, you've "fixed" some boards, but left others to suffer. Ideally, the
best fix would be to also make the card polling cheap.

Anyways, using (d) clause of the "Reviewer's statement of oversight", I
can easily give this:

Reviewed-by: Anton Vorontsov 

:)

Thanks!

[...]
> > > IIRC, the card detection is broken SOC-revision-wise, not board-wise.
> > > So the change seems wrong.
> > >
> > > Also, take a look at this:
> > >
> > >   http://lkml.org/lkml/2010/7/14/127
> > >
> > > I started the work but never finished, unfortunately it caused some
> > > regressions for non-FSL hardware...
> > >
> > > >  drivers/mmc/host/sdhci-of-esdhc.c |7 ++-
> > > >  1 file changed, 6 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
> > > > b/drivers/mmc/host/sdhci-of-esdhc.c
> > > > index ffc1226..5dc362f 100644
> > > > --- a/drivers/mmc/host/sdhci-of-esdhc.c
> > > > +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> > > > @@ -196,6 +196,11 @@ static void esdhc_of_detect_limitation(struct
> > > platform_device *pdev,
> > > > if (vvn == VENDOR_V_22)
> > > > pdata->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
> > > >
> > > > +   /* P4080DS and MPC837XMDS board don't support interrupt mode */
> > > > +   if (of_machine_is_compatible("fsl,mpc837xmds") ||
> > > > +   of_machine_is_compatible("fsl,P4080DS"))
> > > > +   pdata->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
> > > > +
> > > > iounmap(ioaddr);
> > > >  end:
> > > > return;
> > > > @@ -223,7 +228,7 @@ static struct sdhci_pltfm_data sdhci_esdhc_pdata
> > > > =
> > > {
> > > >  * card detection could be handled via GPIO
> > > >  * eSDHC cannot support End Attribute in NOP ADMA descriptor
> > > >  */
> > > > -   .quirks = ESDHC_DEFAULT_QUIRKS | 
> > > > SDHCI_QUIRK_BROKEN_CARD_DETECTION
> > > > +   .quirks = ESDHC_DEFAULT_QUIRKS
> > > > | SDHCI_QUIRK_NO_CARD_NO_RESET
> > > > | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
> > > > .ops = &sdhci_esdhc_ops,
> > > > --
> > > > 1.7.9.5
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] powerpc/esdhc: enable the card insert/remove interrupt

2012-10-26 Thread Anton Vorontsov
Hello Huang,

On Fri, Oct 26, 2012 at 02:42:36AM +, Huang Changming-R66093 wrote:
> For the current polling mode, driver will send CMD13 to poll the card status 
> periodically , which will cause too many interrupts.
> Once I sent patches to detect the card when using polling mode last year: 
> read the state register, instead of send CMD13. But, these patches were not 
> accepted. Now I attach them for you.

Was there any specific reason why the patches didn't get accepted?

I very briefly looked at them, and they seem to be OK (there are a few
cosmetic details I'd comment on, tho -- but please send them in a normal
way (i.e. not as attachments).

Thanks,
Anton.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2 0/10] Fixes for common mistakes w/ for_each_process and task->mm

2012-03-24 Thread Anton Vorontsov
Hi all,

This is a reincarnation of the task->mm fixes. Several architectures
were traverse the tasklist in an unsafe manner, plus there are a
few cases of unsafe access to task->mm.

In v2 I decided to introduce a small helper in cpu.c: most arches
duplicate the same [buggy] code snippet, so it's better to fix it
and move the logic into a common function.

Thanks!

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 01/10] cpu: Introduce clear_tasks_mm_cpumask() helper

2012-03-24 Thread Anton Vorontsov
Many architctures clear tasks' mm_cpumask like this:

read_lock(&tasklist_lock);
for_each_process(p) {
if (p->mm)
cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
}
read_unlock(&tasklist_lock);

The code above has several problems, such as:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

This patch implements a small helper function that does things
correctly, i.e.:

1. We take the task's lock while whe handle its mm (we can't use
   get_task_mm()/mmput() pair as mmput() might sleep);

2. To catch exited main thread case, we use find_lock_task_mm(),
   which walks up all threads and returns an appropriate task
   (with task lock held).

Signed-off-by: Anton Vorontsov 
---
 include/linux/cpu.h |1 +
 kernel/cpu.c|   18 ++
 2 files changed, 19 insertions(+)

diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 1f65875..941e865 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -171,6 +171,7 @@ extern void put_online_cpus(void);
 #define hotcpu_notifier(fn, pri)   cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
+void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2060c6e..5255936 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -171,6 +172,23 @@ void __ref unregister_cpu_notifier(struct notifier_block 
*nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+void clear_tasks_mm_cpumask(int cpu)
+{
+   struct task_struct *p;
+
+   read_lock(&tasklist_lock);
+   for_each_process(p) {
+   struct task_struct *t;
+
+   t = find_lock_task_mm(p);
+   if (!t)
+   continue;
+   cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
+   task_unlock(t);
+   }
+   read_unlock(&tasklist_lock);
+}
+
 static inline void check_for_tasks(int cpu)
 {
struct task_struct *p;
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 02/10] arm: Use clear_tasks_mm_cpumask()

2012-03-24 Thread Anton Vorontsov
Current CPU hotplug code has some task->mm handling issues:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we must take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To fix this we would need to use find_lock_task_mm(), which would
   walk up all threads and returns an appropriate task (with task
   lock held).

clear_tasks_mm_cpumask() has all the issues fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/arm/kernel/smp.c |8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index cdeb727..880b93a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -136,7 +136,6 @@ static void percpu_timer_stop(void);
 int __cpu_disable(void)
 {
unsigned int cpu = smp_processor_id();
-   struct task_struct *p;
int ret;
 
ret = platform_cpu_disable(cpu);
@@ -166,12 +165,7 @@ int __cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
 
-   read_lock(&tasklist_lock);
-   for_each_process(p) {
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   }
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
 
return 0;
 }
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 03/10] powerpc: Use clear_tasks_mm_cpumask()

2012-03-24 Thread Anton Vorontsov
Current CPU hotplug code has some task->mm handling issues:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we must take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To fix this we would need to use find_lock_task_mm(), which would
   walk up all threads and returns an appropriate task (with task
   lock held).

clear_tasks_mm_cpumask() has all the issues fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/mm/mmu_context_nohash.c |   11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/mm/mmu_context_nohash.c 
b/arch/powerpc/mm/mmu_context_nohash.c
index 5b63bd3..e779642 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -333,9 +333,7 @@ static int __cpuinit mmu_context_cpu_notify(struct 
notifier_block *self,
unsigned long action, void *hcpu)
 {
unsigned int cpu = (unsigned int)(long)hcpu;
-#ifdef CONFIG_HOTPLUG_CPU
-   struct task_struct *p;
-#endif
+
/* We don't touch CPU 0 map, it's allocated at aboot and kept
 * around forever
 */
@@ -358,12 +356,7 @@ static int __cpuinit mmu_context_cpu_notify(struct 
notifier_block *self,
stale_map[cpu] = NULL;
 
/* We also clear the cpu_vm_mask bits of CPUs going away */
-   read_lock(&tasklist_lock);
-   for_each_process(p) {
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   }
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
break;
 #endif /* CONFIG_HOTPLUG_CPU */
}
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 04/10] sh: Use clear_tasks_mm_cpumask()

2012-03-24 Thread Anton Vorontsov
Current CPU hotplug code has some task->mm handling issues:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we must take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To fix this we would need to use find_lock_task_mm(), which would
   walk up all threads and returns an appropriate task (with task
   lock held).

clear_tasks_mm_cpumask() has all the issues fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/sh/kernel/smp.c |7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index f624174..2470c83 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -123,7 +123,6 @@ void native_play_dead(void)
 int __cpu_disable(void)
 {
unsigned int cpu = smp_processor_id();
-   struct task_struct *p;
int ret;
 
ret = mp_ops->cpu_disable(cpu);
@@ -153,11 +152,7 @@ int __cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
 
-   read_lock(&tasklist_lock);
-   for_each_process(p)
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
 
return 0;
 }
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 05/10] blackfin: A couple of task->mm handling fixes

2012-03-24 Thread Anton Vorontsov
The patch fixes two problems:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we have to take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To catch this we use find_lock_task_mm(), which walks up all
   threads and returns an appropriate task (with task lock held).

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/blackfin/kernel/trace.c |   26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index 050db44..5102cdf 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -27,7 +29,6 @@ void decode_address(char *buf, unsigned long address)
struct task_struct *p;
struct mm_struct *mm;
unsigned long flags, offset;
-   unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
struct rb_node *n;
 
 #ifdef CONFIG_KALLSYMS
@@ -113,15 +114,15 @@ void decode_address(char *buf, unsigned long address)
 */
write_lock_irqsave(&tasklist_lock, flags);
for_each_process(p) {
-   mm = (in_atomic ? p->mm : get_task_mm(p));
-   if (!mm)
-   continue;
+   struct task_struct *t;
 
-   if (!down_read_trylock(&mm->mmap_sem)) {
-   if (!in_atomic)
-   mmput(mm);
+   t = find_lock_task_mm(p);
+   if (!t)
continue;
-   }
+
+   mm = t->mm;
+   if (!down_read_trylock(&mm->mmap_sem))
+   goto __continue;
 
for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
struct vm_area_struct *vma;
@@ -130,7 +131,7 @@ void decode_address(char *buf, unsigned long address)
 
if (address >= vma->vm_start && address < vma->vm_end) {
char _tmpbuf[256];
-   char *name = p->comm;
+   char *name = t->comm;
struct file *file = vma->vm_file;
 
if (file) {
@@ -163,8 +164,7 @@ void decode_address(char *buf, unsigned long address)
name, vma->vm_start, 
vma->vm_end);
 
up_read(&mm->mmap_sem);
-   if (!in_atomic)
-   mmput(mm);
+   task_unlock(t);
 
if (buf[0] == '\0')
sprintf(buf, "[ %s ] dynamic memory", 
name);
@@ -174,8 +174,8 @@ void decode_address(char *buf, unsigned long address)
}
 
up_read(&mm->mmap_sem);
-   if (!in_atomic)
-   mmput(mm);
+__continue:
+   task_unlock(t);
}
 
/*
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 06/10] blackfin: Fix possible deadlock in decode_address()

2012-03-24 Thread Anton Vorontsov
Oleg Nesterov found an interesting deadlock possibility:

> sysrq_showregs_othercpus() does smp_call_function(showacpu)
> and showacpu() show_stack()->decode_address(). Now suppose that IPI
> interrupts the task holding read_lock(tasklist).

To fix this, blackfin should not grab the write_ variant of the
tasklist lock, read_ one is enough.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/blackfin/kernel/trace.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index 5102cdf..9cc9302 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -28,7 +28,7 @@ void decode_address(char *buf, unsigned long address)
 {
struct task_struct *p;
struct mm_struct *mm;
-   unsigned long flags, offset;
+   unsigned long offset;
struct rb_node *n;
 
 #ifdef CONFIG_KALLSYMS
@@ -112,7 +112,7 @@ void decode_address(char *buf, unsigned long address)
 * mappings of all our processes and see if we can't be a whee
 * bit more specific
 */
-   write_lock_irqsave(&tasklist_lock, flags);
+   read_lock(&tasklist_lock);
for_each_process(p) {
struct task_struct *t;
 
@@ -185,7 +185,7 @@ __continue:
sprintf(buf, "/* kernel dynamic memory */");
 
 done:
-   write_unlock_irqrestore(&tasklist_lock, flags);
+   read_unlock(&tasklist_lock);
 }
 
 #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 07/10] um: Should hold tasklist_lock while traversing processes

2012-03-24 Thread Anton Vorontsov
Traversing the tasks requires holding tasklist_lock, otherwise it
is unsafe.

p.s. However, I'm not sure that calling os_kill_ptraced_process()
in the atomic context is correct. It seem to work, but please
take a closer look.

Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 4d93dff..66d754c 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
  */
 
 #include "linux/sched.h"
+#include "linux/spinlock.h"
 #include "linux/slab.h"
 #include "kern_util.h"
 #include "os.h"
@@ -22,6 +23,7 @@ static void kill_off_processes(void)
struct task_struct *p;
int pid;
 
+   read_lock(&tasklist_lock);
for_each_process(p) {
if (p->mm == NULL)
continue;
@@ -29,6 +31,7 @@ static void kill_off_processes(void)
pid = p->mm->context.id.u.pid;
os_kill_ptraced_process(pid, 1);
}
+   read_unlock(&tasklist_lock);
}
 }
 
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 08/10] um: Fix possible race on task->mm

2012-03-24 Thread Anton Vorontsov
Checking for task->mm is dangerous as ->mm might disappear (exit_mm()
assigns NULL under task_lock(), so tasklist lock is not enough).

We can't use get_task_mm()/mmput() pair as mmput() might sleep,
so let's take the task lock while we care about its mm.

Note that we should also use find_lock_task_mm() to check all process'
threads for a valid mm, but for uml we'll do it in a separate patch.

Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 66d754c..1411f4e 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -25,10 +25,13 @@ static void kill_off_processes(void)
 
read_lock(&tasklist_lock);
for_each_process(p) {
-   if (p->mm == NULL)
+   task_lock(p);
+   if (!p->mm) {
+   task_unlock(p);
continue;
-
+   }
pid = p->mm->context.id.u.pid;
+   task_unlock(p);
os_kill_ptraced_process(pid, 1);
}
read_unlock(&tasklist_lock);
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 09/10] um: Properly check all process' threads for a live mm

2012-03-24 Thread Anton Vorontsov
kill_off_processes() might miss a valid process, this is because
checking for process->mm is not enough. Process' main thread may
exit or detach its mm via use_mm(), but other threads may still
have a valid mm.

To catch this we use find_lock_task_mm(), which walks up all
threads and returns an appropriate task (with task lock held).

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |   13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 1411f4e..3d15243 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -6,6 +6,7 @@
 #include "linux/sched.h"
 #include "linux/spinlock.h"
 #include "linux/slab.h"
+#include "linux/oom.h"
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
@@ -25,13 +26,13 @@ static void kill_off_processes(void)
 
read_lock(&tasklist_lock);
for_each_process(p) {
-   task_lock(p);
-   if (!p->mm) {
-   task_unlock(p);
+   struct task_struct *t;
+
+   t = find_lock_task_mm(p);
+   if (!t)
continue;
-   }
-   pid = p->mm->context.id.u.pid;
-   task_unlock(p);
+   pid = t->mm->context.id.u.pid;
+   task_unlock(t);
os_kill_ptraced_process(pid, 1);
}
read_unlock(&tasklist_lock);
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 10/10] oom: Make find_lock_task_mm() sparse-aware

2012-03-24 Thread Anton Vorontsov
This is needed so that callers would not get 'context imbalance'
warnings from the sparse tool.

As a side effect, this patch fixes the following sparse warnings:

  CHECK   mm/oom_kill.c
  mm/oom_kill.c:201:28: warning: context imbalance in 'oom_badness' -
  unexpected unlock
  include/linux/rcupdate.h:249:30: warning: context imbalance in
  'dump_tasks' - unexpected unlock
  mm/oom_kill.c:453:9: warning: context imbalance in 'oom_kill_task' -
  unexpected unlock
  CHECK   mm/memcontrol.c
  ...
  mm/memcontrol.c:1130:17: warning: context imbalance in
  'task_in_mem_cgroup' - unexpected unlock

p.s. I know Peter Zijlstra detest the __cond_lock() stuff, but untill
 we have anything better in sparse, let's use it. This particular
 patch helped me to detect one bug that I myself made during
 task->mm fixup series. So, it is useful.

Signed-off-by: Anton Vorontsov 
Acked-by: KOSAKI Motohiro 
---
 include/linux/oom.h |   12 +++-
 mm/oom_kill.c   |2 +-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/linux/oom.h b/include/linux/oom.h
index 552fba9..26cf628 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -21,6 +21,7 @@
 
 #ifdef __KERNEL__
 
+#include 
 #include 
 #include 
 #include 
@@ -65,7 +66,16 @@ static inline void oom_killer_enable(void)
oom_killer_disabled = false;
 }
 
-extern struct task_struct *find_lock_task_mm(struct task_struct *p);
+extern struct task_struct *__find_lock_task_mm(struct task_struct *p);
+
+static inline struct task_struct *find_lock_task_mm(struct task_struct *p)
+{
+   struct task_struct *ret;
+
+   ret = __find_lock_task_mm(p);
+   (void)__cond_lock(&ret->alloc_lock, ret);
+   return ret;
+}
 
 /* sysctls */
 extern int sysctl_oom_dump_tasks;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2958fd8..0ebb383 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -136,7 +136,7 @@ static bool has_intersects_mems_allowed(struct task_struct 
*tsk,
  * pointer.  Return p, or any of its subthreads with a valid ->mm, with
  * task_lock() held.
  */
-struct task_struct *find_lock_task_mm(struct task_struct *p)
+struct task_struct *__find_lock_task_mm(struct task_struct *p)
 {
struct task_struct *t = p;
 
-- 
1.7.9.2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 10/10] oom: Make find_lock_task_mm() sparse-aware

2012-03-24 Thread Anton Vorontsov
On Sat, Mar 24, 2012 at 01:52:54PM +0100, Peter Zijlstra wrote:
[...]
> > p.s. I know Peter Zijlstra detest the __cond_lock() stuff, but untill
> >  we have anything better in sparse, let's use it. This particular
> >  patch helped me to detect one bug that I myself made during
> >  task->mm fixup series. So, it is useful.
> 
> Yeah, so Nacked-by: Peter Zijlstra 
> 
> Also, why didn't lockdep catch it?

Because patch authors test their patches on architectures they own
(well, sometimes I do check patches on exotic architectures w/ qemu,
but it is less convenient than just build/sparse-test the patch w/
a cross compiler).

And since lockdep is a runtime checker, it is not very useful.

Sparse is a build-time checker, so it is even better in the sense
that it is able to catch bugs even in code that is executed rarely.

> Fix sparse already instead of smearing ugly all over.

Just wonder how do you see the feature implemented?

Something like this?

#define __ret_cond_locked(l, c) __attribute__((ret_cond_locked(l, c)))
#define __ret_value __attribute__((ret_value))
#define __ret_locked_nonnull(l) __ret_cond_locked(l, __ret_value);

extern struct task_struct *find_lock_task_mm(struct task_struct *p)
__ret_locked_nonnull(&__ret_value->alloc_lock);

Thanks,

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2.1 01/10] cpu: Introduce clear_tasks_mm_cpumask() helper

2012-03-24 Thread Anton Vorontsov
Many architctures clear tasks' mm_cpumask like this:

read_lock(&tasklist_lock);
for_each_process(p) {
if (p->mm)
cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
}
read_unlock(&tasklist_lock);

The code above has several problems, such as:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

This patch implements a small helper function that does things
correctly, i.e.:

1. We take the task's lock while whe handle its mm (we can't use
   get_task_mm()/mmput() pair as mmput() might sleep);

2. To catch exited main thread case, we use find_lock_task_mm(),
   which walks up all threads and returns an appropriate task
   (with task lock held).

Also, Per Peter Zijlstra's idea, now we don't grab tasklist_lock in
the new helper, instead we take the rcu read lock. We can do this
because the function is called after the cpu is taken down and marked
offline, so no new tasks will get this cpu set in their mm mask.

Signed-off-by: Anton Vorontsov 
---

On Sat, Mar 24, 2012 at 01:43:41PM +0100, Peter Zijlstra wrote:
> On Sat, 2012-03-24 at 14:27 +0400, Anton Vorontsov wrote:
> > +   read_unlock(&tasklist_lock);
> > +} 
> 
> Why bother with the tasklist_lock at all anymore, afaict you could use
> rcu_read_lock() here. This all is called after the cpu is taken down and
> marked offline, so its not like new tasks will ever get this cpu set in
> their mm mask.

I guess you're right. Well, this would make the code a bit fragile,
but a comment might help.

How about this version?

 include/linux/cpu.h |1 +
 kernel/cpu.c|   26 ++
 2 files changed, 27 insertions(+)

diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 1f65875..941e865 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -171,6 +171,7 @@ extern void put_online_cpus(void);
 #define hotcpu_notifier(fn, pri)   cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
+void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2060c6e..ecdf499 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -171,6 +173,30 @@ void __ref unregister_cpu_notifier(struct notifier_block 
*nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+void clear_tasks_mm_cpumask(int cpu)
+{
+   struct task_struct *p;
+
+   /*
+* This function is called after the cpu is taken down and marked
+* offline, so its not like new tasks will ever get this cpu set in
+* their mm mask. -- Peter Zijlstra
+* Thus, we may use rcu_read_lock() here, instead of grabbing
+* full-fledged tasklist_lock.
+*/
+   rcu_read_lock();
+   for_each_process(p) {
+   struct task_struct *t;
+
+   t = find_lock_task_mm(p);
+   if (!t)
+   continue;
+   cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
+   task_unlock(t);
+   }
+   rcu_read_unlock();
+}
+
 static inline void check_for_tasks(int cpu)
 {
struct task_struct *p;
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 07/10] um: Should hold tasklist_lock while traversing processes

2012-03-24 Thread Anton Vorontsov
On Sat, Mar 24, 2012 at 01:48:23PM +0100, Peter Zijlstra wrote:
> On Sat, 2012-03-24 at 14:30 +0400, Anton Vorontsov wrote:
> > Traversing the tasks requires holding tasklist_lock, otherwise it
> > is unsafe. 
> 
> No it doesn't, it either requires tasklist_lock or rcu_read_lock().

Well, currently the code does neither. :-)

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v3 0/9] Fixes for common mistakes w/ for_each_process and task->mm

2012-04-23 Thread Anton Vorontsov
Hi all,

This is another resend of several task->mm fixes, the bugs I found
during LMK code audit. Architectures were traverse the tasklist
in an unsafe manner, plus there are a few cases of unsafe access to
task->mm in general.

There were no objections on the previous resend, and the final words
were somewhere along "the patches are fine" line.

In v3:
- Dropped a controversal 'Make find_lock_task_mm() sparse-aware' patch;
- Reword arm and sh commit messages, per Oleg Nesterov's suggestions;
- Added an optimization trick in clear_tasks_mm_cpumask(): take only
  the rcu read lock, no need for the whole tasklist_lock.
  Suggested by Peter Zijlstra.

In v2: 
- introduced a small helper in cpu.c: most arches duplicate the
  same [buggy] code snippet, so it's better to fix it and move the
  logic into a common function.

Thanks,

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/9] cpu: Introduce clear_tasks_mm_cpumask() helper

2012-04-23 Thread Anton Vorontsov
Many architectures clear tasks' mm_cpumask like this:

read_lock(&tasklist_lock);
for_each_process(p) {
if (p->mm)
cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
}
read_unlock(&tasklist_lock);

Depending on the context, the code above may have several problems,
such as:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

This patch implements a small helper function that does things
correctly, i.e.:

1. We take the task's lock while whe handle its mm (we can't use
   get_task_mm()/mmput() pair as mmput() might sleep);

2. To catch exited main thread case, we use find_lock_task_mm(),
   which walks up all threads and returns an appropriate task
   (with task lock held).

Also, Per Peter Zijlstra's idea, now we don't grab tasklist_lock in
the new helper, instead we take the rcu read lock. We can do this
because the function is called after the cpu is taken down and marked
offline, so no new tasks will get this cpu set in their mm mask.

Signed-off-by: Anton Vorontsov 
---
 include/linux/cpu.h |1 +
 kernel/cpu.c|   26 ++
 2 files changed, 27 insertions(+)

diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index ee28844..d2ca49f 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -179,6 +179,7 @@ extern void put_online_cpus(void);
 #define hotcpu_notifier(fn, pri)   cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
+void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2060c6e..ecdf499 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -171,6 +173,30 @@ void __ref unregister_cpu_notifier(struct notifier_block 
*nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+void clear_tasks_mm_cpumask(int cpu)
+{
+   struct task_struct *p;
+
+   /*
+* This function is called after the cpu is taken down and marked
+* offline, so its not like new tasks will ever get this cpu set in
+* their mm mask. -- Peter Zijlstra
+* Thus, we may use rcu_read_lock() here, instead of grabbing
+* full-fledged tasklist_lock.
+*/
+   rcu_read_lock();
+   for_each_process(p) {
+   struct task_struct *t;
+
+   t = find_lock_task_mm(p);
+   if (!t)
+   continue;
+   cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
+   task_unlock(t);
+   }
+   rcu_read_unlock();
+}
+
 static inline void check_for_tasks(int cpu)
 {
struct task_struct *p;
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/9] arm: Use clear_tasks_mm_cpumask()

2012-04-23 Thread Anton Vorontsov
Checking for process->mm is not enough because process' main
thread may exit or detach its mm via use_mm(), but other threads
may still have a valid mm.

To fix this we would need to use find_lock_task_mm(), which would
walk up all threads and returns an appropriate task (with task
lock held).

clear_tasks_mm_cpumask() has this issue fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/arm/kernel/smp.c |8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index addbbe8..e824ee4 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -130,7 +130,6 @@ static void percpu_timer_stop(void);
 int __cpu_disable(void)
 {
unsigned int cpu = smp_processor_id();
-   struct task_struct *p;
int ret;
 
ret = platform_cpu_disable(cpu);
@@ -160,12 +159,7 @@ int __cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
 
-   read_lock(&tasklist_lock);
-   for_each_process(p) {
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   }
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
 
return 0;
 }
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/9] powerpc: Use clear_tasks_mm_cpumask()

2012-04-23 Thread Anton Vorontsov
Current CPU hotplug code has some task->mm handling issues:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we must take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To fix this we would need to use find_lock_task_mm(), which would
   walk up all threads and returns an appropriate task (with task
   lock held).

clear_tasks_mm_cpumask() has all the issues fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/mm/mmu_context_nohash.c |   11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/mm/mmu_context_nohash.c 
b/arch/powerpc/mm/mmu_context_nohash.c
index 5b63bd3..e779642 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -333,9 +333,7 @@ static int __cpuinit mmu_context_cpu_notify(struct 
notifier_block *self,
unsigned long action, void *hcpu)
 {
unsigned int cpu = (unsigned int)(long)hcpu;
-#ifdef CONFIG_HOTPLUG_CPU
-   struct task_struct *p;
-#endif
+
/* We don't touch CPU 0 map, it's allocated at aboot and kept
 * around forever
 */
@@ -358,12 +356,7 @@ static int __cpuinit mmu_context_cpu_notify(struct 
notifier_block *self,
stale_map[cpu] = NULL;
 
/* We also clear the cpu_vm_mask bits of CPUs going away */
-   read_lock(&tasklist_lock);
-   for_each_process(p) {
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   }
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
break;
 #endif /* CONFIG_HOTPLUG_CPU */
}
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 4/9] sh: Use clear_tasks_mm_cpumask()

2012-04-23 Thread Anton Vorontsov
Checking for process->mm is not enough because process' main
thread may exit or detach its mm via use_mm(), but other threads
may still have a valid mm.

To fix this we would need to use find_lock_task_mm(), which would
walk up all threads and returns an appropriate task (with task
lock held).

clear_tasks_mm_cpumask() has the issue fixed, so let's use it.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/sh/kernel/smp.c |7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index eaebdf6..4664f76 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -123,7 +123,6 @@ void native_play_dead(void)
 int __cpu_disable(void)
 {
unsigned int cpu = smp_processor_id();
-   struct task_struct *p;
int ret;
 
ret = mp_ops->cpu_disable(cpu);
@@ -153,11 +152,7 @@ int __cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
 
-   read_lock(&tasklist_lock);
-   for_each_process(p)
-   if (p->mm)
-   cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
-   read_unlock(&tasklist_lock);
+   clear_tasks_mm_cpumask(cpu);
 
return 0;
 }
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 5/9] blackfin: A couple of task->mm handling fixes

2012-04-23 Thread Anton Vorontsov
The patch fixes two problems:

1. Working with task->mm w/o getting mm or grabing the task lock is
   dangerous as ->mm might disappear (exit_mm() assigns NULL under
   task_lock(), so tasklist lock is not enough).

   We can't use get_task_mm()/mmput() pair as mmput() might sleep,
   so we have to take the task lock while handle its mm.

2. Checking for process->mm is not enough because process' main
   thread may exit or detach its mm via use_mm(), but other threads
   may still have a valid mm.

   To catch this we use find_lock_task_mm(), which walks up all
   threads and returns an appropriate task (with task lock held).

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/blackfin/kernel/trace.c |   26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index 44bbf2f..d08f0e3 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -28,7 +30,6 @@ void decode_address(char *buf, unsigned long address)
struct task_struct *p;
struct mm_struct *mm;
unsigned long flags, offset;
-   unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
struct rb_node *n;
 
 #ifdef CONFIG_KALLSYMS
@@ -114,15 +115,15 @@ void decode_address(char *buf, unsigned long address)
 */
write_lock_irqsave(&tasklist_lock, flags);
for_each_process(p) {
-   mm = (in_atomic ? p->mm : get_task_mm(p));
-   if (!mm)
-   continue;
+   struct task_struct *t;
 
-   if (!down_read_trylock(&mm->mmap_sem)) {
-   if (!in_atomic)
-   mmput(mm);
+   t = find_lock_task_mm(p);
+   if (!t)
continue;
-   }
+
+   mm = t->mm;
+   if (!down_read_trylock(&mm->mmap_sem))
+   goto __continue;
 
for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
struct vm_area_struct *vma;
@@ -131,7 +132,7 @@ void decode_address(char *buf, unsigned long address)
 
if (address >= vma->vm_start && address < vma->vm_end) {
char _tmpbuf[256];
-   char *name = p->comm;
+   char *name = t->comm;
struct file *file = vma->vm_file;
 
if (file) {
@@ -164,8 +165,7 @@ void decode_address(char *buf, unsigned long address)
name, vma->vm_start, 
vma->vm_end);
 
up_read(&mm->mmap_sem);
-   if (!in_atomic)
-   mmput(mm);
+   task_unlock(t);
 
if (buf[0] == '\0')
sprintf(buf, "[ %s ] dynamic memory", 
name);
@@ -175,8 +175,8 @@ void decode_address(char *buf, unsigned long address)
}
 
up_read(&mm->mmap_sem);
-   if (!in_atomic)
-   mmput(mm);
+__continue:
+   task_unlock(t);
}
 
/*
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 6/9] blackfin: Fix possible deadlock in decode_address()

2012-04-23 Thread Anton Vorontsov
Oleg Nesterov found an interesting deadlock possibility:

> sysrq_showregs_othercpus() does smp_call_function(showacpu)
> and showacpu() show_stack()->decode_address(). Now suppose that IPI
> interrupts the task holding read_lock(tasklist).

To fix this, blackfin should not grab the write_ variant of the
tasklist lock, read_ one is enough.

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/blackfin/kernel/trace.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index d08f0e3..f7f7a18 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -29,7 +29,7 @@ void decode_address(char *buf, unsigned long address)
 {
struct task_struct *p;
struct mm_struct *mm;
-   unsigned long flags, offset;
+   unsigned long offset;
struct rb_node *n;
 
 #ifdef CONFIG_KALLSYMS
@@ -113,7 +113,7 @@ void decode_address(char *buf, unsigned long address)
 * mappings of all our processes and see if we can't be a whee
 * bit more specific
 */
-   write_lock_irqsave(&tasklist_lock, flags);
+   read_lock(&tasklist_lock);
for_each_process(p) {
struct task_struct *t;
 
@@ -186,7 +186,7 @@ __continue:
sprintf(buf, "/* kernel dynamic memory */");
 
 done:
-   write_unlock_irqrestore(&tasklist_lock, flags);
+   read_unlock(&tasklist_lock);
 }
 
 #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 7/9] um: Should hold tasklist_lock while traversing processes

2012-04-23 Thread Anton Vorontsov
Traversing the tasks requires holding tasklist_lock, otherwise it
is unsafe.

p.s. However, I'm not sure that calling os_kill_ptraced_process()
in the atomic context is correct. It seem to work, but please
take a closer look.

Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 4d93dff..66d754c 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
  */
 
 #include "linux/sched.h"
+#include "linux/spinlock.h"
 #include "linux/slab.h"
 #include "kern_util.h"
 #include "os.h"
@@ -22,6 +23,7 @@ static void kill_off_processes(void)
struct task_struct *p;
int pid;
 
+   read_lock(&tasklist_lock);
for_each_process(p) {
if (p->mm == NULL)
continue;
@@ -29,6 +31,7 @@ static void kill_off_processes(void)
pid = p->mm->context.id.u.pid;
os_kill_ptraced_process(pid, 1);
}
+   read_unlock(&tasklist_lock);
}
 }
 
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 8/9] um: Fix possible race on task->mm

2012-04-23 Thread Anton Vorontsov
Checking for task->mm is dangerous as ->mm might disappear (exit_mm()
assigns NULL under task_lock(), so tasklist lock is not enough).

We can't use get_task_mm()/mmput() pair as mmput() might sleep,
so let's take the task lock while we care about its mm.

Note that we should also use find_lock_task_mm() to check all process'
threads for a valid mm, but for uml we'll do it in a separate patch.

Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 66d754c..1411f4e 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -25,10 +25,13 @@ static void kill_off_processes(void)
 
read_lock(&tasklist_lock);
for_each_process(p) {
-   if (p->mm == NULL)
+   task_lock(p);
+   if (!p->mm) {
+   task_unlock(p);
continue;
-
+   }
pid = p->mm->context.id.u.pid;
+   task_unlock(p);
os_kill_ptraced_process(pid, 1);
}
read_unlock(&tasklist_lock);
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 9/9] um: Properly check all process' threads for a live mm

2012-04-23 Thread Anton Vorontsov
kill_off_processes() might miss a valid process, this is because
checking for process->mm is not enough. Process' main thread may
exit or detach its mm via use_mm(), but other threads may still
have a valid mm.

To catch this we use find_lock_task_mm(), which walks up all
threads and returns an appropriate task (with task lock held).

Suggested-by: Oleg Nesterov 
Signed-off-by: Anton Vorontsov 
---
 arch/um/kernel/reboot.c |   13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 1411f4e..3d15243 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -6,6 +6,7 @@
 #include "linux/sched.h"
 #include "linux/spinlock.h"
 #include "linux/slab.h"
+#include "linux/oom.h"
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
@@ -25,13 +26,13 @@ static void kill_off_processes(void)
 
read_lock(&tasklist_lock);
for_each_process(p) {
-   task_lock(p);
-   if (!p->mm) {
-   task_unlock(p);
+   struct task_struct *t;
+
+   t = find_lock_task_mm(p);
+   if (!t)
continue;
-   }
-   pid = p->mm->context.id.u.pid;
-   task_unlock(p);
+   pid = t->mm->context.id.u.pid;
+   task_unlock(t);
os_kill_ptraced_process(pid, 1);
}
read_unlock(&tasklist_lock);
-- 
1.7.9.2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 7/9] um: Should hold tasklist_lock while traversing processes

2012-04-23 Thread Anton Vorontsov
On Mon, Apr 23, 2012 at 04:57:54PM +0200, Richard Weinberger wrote:
> On 23.04.2012 09:09, Anton Vorontsov wrote:
> >Traversing the tasks requires holding tasklist_lock, otherwise it
> >is unsafe.
> >
> >p.s. However, I'm not sure that calling os_kill_ptraced_process()
> >in the atomic context is correct. It seem to work, but please
> >take a closer look.
> >
> >Signed-off-by: Anton Vorontsov
> >---
> 
> You forgot my Ack and I've already explained why
> os_kill_ptraced_process() is fine.

Ouch, sorry!

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/9] cpu: Introduce clear_tasks_mm_cpumask() helper

2012-05-04 Thread Anton Vorontsov
On Thu, Apr 26, 2012 at 04:59:11PM -0700, Andrew Morton wrote:
[...]
> >  so its not like new tasks will ever get this cpu set in
> > +* their mm mask. -- Peter Zijlstra
> > +* Thus, we may use rcu_read_lock() here, instead of grabbing
> > +* full-fledged tasklist_lock.
> > +*/
> > +   rcu_read_lock();
> > +   for_each_process(p) {
> > +   struct task_struct *t;
> > +
> > +   t = find_lock_task_mm(p);
> > +   if (!t)
> > +   continue;
> > +   cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
> > +   task_unlock(t);
> > +   }
> > +   rcu_read_unlock();
> > +}
> 
> It is good that this code exists under CONFIG_HOTPLUG_CPU.  Did you
> check that everything works correctly with CONFIG_HOTPLUG_CPU=n?

Yeah, only the code under CONFIG_HOTPLUG_CPU calls the function, so
it should be all fine.

Thanks!

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] cpu: Document clear_tasks_mm_cpumask()

2012-05-04 Thread Anton Vorontsov
This patch adds more comments on clear_tasks_mm_cpumask, plus adds
a runtime check: the function is only suitable for offlined CPUs,
and if called inappropriately, the kernel should scream aloud.

Suggested-by: Andrew Morton 
Suggested-by: Peter Zijlstra 
Signed-off-by: Anton Vorontsov 
---

On Tue, May 01, 2012 at 12:45:33PM +0200, Peter Zijlstra wrote:
> On Thu, 2012-04-26 at 16:59 -0700, Andrew Morton wrote:
> > > +void clear_tasks_mm_cpumask(int cpu)
> > 
> > The operation of this function was presumably obvious to you at the
> > time you wrote it, but that isn't true of other people at later times.
> > 
> > Please document it?
[...]
> > If someone tries to use this function for a different purpose, or
> > copies-and-modifies it for a different purpose, we just shot them in
> > the foot.
> > 
> > They'd be pretty dumb to do that without reading the local comment,
> > but still...
> 
> Methinks something simple like:
> 
>   WARN_ON(cpu_online(cpu));
> 
> Ought to cure that worry, no? :-)

Yeah, this is all good ideas, thanks.

How about the following patch?

 kernel/cpu.c |   18 ++
 1 file changed, 18 insertions(+)

diff --git a/kernel/cpu.c b/kernel/cpu.c
index ecdf499..1bfa26f 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -173,6 +174,18 @@ void __ref unregister_cpu_notifier(struct notifier_block 
*nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+/**
+ * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
+ * @cpu: a CPU id
+ *
+ * This function walks up all processes, finds a valid mm struct for
+ * each one and then clears a corresponding bit in mm's cpumask. While
+ * this all sounds trivial, there are various non-obvious corner cases,
+ * which this function tries to solve in a safe manner.
+ *
+ * Also note that the function uses a somewhat relaxed locking scheme,
+ * so it may be called only for an already offlined CPU.
+ */
 void clear_tasks_mm_cpumask(int cpu)
 {
struct task_struct *p;
@@ -184,10 +197,15 @@ void clear_tasks_mm_cpumask(int cpu)
 * Thus, we may use rcu_read_lock() here, instead of grabbing
 * full-fledged tasklist_lock.
 */
+   WARN_ON(cpu_online(cpu));
rcu_read_lock();
for_each_process(p) {
struct task_struct *t;
 
+   /*
+* Main thread might exit, but other threads may still have
+* a valid mm. Find one.
+*/
t = find_lock_task_mm(p);
if (!t)
continue;
-- 
1.7.9.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] spi_mpc8xxx: issue with using definition of pram in Device Tree

2010-09-24 Thread Anton Vorontsov
Hello,

On Fri, Sep 24, 2010 at 09:20:27AM +0200, LEROY Christophe wrote:
> The issue is that cpm_muram_alloc_fixed() allocates memory from the
> general purpose muram area (from 0x0 to 0x1bff).
> Here we need to return a pointer to the parameter RAM, which is
> located somewhere starting at 0x1c00. It is not a dynamic allocation
> that is required here but only to point on the correct location in
> the parameter RAM.
> 
> For the CPM2, I don't know. I'm working with a MPC866.
> 
> Attached is a previous discussion on the subject where I explain a
> bit more in details the issue.

The patch looks OK, I think.

Doesn't explain why that worked on MPC8272 (CPM2) and MPC8560
(also CPM2) machines though. But here's my guess (I no longer
have these boards to test it):

On 8272 I used this node:

+   s...@4c0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   compatible = "fsl,cpm2-spi", "fsl,spi";
+   reg = <0x11a80 0x40 0x89fc 0x2>;

On that SOC there are two muram data regions 0x0..0x2000 and
0x9000..0x9100. Note that we actually don't want "data" regions,
and the only reason why that worked is that sysdev/cpm_common.c
maps muram(0)..muram(max).

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2 1/3] powerpc/fsl_soc.c: remove FSL USB platform code

2010-09-28 Thread Anton Vorontsov
On Tue, Sep 28, 2010 at 11:36:32AM +0200, Anatolij Gustschin wrote:
> This removed code will be replaced by simple of_platform
> driver for creation of FSL USB platform devices which is
> added by next patch of the series.
> 
> Signed-off-by: Anatolij Gustschin 
> Cc: Kumar Gala 
> Cc: Grant Likely 
> ---

This is not bisectable. You have to merge 1/3 and 2/3.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by page

2010-09-30 Thread Anton Vorontsov
On Thu, Sep 30, 2010 at 11:41:40PM +0900, Grant Likely wrote:
> On Thu, Sep 30, 2010 at 11:16 PM, Grant Likely
>  wrote:
> > On Thu, Sep 30, 2010 at 7:46 PM, David Brownell  wrote:
> >>
> >> --- On Thu, 9/30/10, Mingkai Hu  wrote:
> >>
> >>> From: Mingkai Hu 
> >>> Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by 
> >>> page
> >>
> >> NAK.
> >>
> >> We went over this before.
> >
> > Yes, I agree with David on this.  If large transfers don't work, then
> > it is the SPI master driver that is buggy.
> 
> By the way, does this fix your problem?
> 
> https://patchwork.kernel.org/patch/184752/

It shouldn't. AFAIK, eSPI is PIO-only controller, and the overrun
fix is for the DMA mode.

Thanks,

p.s. Btw, in patch 3/7, is_dma_mapped argument of fsl_espi_bufs()
is unneeded.

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH v3 3/7] eSPI: add eSPI controller support

2010-10-01 Thread Anton Vorontsov
(dev, master);
> +
> + ret = mpc8xxx_spi_probe(dev, mem, irq);
> + if (ret)
> + goto err_probe;
> +
> + master->setup = fsl_espi_setup;
> +
> + mpc8xxx_spi = spi_master_get_devdata(master);
> + mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
> + mpc8xxx_spi->spi_remove = fsl_espi_remove;
> +
> + mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
> + if (mpc8xxx_spi->reg_base == NULL) {

Ditto.

> + ret = -ENOMEM;
> + goto err_probe;
> + }
> +
> + reg_base = (struct fsl_espi_reg *)mpc8xxx_spi->reg_base;
> +
> + /* Register for SPI Interrupt */
> + ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
> +   0, "fsl_espi", mpc8xxx_spi);
> +
> + if (ret != 0)

Every time someone writes 'if (rc != 0)', a kitty dies.
Simple 'if (rc)' saves kittens.

> + goto free_irq;
> +
> + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> + mpc8xxx_spi->rx_shift = 16;
> + mpc8xxx_spi->tx_shift = 24;
> + }
[...]
> +
> +static int __devexit of_fsl_espi_remove(struct platform_device *dev)
> +{
> + int ret;
> +
> + ret = mpc8xxx_spi_remove(&dev->dev);
> + if (ret)
> + return ret;
> +
> + return 0;

Just 'return mpc8xxx_spi_remove(&dev->dev);' is sufficient.

Also, I think there's no need for this wrapper nowadays (but
splitting OF and real probe() stuff is still appropriate).

> +}
> +
> +static const struct of_device_id of_fsl_espi_match[] = {
> + { .compatible = "fsl,mpc8536-espi" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> +
> +static struct of_platform_driver fsl_espi_driver = {
> + .driver = {
> + .name = "fsl_espi",
> + .owner = THIS_MODULE,
> + .of_match_table = of_fsl_espi_match,
> + },
> + .probe  = of_fsl_espi_probe,
> + .remove = __devexit_p(of_fsl_espi_remove),
> +};
> +
> +static int __init fsl_espi_init(void)
> +{
> + return of_register_platform_driver(&fsl_espi_driver);
> +}
> +module_init(fsl_espi_init);
> +
> +static void __exit fsl_espi_exit(void)
> +{
> + of_unregister_platform_driver(&fsl_espi_driver);
> +}
> +module_exit(fsl_espi_exit);
> +
> +MODULE_AUTHOR("Mingkai Hu");
> +MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");

This sounds like that this is an enhanced version of the
Freescale SPI driver, which it is not. ;-)

> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
> index 6ae8949..9c81498 100644
> --- a/drivers/spi/spi_fsl_lib.h
> +++ b/drivers/spi/spi_fsl_lib.h
> @@ -26,6 +26,7 @@ struct mpc8xxx_spi {
>   /* rx & tx bufs from the spi_transfer */
>   const void *tx;
>   void *rx;
> + int len;

I'd place the #ifdef CONFIG_SPI_ESPI, for documentation purposes.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v3 2/7] spi/mpc8xxx: refactor the common code for SPI/eSPI controller

2010-10-01 Thread Anton Vorontsov
On Thu, Sep 30, 2010 at 04:00:41PM +0800, Mingkai Hu wrote:
[...]
> -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> +static void fsl_spi_change_mode(struct spi_device *spi)
>  {
>   struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
>   struct spi_mpc8xxx_cs *cs = spi->controller_state;
> - __be32 __iomem *mode = &mspi->base->mode;
> + struct fsl_spi_reg *reg_base = (struct fsl_spi_reg *)mspi->reg_base;

No need for these type casts (the same is for the whole patch).

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] edac: mpc85xx: Add support for new MPCxxx/Pxxxx EDAC controllers (fix)

2010-10-06 Thread Anton Vorontsov
On Thu, Oct 07, 2010 at 01:18:19AM -0500, Kumar Gala wrote:
[...]
> > diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
> > index cfa86f7..b178cfa 100644
> > --- a/drivers/edac/mpc85xx_edac.c
> > +++ b/drivers/edac/mpc85xx_edac.c
> > @@ -652,7 +652,6 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
> > { .compatible = "fsl,p1020-l2-cache-controller", },
> > { .compatible = "fsl,p1021-l2-cache-controller", },
> > { .compatible = "fsl,p2020-l2-cache-controller", },
> > -   { .compatible = "fsl,p4080-l2-cache-controller", },
> > {},
> > };
> > MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
> > -- 
> > 1.7.0.5
> 
> Can you post a new patch as it doesn't look like this got merged by Andrew so 
> we need to clean up after ourselves.

It's already in Linus' tree.

Thanks,

- - - -
commit cd1542c8197fc3c2eb3a8301505d5d9738fab1e4
Author: Anton Vorontsov 
Date:   Tue Aug 10 18:03:21 2010 -0700

edac: mpc85xx: add support for new MPCxxx/P EDAC controllers

Simply add proper IDs into the device table.

Signed-off-by: Anton Vorontsov 
Cc: Scott Wood 
Cc: Peter Tyser 
Cc: Dave Jiang 
Cc: Doug Thompson 
Signed-off-by: Andrew Morton 
Signed-off-by: Linus Torvalds 

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index fdbad55..af75e27 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -647,7 +647,10 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
{ .compatible = "fsl,mpc8555-l2-cache-controller", },
{ .compatible = "fsl,mpc8560-l2-cache-controller", },
{ .compatible = "fsl,mpc8568-l2-cache-controller", },
+   { .compatible = "fsl,mpc8569-l2-cache-controller", },
{ .compatible = "fsl,mpc8572-l2-cache-controller", },
+   { .compatible = "fsl,p1020-l2-cache-controller", },
+   { .compatible = "fsl,p1021-l2-cache-controller", },
{ .compatible = "fsl,p2020-l2-cache-controller", },
{},
 };
@@ -1125,7 +1128,10 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
{ .compatible = "fsl,mpc8569-memory-controller", },
{ .compatible = "fsl,mpc8572-memory-controller", },
{ .compatible = "fsl,mpc8349-memory-controller", },
+   { .compatible = "fsl,p1020-memory-controller", },
+   { .compatible = "fsl,p1021-memory-controller", },
{ .compatible = "fsl,p2020-memory-controller", },
+   { .compatible = "fsl,p4080-memory-controller", },
{},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] edac: mpc85xx: Add support for new MPCxxx/Pxxxx EDAC controllers (fix)

2010-10-07 Thread Anton Vorontsov
On Thu, Oct 07, 2010 at 02:00:50AM -0500, Kumar Gala wrote:
> 
> On Oct 7, 2010, at 1:37 AM, Kumar Gala wrote:
> 
> >> @ -1125,7 +1128,10 @@ static struct of_device_id mpc85xx_mc_err_of_match[] 
> >> = {
> >>{ .compatible = "fsl,mpc8569-memory-controller", },
> >>{ .compatible = "fsl,mpc8572-memory-controller", },
> >>{ .compatible = "fsl,mpc8349-memory-controller", },
> >> +  { .compatible = "fsl,p1020-memory-controller", },
> >> +  { .compatible = "fsl,p1021-memory-controller", },
> >>{ .compatible = "fsl,p2020-memory-controller", },
> >> +  { .compatible = "fsl,p4080-memory-controller", },
> > 
> > This line should be here ;)
> 
> should NOT be here.

Hm. Are you sure? I thought that only L2 cache controller is
not applicable (and based on Scott's comment I removed
the l2 cache compatible entry for p4080). But I guess
memory-controller is somewhat similar to all other 85xx?

If it's not, I can surely prepare a patch that removes
p4080 entry.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/2] ucc_geth: Do not bring the whole IF down when TX failure.

2010-11-12 Thread Anton Vorontsov
On Fri, Nov 12, 2010 at 02:55:08PM +0100, Joakim Tjernlund wrote:
> ucc_geth_close lacks a cancel_work_sync(&ugeth->timeout_work)
> to stop any outstanding processing of TX fail. However, one
> can not call cancel_work_sync without fixing the timeout function
> otherwise it will deadlock. This patch brings ucc_geth in line with
> gianfar:
> 
> Don't bring the interface down and up, just reinit controller HW
> and PHY.
> 
> Signed-off-by: Joakim Tjernlund 

Looks sane, thanks!

Reviewed-by: Anton Vorontsov 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] ucc_geth: Fix deadlock

2010-11-12 Thread Anton Vorontsov
On Fri, Nov 12, 2010 at 02:55:09PM +0100, Joakim Tjernlund wrote:
> This script:
>  while [ 1==1 ] ; do ifconfig eth0 up; usleep 195 ;ifconfig eth0 down; 
> dmesg -c ;done
> causes in just a second or two:
> INFO: task ifconfig:572 blocked for more than 120 seconds.
[...]
> The reason appears to be ucc_geth_stop meets adjust_link as the
> PHY reports PHY changes. I belive adjust_link hangs somewhere,
> holding the PHY lock, because ucc_geth_stop disabled the
> controller HW.
> Fix is to stop the PHY before disabling the controller.
> 
> Signed-off-by: Joakim Tjernlund 

It's unclear where exactly adjust_link() hangs, but the patch
looks as the right thing overall.

Thanks!

Reviewed-by: Anton Vorontsov 

> ---
>  drivers/net/ucc_geth.c |   10 +++---
>  1 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
> index 6c254ed..06a5db3 100644
> --- a/drivers/net/ucc_geth.c
> +++ b/drivers/net/ucc_geth.c
> @@ -2050,12 +2050,16 @@ static void ucc_geth_stop(struct ucc_geth_private 
> *ugeth)
>  
>   ugeth_vdbg("%s: IN", __func__);
>  
> + /*
> +  * Tell the kernel the link is down.
> +  * Must be done before disabling the controller
> +  * or deadlock may happen.
> +  */
> + phy_stop(phydev);
> +
>   /* Disable the controller */
>   ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
>  
> - /* Tell the kernel the link is down */
> - phy_stop(phydev);
> -
>   /* Mask all interrupts */
>   out_be32(ugeth->uccf->p_uccm, 0x);
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] powerpc: pcm030/032: add pagesize to dts

2010-11-15 Thread Anton Vorontsov
On Mon, Nov 15, 2010 at 06:25:16PM +0100, Wolfram Sang wrote:
> Signed-off-by: Wolfram Sang 
> ---
>  arch/powerpc/boot/dts/pcm030.dts |1 +
>  arch/powerpc/boot/dts/pcm032.dts |3 ++-
>  2 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/boot/dts/pcm030.dts 
> b/arch/powerpc/boot/dts/pcm030.dts
> index 8a4ec30..e7c36bc 100644
> --- a/arch/powerpc/boot/dts/pcm030.dts
> +++ b/arch/powerpc/boot/dts/pcm030.dts
> @@ -259,6 +259,7 @@
>   eep...@52 {
>   compatible = "catalyst,24c32";
>   reg = <0x52>;
> + pagesize = <32>;

I think you'd better drop the pagesize property altogether, and
instead make the compatible string more specific (if needed at
all. are there any 'catalyst,24c32' chips with pagesize != 32?)

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] powerpc: pcm030/032: add pagesize to dts

2010-11-15 Thread Anton Vorontsov
On Mon, Nov 15, 2010 at 11:06:44AM -1000, Mitch Bradley wrote:
[...]
> >>eep...@52 {
> >>compatible = "catalyst,24c32";
> >>reg =<0x52>;
> >>+   pagesize =<32>;
> >
> >I think you'd better drop the pagesize property altogether, and
> >instead make the compatible string more specific (if needed at
> >all. are there any 'catalyst,24c32' chips with pagesize != 32?)
> 
> Microchip makes a 24c32 part that looks pretty similar to the
> catalyst part, but Microchip's has a 64-byte page size compared to
> Catalyst's 32.

Well, when using microchip part, the compatible string would be
"microchip,24c32", correct? Then we have all the information
already, no need for the pagesize.

> It would probably be feasible to have a generic I2C EEPROM driver
> that could handle many different parts, parameterized by total size,
> block size, and page size.

I guess it can do this already via I2C ID table. The problem
is that I2C core is only using part ID (no vendor ID matching).

So, the current driver may just implement quirks like this:

if (of_device_is_compatible(np, "catalyst,24c32"))
pagesize = 32;

Or, if it's some generic pattern, something like

if (of_device_is_compatible_vendor(np, "catalyst"))
pagesize /= 2;

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] powerpc: pcm030/032: add pagesize to dts

2010-11-16 Thread Anton Vorontsov
On Tue, Nov 16, 2010 at 10:45:37PM +0100, Wolfram Sang wrote:
> 
> > Even worse, I seem to recall that I had once seen a manufacturer increasing 
> > the
> > page-size from one charge to the next without changing the part-number, so I
> > got this feeling "you can't map pagesize to manufacturer/type" which I still
> > have. Sadly, this was long ago, so I can't proof it right now. Will try to 
> > dig
> > up some datasheets when in the office tomorrow.
> 
> Had a look, couldn't find anything :( And now?

Well, it seems that there are enough people in "pagesize" camp
anyway, I'd say just go ahead with the current approach. :-)

It's an additional information, so won't do any harm anyway...

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] of_mmc_spi: add card detect irq support

2010-12-28 Thread Anton Vorontsov
On Mon, Aug 30, 2010 at 11:49:08AM -0600, Grant Likely wrote:
> On Mon, Aug 30, 2010 at 10:38 AM, David Brownell  wrote:
> > Since I don't do OpenFirmware, let's hear from
> > Grant on this one.
> 
> Looks good to me.
> 
> Acked-by: Grant Likely 

I wonder what happened with this patch?

Thanks,

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] gianfar: Fall back to software tcp/udp checksum on older controllers

2011-01-27 Thread Anton Vorontsov
Hello Alex,

On Thu, Jan 27, 2011 at 12:14:21AM -0800, Alex Dubov wrote:
> As specified by errata eTSEC49 of MPC8548 and errata eTSEC12 of MPC83xx,
> older revisions of gianfar controllers will be unable to calculate a TCP/UDP
> packet checksum for some aligments of the appropriate FCB. This patch checks
> for FCB alignment on such controllers and falls back to software checksumming
> if the aligment is known to be bad.
> 
> Signed-off-by: Alex Dubov 
> ---
> This is my, somewhat different approach to Matthew Creech proposed solution.
> 
>  drivers/net/gianfar.c |   21 +++--
>  drivers/net/gianfar.h |1 +
>  2 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
> index 5ed8f9f..b4f0e99 100644
> --- a/drivers/net/gianfar.c
> +++ b/drivers/net/gianfar.c
> @@ -950,6 +950,11 @@ static void gfar_detect_errata(struct gfar_private *priv)
>   (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
>   priv->errata |= GFAR_ERRATA_A002;
>  
> + /* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
> + if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020)
> + || (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))

Please indent it like the above: with two tabs. This is
to keep things consistent.

> + priv->errata |= GFAR_ERRATA_12;
> +
>   if (priv->errata)
>   dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
>priv->errata);
> @@ -2156,8 +2161,20 @@ static int gfar_start_xmit(struct sk_buff *skb, struct 
> net_device *dev)
>   /* Set up checksumming */
>   if (CHECKSUM_PARTIAL == skb->ip_summed) {
>   fcb = gfar_add_fcb(skb);
> - lstatus |= BD_LFLAG(TXBD_TOE);
> - gfar_tx_checksum(skb, fcb);
> + switch (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12))
> + ? 1 : 0) {

The switch construction is quite bizarre. ;-) Why not

if (gfar_has_errata() && (ulong)fcb % 0x20 > 18) {
csum_help();
} else {
lstatus |=...
tx_csum();
}

?

Thanks,

> + case 1:
> + /* as specified by errata */
> + if (((unsigned long)fcb % 0x20) > 0x18) { 
> + __skb_pull(skb, GMAC_FCB_LEN);
> + skb_checksum_help(skb);
> + break;
> +     }
> + /* otherwise, fall through */
> + default:
> + lstatus |= BD_LFLAG(TXBD_TOE);
> + gfar_tx_checksum(skb, fcb);
> + }
>   }

-- 
Anton Vorontsov
Email: cbouatmai...@gmail.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] qe_lib: Set gpio data before changing the direction to output

2009-08-18 Thread Anton Vorontsov
On Tue, Aug 18, 2009 at 05:20:44PM -0400, Michael Barkowski wrote:
> This avoids having a short glitch if the desired initial value is not
> the same as what was previously in the data register.
> 
> Signed-off-by: Michael Barkowski 

Acked-by: Anton Vorontsov 

Thanks!

> ---
> Anton Vorontsov wrote:
> > There is a recursive locking bug: _set() takes the same spinlock.
> > So you'd better move this call two lines upper. Otherwise the
> > patch looks OK.
> > 
> > Thanks!
> 
> Thanks - here is v2.
> 
>  arch/powerpc/sysdev/qe_lib/gpio.c |4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c 
> b/arch/powerpc/sysdev/qe_lib/gpio.c
> index 3485288..8e7a776 100644
> --- a/arch/powerpc/sysdev/qe_lib/gpio.c
> +++ b/arch/powerpc/sysdev/qe_lib/gpio.c
> @@ -105,14 +105,14 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, 
> unsigned int gpio, int val)
>   struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
>   unsigned long flags;
>  
> + qe_gpio_set(gc, gpio, val);
> +
>   spin_lock_irqsave(&qe_gc->lock, flags);
>  
>   __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
>  
>   spin_unlock_irqrestore(&qe_gc->lock, flags);
>  
> - qe_gpio_set(gc, gpio, val);
> -
>   return 0;
>  }
>  
> -- 
> 1.6.3.3
> 

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2 0/6] Device table matching for SPI subsystem

2009-08-18 Thread Anton Vorontsov
On Mon, Aug 10, 2009 at 10:35:23AM +0300, Artem Bityutskiy wrote:
> On Fri, 2009-07-31 at 04:39 +0400, Anton Vorontsov wrote:
> > Andrew,
> > 
> > This new patch set overwrites following patches:
> > 
> >   hwmon-lm70-convert-to-device-table-matching.patch
> >   hwmon-adxx-convert-to-device-table-matching.patch
> >   spi-merge-probe-and-probe_id-callbacks.patch
> >   spi-prefix-modalias-with-spi.patch
> >   of-remove-stmm25p40-alias.patch
> >   mtd-m25p80-convert-to-device-table-matching.patch
> >   spi-add-support-for-device-table-matching.patch
> 
> Are you going to send v3 and address David's comments?

No v3, but I'm going to address David's comments in a follow up
patch set where I'll change the probing code anyway.

> Do you want some of these patches to go via the MTD tree or
> they better go as a series via some other tree?

Um.. The MTD patches depend on SPI subsystem changes... If
David and Andrew are OK with SPI patches going through MTD tree,
then I'm fine with it as well.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/6] mtd: m25p80: Convert to device table matching

2009-08-18 Thread Anton Vorontsov
Hi David,

Thanks for the review, and sorry for the delayed response.

On Mon, Aug 03, 2009 at 07:54:50PM -0700, David Brownell wrote:
> On Thursday 30 July 2009, Anton Vorontsov wrote:
> > This patch converts the m25p80 driver so that now it uses .id_table
> > for device matching, making it properly detect devices on OpenFirmware
> > platforms (prior to this patch the driver misdetected non-JEDEC chips,
> > seeing all chips as "m25p80").
> 
> I suspect "detect" is a misnomer there.  It only "detects" JEDEC chips.

Currently the driver always tries JEDEC probing, and it wrongly "assumed"
that all non-JEDEC chips are m25p80, because an entry for m25p80 chips
had "0" in jedec id field, which isn't correct ID, but 0 is returned by
most non-JEDEC chips. Having 0 in the m25p80 entry was a hack.

> All others got explicit declarations ... so if there's misbehavior for
> other chips, it's because those declarations were poorly handled.  Maybe
> they were not properly flagged as non-JDEC

> > Also, now jedec_probe() only does jedec probing, nothing else. If it
> > is not able to detect a chip, NULL is returned and the driver fall
> > backs to the information specified by the platform (platform_data, or
> > exact ID).
> 
> I'd rather keep the warning, so there's a clue about what's really
> going on:  JEDEC chip found, but its ID is not handled.

We can't tell if the chip was actually found.

M25Px0 chips can be JEDEC and non-JEDEC, e.g. Nymonyx manufacturing
"M25P80" chips in two variants: "The RDID instruction is available only
for parts made with Technology T9HX (0.11μm), ..."

Most (but not all) non-JEDEC EEPROMs will return "0" for RDID opcode
though (in that case warning is misleading). And for the chips that
don't return 0, we shouldn't probe them with jedec at all.

[...]
> > @@ -608,32 +615,38 @@ static int __devinit m25p_probe(struct spi_device 
> > *spi)
> >  */
> > data = spi->dev.platform_data;
> > if (data && data->type) {
> 
> At this point I wonder why you're not changing the probe sequence
> more.

Yep, I was going to do it anyway, but for another reason: to support
CAT25 chips.

> There's a new error case of course:  new-style but data->type
> doesn't match id->name.
[...]
> > +   if (i == ARRAY_SIZE(m25p_ids) - 1) {
> 
> Better:  "if (info == NULL) ..."   You've got all the pointers
> in hand; don't use indices.
[...]
> > +   if (id != &m25p_ids[i]) {
> 
> Again, don't use indices except during the lookup.

Yep, good ideas. Though, the code will vanish anyway.

Patches on the way...
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 1/2] mtd: m25p80: Rework probing/JEDEC code

2009-08-18 Thread Anton Vorontsov
Previosly the driver always tried JEDEC probing, assuming that non-JEDEC
chips will return '0'. But truly non-JEDEC chips (like CAT25) won't do
that, their behaviour on RDID command is undefined, so the driver should
not call jedec_probe() for these chips.

Also, be less strict on error conditions, don't fail to probe if JEDEC
found a chip that is different from what platform code told, instead
just print some warnings and use an information obtained via JEDEC. In
that case we should not trust partitions any longer, but they might be
still useful (i.e. they could protect some parts of the chip).

Signed-off-by: Anton Vorontsov 
---
 drivers/mtd/devices/m25p80.c |   69 -
 1 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 0d74b38..b75e319 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -581,6 +581,14 @@ static const struct spi_device_id *__devinit 
jedec_probe(struct spi_device *spi)
jedec = jedec << 8;
jedec |= id[2];
 
+   /*
+* Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
+* which depend on technology process. Officially RDID command doesn't
+* exist for non-JEDEC chips, but for compatibility they return ID 0.
+*/
+   if (jedec == 0)
+   return NULL;
+
ext_jedec = id[3] << 8 | id[4];
 
for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
@@ -602,7 +610,7 @@ static const struct spi_device_id *__devinit 
jedec_probe(struct spi_device *spi)
  */
 static int __devinit m25p_probe(struct spi_device *spi)
 {
-   const struct spi_device_id  *id;
+   const struct spi_device_id  *id = spi_get_device_id(spi);
struct flash_platform_data  *data;
struct m25p *flash;
struct flash_info   *info;
@@ -615,41 +623,44 @@ static int __devinit m25p_probe(struct spi_device *spi)
 */
data = spi->dev.platform_data;
if (data && data->type) {
+   const struct spi_device_id *plat_id;
+
for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
-   id = &m25p_ids[i];
-   info = (void *)m25p_ids[i].driver_data;
-   if (strcmp(data->type, id->name))
+   plat_id = &m25p_ids[i];
+   if (strcmp(data->type, plat_id->name))
continue;
break;
}
 
-   /* unrecognized chip? */
-   if (i == ARRAY_SIZE(m25p_ids) - 1) {
-   DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
-   dev_name(&spi->dev), data->type);
-   info = NULL;
-
-   /* recognized; is that chip really what's there? */
-   } else if (info->jedec_id) {
-   id = jedec_probe(spi);
-
-   if (id != &m25p_ids[i]) {
-   dev_warn(&spi->dev, "found %s, expected %s\n",
-   id ? id->name : "UNKNOWN",
-   m25p_ids[i].name);
-   info = NULL;
-   }
-   }
-   } else {
-   id = jedec_probe(spi);
-   if (!id)
-   id = spi_get_device_id(spi);
-
-   info = (void *)id->driver_data;
+   if (plat_id)
+   id = plat_id;
+   else
+   dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
}
 
-   if (!info)
-   return -ENODEV;
+   info = (void *)id->driver_data;
+
+   if (info->jedec_id) {
+   const struct spi_device_id *jid;
+
+   jid = jedec_probe(spi);
+   if (!jid) {
+   dev_info(&spi->dev, "non-JEDEC variant of %s\n",
+id->name);
+   } else if (jid != id) {
+   /*
+* JEDEC knows better, so overwrite platform ID. We
+* can't trust partitions any longer, but we'll let
+* mtd apply them anyway, since some partitions may be
+* marked read-only, and we don't want to lose that
+* information, even if it's not 100% accurate.
+*/
+   dev_warn(&spi->dev, "found %s, expected %s\n",
+jid->name, id->name);
+   id = jid;
+

[PATCH 2/2] mtd: m25p80: Add support for CAT25xxx serial EEPROMs

2009-08-18 Thread Anton Vorontsov
CAT25 chips (as manufactured by On Semiconductor, previously Catalyst
Semiconductor) are similar to the original M25Px0 chips, except:

- Address width can vary (1-2 bytes, in contrast to 3 bytes in M25P
  chips). So, implement convenient m25p_addr2cmd() and m25p_cmdsz()
  calls, and place address width information into flash_info struct;

- Page size can vary, therefore we shouldn't hardcode it, so get rid
  of FLASH_PAGESIZE definition, and place the page size information
  into flash_info struct;

- CAT25 EEPROMs don't need to be erased, so add NO_ERASE flag, and
  propagate it to the mtd subsystem.

Signed-off-by: Anton Vorontsov 
---
 drivers/mtd/devices/m25p80.c |  172 --
 1 files changed, 97 insertions(+), 75 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index b75e319..8930266 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -29,9 +29,6 @@
 #include 
 #include 
 
-
-#define FLASH_PAGESIZE 256
-
 /* Flash opcodes. */
 #defineOPCODE_WREN 0x06/* Write enable */
 #defineOPCODE_RDSR 0x05/* Read status register */
@@ -56,7 +53,7 @@
 
 /* Define max times to check status register before we give up. */
 #defineMAX_READY_WAIT_JIFFIES  (40 * HZ)   /* M25P16 specs 40s max 
chip erase */
-#defineCMD_SIZE4
+#defineMAX_CMD_SIZE4
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define OPCODE_READOPCODE_FAST_READ
@@ -73,8 +70,10 @@ struct m25p {
struct mutexlock;
struct mtd_info mtd;
unsignedpartitioned:1;
+   u16 page_size;
+   u16 addr_width;
u8  erase_opcode;
-   u8  command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
+   u8  command[MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE];
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -184,6 +183,19 @@ static int erase_chip(struct m25p *flash)
return 0;
 }
 
+static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
+{
+   /* opcode is in cmd[0] */
+   cmd[1] = addr >> (flash->addr_width * 8 -  8);
+   cmd[2] = addr >> (flash->addr_width * 8 - 16);
+   cmd[3] = addr >> (flash->addr_width * 8 - 24);
+}
+
+static int m25p_cmdsz(struct m25p *flash)
+{
+   return 1 + flash->addr_width;
+}
+
 /*
  * Erase one sector of flash memory at offset ``offset'' which is any
  * address within the sector which should be erased.
@@ -205,11 +217,9 @@ static int erase_sector(struct m25p *flash, u32 offset)
 
/* Set up command buffer. */
flash->command[0] = flash->erase_opcode;
-   flash->command[1] = offset >> 16;
-   flash->command[2] = offset >> 8;
-   flash->command[3] = offset;
+   m25p_addr2cmd(flash, offset, flash->command);
 
-   spi_write(flash->spi, flash->command, CMD_SIZE);
+   spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
 
return 0;
 }
@@ -311,7 +321,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, 
size_t len,
 * Should add 1 byte DUMMY_BYTE.
 */
t[0].tx_buf = flash->command;
-   t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
+   t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
spi_message_add_tail(&t[0], &m);
 
t[1].rx_buf = buf;
@@ -338,13 +348,11 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, 
size_t len,
 
/* Set up the write data buffer. */
flash->command[0] = OPCODE_READ;
-   flash->command[1] = from >> 16;
-   flash->command[2] = from >> 8;
-   flash->command[3] = from;
+   m25p_addr2cmd(flash, from, flash->command);
 
spi_sync(flash->spi, &m);
 
-   *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
+   *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
 
mutex_unlock(&flash->lock);
 
@@ -382,7 +390,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, 
size_t len,
memset(t, 0, (sizeof t));
 
t[0].tx_buf = flash->command;
-   t[0].len = CMD_SIZE;
+   t[0].len = m25p_cmdsz(flash);
spi_message_add_tail(&t[0], &m);
 
t[1].tx_buf = buf;
@@ -400,41 +408,36 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, 
size_t len,
 
/* Set up the opcode in the write buffer. */
flash->command[0] = OPCODE_PP;
-   flash->command[1] = to >> 16;
-   flash->command[2] = to >> 8;
-   flash->command[3] = to;
+   m25p_addr2cmd(flash, to, flash->command);
 
-   /* what page do we start with? */
-   page_offset = to % FLASH_PAGESIZE;
+   page_offset =

[PATCH v2 0/8] spi_mpc8xxx: Add support for DMA transfers

2009-08-18 Thread Anton Vorontsov
Hi all,

In v2:

- Fix build issues in fsl_qe_udc;
- Some minor cosmetic changes in "Add support for QE DMA mode and
  CPM1/CPM2 chips" patch.


David/Greg, could you Ack drivers/usb/gadget/fsl_qe_udc.h's changes 
in "[PATCH 4/8] powerpc/qe&cpm: Implement static inline stubs for
non-QE/CPM builds", so we could merge that patch via powerpc tree?

Thanks!

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/8] powerpc/cpm: Remove SPI defines and spi structs

2009-08-18 Thread Anton Vorontsov
When cpm2.h included into spi_mpc8xxx driver, the SPI defines
in the header conflict with defines in the driver.

We don't need them in the header file, so remove them. Plus
remove "struct spi", we'll use a better version in the driver.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/cpm1.h |   45 ---
 arch/powerpc/include/asm/cpm2.h |   39 -
 2 files changed, 0 insertions(+), 84 deletions(-)

diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h
index 7685ffd..81b0119 100644
--- a/arch/powerpc/include/asm/cpm1.h
+++ b/arch/powerpc/include/asm/cpm1.h
@@ -478,51 +478,6 @@ typedef struct iic {
charres2[2];/* Reserved */
 } iic_t;
 
-/* SPI parameter RAM.
-*/
-typedef struct spi {
-   ushort  spi_rbase;  /* Rx Buffer descriptor base address */
-   ushort  spi_tbase;  /* Tx Buffer descriptor base address */
-   u_char  spi_rfcr;   /* Rx function code */
-   u_char  spi_tfcr;   /* Tx function code */
-   ushort  spi_mrblr;  /* Max receive buffer length */
-   uintspi_rstate; /* Internal */
-   uintspi_rdp;/* Internal */
-   ushort  spi_rbptr;  /* Internal */
-   ushort  spi_rbc;/* Internal */
-   uintspi_rxtmp;  /* Internal */
-   uintspi_tstate; /* Internal */
-   uintspi_tdp;/* Internal */
-   ushort  spi_tbptr;  /* Internal */
-   ushort  spi_tbc;/* Internal */
-   uintspi_txtmp;  /* Internal */
-   uintspi_res;
-   ushort  spi_rpbase; /* Relocation pointer */
-   ushort  spi_res2;
-} spi_t;
-
-/* SPI Mode register.
-*/
-#define SPMODE_LOOP((ushort)0x4000)/* Loopback */
-#define SPMODE_CI  ((ushort)0x2000)/* Clock Invert */
-#define SPMODE_CP  ((ushort)0x1000)/* Clock Phase */
-#define SPMODE_DIV16   ((ushort)0x0800)/* BRG/16 mode */
-#define SPMODE_REV ((ushort)0x0400)/* Reversed Data */
-#define SPMODE_MSTR((ushort)0x0200)/* SPI Master */
-#define SPMODE_EN  ((ushort)0x0100)/* Enable */
-#define SPMODE_LENMSK  ((ushort)0x00f0)/* character length */
-#define SPMODE_LEN4((ushort)0x0030)/*  4 bits per char */
-#define SPMODE_LEN8((ushort)0x0070)/*  8 bits per char */
-#define SPMODE_LEN16   ((ushort)0x00f0)/* 16 bits per char */
-#define SPMODE_PMMSK   ((ushort)0x000f)/* prescale modulus */
-
-/* SPIE fields */
-#define SPIE_MME   0x20
-#define SPIE_TXE   0x10
-#define SPIE_BSY   0x04
-#define SPIE_TXB   0x02
-#define SPIE_RXB   0x01
-
 /*
  * RISC Controller Configuration Register definitons
  */
diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h
index 990ff19..236cfa3 100644
--- a/arch/powerpc/include/asm/cpm2.h
+++ b/arch/powerpc/include/asm/cpm2.h
@@ -654,45 +654,6 @@ typedef struct iic {
uintiic_txtmp;  /* Internal */
 } iic_t;
 
-/* SPI parameter RAM.
-*/
-typedef struct spi {
-   ushort  spi_rbase;  /* Rx Buffer descriptor base address */
-   ushort  spi_tbase;  /* Tx Buffer descriptor base address */
-   u_char  spi_rfcr;   /* Rx function code */
-   u_char  spi_tfcr;   /* Tx function code */
-   ushort  spi_mrblr;  /* Max receive buffer length */
-   uintspi_rstate; /* Internal */
-   uintspi_rdp;/* Internal */
-   ushort  spi_rbptr;  /* Internal */
-   ushort  spi_rbc;/* Internal */
-   uintspi_rxtmp;  /* Internal */
-   uintspi_tstate; /* Internal */
-   uintspi_tdp;/* Internal */
-   ushort  spi_tbptr;  /* Internal */
-   ushort  spi_tbc;/* Internal */
-   uintspi_txtmp;  /* Internal */
-   uintspi_res;/* Tx temp. */
-   uintspi_res1[4];/* SDMA temp. */
-} spi_t;
-
-/* SPI Mode register.
-*/
-#define SPMODE_LOOP((ushort)0x4000)/* Loopback */
-#define SPMODE_CI  ((ushort)0x2000)/* Clock Invert */
-#define SPMODE_CP  ((ushort)0x1000)/* Clock Phase */
-#define SPMODE_DIV16   ((ushort)0x0800)/* BRG/16 mode */
-#define SPMODE_REV ((ushort)0x0400)/* Reversed Data */
-#define SPMODE_MSTR((ushort)0x0200)/* SPI Master */
-#define SPMODE_EN  ((ushort)0x0100)/* Enable */
-#define SPMODE_LENMSK  ((ushort)0x00f0)/* character length */
-#define SPMODE_PMMSK   ((ushort)0x000f)/* prescale modulus */
-
-#define SPMODE_LEN(x)  x)-1)&0xF)<<4)
-#define SPMODE_PM(x)   ((x) &0xF)
-
-#define SPI_EB ((u_char)0x10)  /* big endian byte order */
-
 /* IDMA parameter RAM
 */
 typedef struct idma {
-- 
1.6.3.3

___
Linuxppc-dev mailing list
L

[PATCH 2/8] powerpc/qe&cpm2: Avoid redefinitions in CPM2 and QE headers

2009-08-18 Thread Anton Vorontsov
struct mcc defined in both immap_qe.h and immap_cpm2.h, so they will
conflic when included in a single file. The mcc struct is easy to deal
with, since it isn't used in any driver (yet), so let's just rename QE
version to qe_mcc.

The ucb_ctlr is a bit trickier, since it is used by fsl_qe_udc driver,
and the driver supports both CPM and QE UDCs, plus the QE version is
used to form a bigger immap struct.

I don't want to touch too much of USB code in this series, so for now
let's just copy most generic version into the common cpm.h header,
later we'll create cpm_usb.h where we'll place common USB structs that
are used by QE/CPM UDC and QE Host drivers (FHCI).

And as for the structs in qe.h and cpm2.h, just prefix them with qe_
and cpm_.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/cpm.h|   22 ++
 arch/powerpc/include/asm/immap_cpm2.h |2 +-
 arch/powerpc/include/asm/immap_qe.h   |8 
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h
index 24d79e3..b5f1534 100644
--- a/arch/powerpc/include/asm/cpm.h
+++ b/arch/powerpc/include/asm/cpm.h
@@ -5,6 +5,28 @@
 #include 
 #include 
 
+/*
+ * USB Controller pram common to QE and CPM.
+ */
+struct usb_ctlr {
+   u8  usb_usmod;
+   u8  usb_usadr;
+   u8  usb_uscom;
+   u8  res1[1];
+   __be16  usb_usep[4];
+   u8  res2[4];
+   __be16  usb_usber;
+   u8  res3[2];
+   __be16  usb_usbmr;
+   u8  res4[1];
+   u8  usb_usbs;
+   /* Fields down below are QE-only */
+   __be16  usb_ussft;
+   u8  res5[2];
+   __be16  usb_usfrn;
+   u8  res6[0x22];
+} __attribute__ ((packed));
+
 /* Opcodes common to CPM1 and CPM2
 */
 #define CPM_CR_INIT_TRX((ushort)0x)
diff --git a/arch/powerpc/include/asm/immap_cpm2.h 
b/arch/powerpc/include/asm/immap_cpm2.h
index d4f069b..7c64fda 100644
--- a/arch/powerpc/include/asm/immap_cpm2.h
+++ b/arch/powerpc/include/asm/immap_cpm2.h
@@ -549,7 +549,7 @@ typedef struct comm_proc {
 
 /* USB Controller.
 */
-typedef struct usb_ctlr {
+typedef struct cpm_usb_ctlr {
u8  usb_usmod;
u8  usb_usadr;
u8  usb_uscom;
diff --git a/arch/powerpc/include/asm/immap_qe.h 
b/arch/powerpc/include/asm/immap_qe.h
index c346d0b..4e10f50 100644
--- a/arch/powerpc/include/asm/immap_qe.h
+++ b/arch/powerpc/include/asm/immap_qe.h
@@ -210,7 +210,7 @@ struct sir {
 } __attribute__ ((packed));
 
 /* USB Controller */
-struct usb_ctlr {
+struct qe_usb_ctlr {
u8  usb_usmod;
u8  usb_usadr;
u8  usb_uscom;
@@ -229,7 +229,7 @@ struct usb_ctlr {
 } __attribute__ ((packed));
 
 /* MCC */
-struct mcc {
+struct qe_mcc {
__be32  mcce;   /* MCC event register */
__be32  mccm;   /* MCC mask register */
__be32  mccf;   /* MCC configuration register */
@@ -431,9 +431,9 @@ struct qe_immap {
struct qe_mux   qmx;/* QE Multiplexer */
struct qe_timersqet;/* QE Timers */
struct spi  spi[0x2];   /* spi */
-   struct mcc  mcc;/* mcc */
+   struct qe_mcc   mcc;/* mcc */
struct qe_brg   brg;/* brg */
-   struct usb_ctlr usb;/* USB */
+   struct qe_usb_ctlr  usb;/* USB */
struct si1  si1;/* SI */
u8  res11[0x800];
struct sir  sir;/* SI Routing Tables */
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/8] powerpc/cpm: Move CPMFCR_* defines into cpm.h

2009-08-18 Thread Anton Vorontsov
The bits are generic to CPM devices, so let's move them to the
common header file, so drivers won't need to privately reintroduce
another bunch of the same bits (as we can't include cpm2.h header
together with cpm1.h).

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/cpm.h  |   16 
 arch/powerpc/include/asm/cpm2.h |8 
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h
index b5f1534..ea3fdb9 100644
--- a/arch/powerpc/include/asm/cpm.h
+++ b/arch/powerpc/include/asm/cpm.h
@@ -27,6 +27,22 @@ struct usb_ctlr {
u8  res6[0x22];
 } __attribute__ ((packed));
 
+/*
+ * Function code bits, usually generic to devices.
+ */
+#ifdef CONFIG_CPM1
+#define CPMFCR_GBL ((u_char)0x00)  /* Flag doesn't exist in CPM1 */
+#define CPMFCR_TC2 ((u_char)0x00)  /* Flag doesn't exist in CPM1 */
+#define CPMFCR_DTB ((u_char)0x00)  /* Flag doesn't exist in CPM1 */
+#define CPMFCR_BDB ((u_char)0x00)  /* Flag doesn't exist in CPM1 */
+#else
+#define CPMFCR_GBL ((u_char)0x20)  /* Set memory snooping */
+#define CPMFCR_TC2 ((u_char)0x04)  /* Transfer code 2 value */
+#define CPMFCR_DTB ((u_char)0x02)  /* Use local bus for data when set */
+#define CPMFCR_BDB ((u_char)0x01)  /* Use local bus for BD when set */
+#endif
+#define CPMFCR_EB  ((u_char)0x10)  /* Set big endian byte order */
+
 /* Opcodes common to CPM1 and CPM2
 */
 #define CPM_CR_INIT_TRX((ushort)0x)
diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h
index 236cfa3..f42e9ba 100644
--- a/arch/powerpc/include/asm/cpm2.h
+++ b/arch/powerpc/include/asm/cpm2.h
@@ -124,14 +124,6 @@ static inline void cpm2_fastbrg(uint brg, uint rate, int 
div16)
__cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT);
 }
 
-/* Function code bits, usually generic to devices.
-*/
-#define CPMFCR_GBL ((u_char)0x20)  /* Set memory snooping */
-#define CPMFCR_EB  ((u_char)0x10)  /* Set big endian byte order */
-#define CPMFCR_TC2 ((u_char)0x04)  /* Transfer code 2 value */
-#define CPMFCR_DTB ((u_char)0x02)  /* Use local bus for data when set */
-#define CPMFCR_BDB ((u_char)0x01)  /* Use local bus for BD when set */
-
 /* Parameter RAM offsets from the base.
 */
 #define PROFF_SCC1 ((uint)0x8000)
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 4/8] powerpc/qe&cpm: Implement static inline stubs for non-QE/CPM builds

2009-08-18 Thread Anton Vorontsov
This is needed to avoid ugly #ifdefs in drivers. Also update fsl_qe_udc
driver so that now it doesn't define its own versions that cause build
breakage when the generic stubs are used.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/cpm.h  |   44 +++
 arch/powerpc/include/asm/qe.h   |   11 -
 drivers/usb/gadget/fsl_qe_udc.h |   15 -
 3 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h
index ea3fdb9..0835eb9 100644
--- a/arch/powerpc/include/asm/cpm.h
+++ b/arch/powerpc/include/asm/cpm.h
@@ -3,6 +3,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 /*
@@ -131,13 +132,56 @@ typedef struct cpm_buf_desc {
 #define BD_I2C_START   (0x0400)
 
 int cpm_muram_init(void);
+
+#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
 unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
 int cpm_muram_free(unsigned long offset);
 unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
 void __iomem *cpm_muram_addr(unsigned long offset);
 unsigned long cpm_muram_offset(void __iomem *addr);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
+#else
+static inline unsigned long cpm_muram_alloc(unsigned long size,
+   unsigned long align)
+{
+   return -ENOSYS;
+}
+
+static inline int cpm_muram_free(unsigned long offset)
+{
+   return -ENOSYS;
+}
+
+static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset,
+ unsigned long size)
+{
+   return -ENOSYS;
+}
+
+static inline void __iomem *cpm_muram_addr(unsigned long offset)
+{
+   return NULL;
+}
+
+static inline unsigned long cpm_muram_offset(void __iomem *addr)
+{
+   return -ENOSYS;
+}
+
+static inline dma_addr_t cpm_muram_dma(void __iomem *addr)
+{
+   return 0;
+}
+#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */
+
+#ifdef CONFIG_CPM
 int cpm_command(u32 command, u8 opcode);
+#else
+static inline int cpm_command(u32 command, u8 opcode)
+{
+   return -ENOSYS;
+}
+#endif /* CONFIG_CPM */
 
 int cpm2_gpiochip_add32(struct device_node *np);
 
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 157c5ca..791c67a 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -145,8 +145,17 @@ static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) 
{}
 static inline void qe_pin_set_dedicated(struct qe_pin *pin) {}
 #endif /* CONFIG_QE_GPIO */
 
-/* QE internal API */
+#ifdef CONFIG_QUICC_ENGINE
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
+#else
+static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
+  u32 cmd_input)
+{
+   return -ENOSYS;
+}
+#endif /* CONFIG_QUICC_ENGINE */
+
+/* QE internal API */
 enum qe_clock qe_clock_source(const char *source);
 unsigned int qe_get_brg_clk(void);
 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
index 31b2710..bea5b82 100644
--- a/drivers/usb/gadget/fsl_qe_udc.h
+++ b/drivers/usb/gadget/fsl_qe_udc.h
@@ -419,19 +419,4 @@ struct qe_udc {
 #define CPM_USB_RESTART_TX_OPCODE 0x0b
 #define CPM_USB_EP_SHIFT 5
 
-#ifndef CONFIG_CPM
-inline int cpm_command(u32 command, u8 opcode)
-{
-   return -EOPNOTSUPP;
-}
-#endif
-
-#ifndef CONFIG_QUICC_ENGINE
-inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
-   u32 cmd_input)
-{
-   return -EOPNOTSUPP;
-}
-#endif
-
 #endif  /* __FSL_QE_UDC_H */
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 5/8] spi_mpc8xxx: Fix uninitialized variable

2009-08-18 Thread Anton Vorontsov
This patch fixes the following warning:

CC  drivers/spi/spi_mpc8xxx.o
  spi_mpc8xxx.c: In function 'of_mpc8xxx_spi_probe':
  spi_mpc8xxx.c:681: warning: 'ret' may be used uninitialized in this function

Signed-off-by: Anton Vorontsov 
---
 drivers/spi/spi_mpc8xxx.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index 0fd0ec4..518671b 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -709,6 +709,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device 
*dev)
gpio = of_get_gpio_flags(np, i, &flags);
if (!gpio_is_valid(gpio)) {
dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+   ret = gpio;
goto err_loop;
}
 
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 6/8] spi_mpc8xxx: Factor out SPI mode change steps into a call

2009-08-18 Thread Anton Vorontsov
We'll add more steps soon, so get rid of the duplication.

Signed-off-by: Anton Vorontsov 
---
 drivers/spi/spi_mpc8xxx.c |   56 +++-
 1 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index 518671b..4b119ea 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -155,6 +155,26 @@ MPC83XX_SPI_TX_BUF(u8)
 MPC83XX_SPI_TX_BUF(u16)
 MPC83XX_SPI_TX_BUF(u32)
 
+static void mpc8xxx_spi_change_mode(struct spi_device *spi)
+{
+   struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+   struct spi_mpc8xxx_cs *cs = spi->controller_state;
+   __be32 __iomem *mode = &mspi->base->mode;
+   unsigned long flags;
+
+   if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
+   return;
+
+   /* Turn off IRQs locally to minimize time that SPI is disabled. */
+   local_irq_save(flags);
+
+   /* Turn off SPI unit prior changing mode */
+   mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
+   mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+
+   local_irq_restore(flags);
+}
+
 static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
 {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -168,27 +188,13 @@ static void mpc8xxx_spi_chipselect(struct spi_device 
*spi, int value)
}
 
if (value == BITBANG_CS_ACTIVE) {
-   u32 regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
-
mpc8xxx_spi->rx_shift = cs->rx_shift;
mpc8xxx_spi->tx_shift = cs->tx_shift;
mpc8xxx_spi->get_rx = cs->get_rx;
mpc8xxx_spi->get_tx = cs->get_tx;
 
-   if (cs->hw_mode != regval) {
-   unsigned long flags;
-   __be32 __iomem *mode = &mpc8xxx_spi->base->mode;
-
-   regval = cs->hw_mode;
-   /* Turn off IRQs locally to minimize time that
-* SPI is disabled
-*/
-   local_irq_save(flags);
-   /* Turn off SPI unit prior changing mode */
-   mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE);
-   mpc8xxx_spi_write_reg(mode, regval);
-   local_irq_restore(flags);
-   }
+   mpc8xxx_spi_change_mode(spi);
+
if (pdata->cs_control)
pdata->cs_control(spi, pol);
}
@@ -198,7 +204,6 @@ static
 int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 {
struct mpc8xxx_spi *mpc8xxx_spi;
-   u32 regval;
u8 bits_per_word, pm;
u32 hz;
struct spi_mpc8xxx_cs   *cs = spi->controller_state;
@@ -286,21 +291,8 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, 
struct spi_transfer *t)
pm--;
 
cs->hw_mode |= SPMODE_PM(pm);
-   regval =  mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
-   if (cs->hw_mode != regval) {
-   unsigned long flags;
-   __be32 __iomem *mode = &mpc8xxx_spi->base->mode;
-
-   regval = cs->hw_mode;
-   /* Turn off IRQs locally to minimize time
-* that SPI is disabled
-*/
-   local_irq_save(flags);
-   /* Turn off SPI unit prior changing mode */
-   mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE);
-   mpc8xxx_spi_write_reg(mode, regval);
-   local_irq_restore(flags);
-   }
+
+   mpc8xxx_spi_change_mode(spi);
return 0;
 }
 
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 7/8] spi_mpc8xxx: Turn qe_mode into flags

2009-08-18 Thread Anton Vorontsov
Soon there will be more flags introduced in subsequent patches, so
let's turn qe_mode into flags.

Also introduce mpc8xxx_spi_strmode() and print current SPI mode.

Signed-off-by: Anton Vorontsov 
---
 drivers/spi/spi_mpc8xxx.c   |   30 +++---
 include/linux/fsl_devices.h |2 +-
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index 4b119ea..80374df 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -96,7 +96,8 @@ struct mpc8xxx_spi {
u32 rx_shift;   /* RX data reg shift when in qe mode */
u32 tx_shift;   /* TX data reg shift when in qe mode */
 
-   bool qe_mode;
+   unsigned int flags;
+#define SPI_QE_CPU_MODE(1 << 0) /* QE CPU ("PIO") mode */
 
struct workqueue_struct *workqueue;
struct work_struct work;
@@ -235,14 +236,14 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, 
struct spi_transfer *t)
if (bits_per_word <= 8) {
cs->get_rx = mpc8xxx_spi_rx_buf_u8;
cs->get_tx = mpc8xxx_spi_tx_buf_u8;
-   if (mpc8xxx_spi->qe_mode) {
+   if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
cs->rx_shift = 16;
cs->tx_shift = 24;
}
} else if (bits_per_word <= 16) {
cs->get_rx = mpc8xxx_spi_rx_buf_u16;
cs->get_tx = mpc8xxx_spi_tx_buf_u16;
-   if (mpc8xxx_spi->qe_mode) {
+   if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
cs->rx_shift = 16;
cs->tx_shift = 16;
}
@@ -252,7 +253,8 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, 
struct spi_transfer *t)
} else
return -EINVAL;
 
-   if (mpc8xxx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) {
+   if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
+   spi->mode & SPI_LSB_FIRST) {
cs->tx_shift = 0;
if (bits_per_word <= 8)
cs->rx_shift = 8;
@@ -518,6 +520,13 @@ static void mpc8xxx_spi_cleanup(struct spi_device *spi)
kfree(spi->controller_state);
 }
 
+static const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+   if (flags & SPI_QE_CPU_MODE)
+   return "QE CPU";
+   return "CPU";
+}
+
 static struct spi_master * __devinit
 mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
 {
@@ -544,14 +553,14 @@ mpc8xxx_spi_probe(struct device *dev, struct resource 
*mem, unsigned int irq)
master->cleanup = mpc8xxx_spi_cleanup;
 
mpc8xxx_spi = spi_master_get_devdata(master);
-   mpc8xxx_spi->qe_mode = pdata->qe_mode;
mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+   mpc8xxx_spi->flags = pdata->flags;
mpc8xxx_spi->spibrg = pdata->sysclk;
 
mpc8xxx_spi->rx_shift = 0;
mpc8xxx_spi->tx_shift = 0;
-   if (mpc8xxx_spi->qe_mode) {
+   if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16;
mpc8xxx_spi->tx_shift = 24;
}
@@ -584,7 +593,7 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, 
unsigned int irq)
 
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-   if (pdata->qe_mode)
+   if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
regval |= SPMODE_OP;
 
mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
@@ -604,9 +613,8 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, 
unsigned int irq)
if (ret < 0)
goto unreg_master;
 
-   printk(KERN_INFO
-  "%s: MPC8xxx SPI Controller driver at 0x%p (irq = %d)\n",
-  dev_name(dev), mpc8xxx_spi->base, mpc8xxx_spi->irq);
+   dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
+mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
 
return master;
 
@@ -797,7 +805,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct of_device 
*ofdev,
 
prop = of_get_property(np, "mode", NULL);
if (prop && !strcmp(prop, "cpu-qe"))
-   pdata->qe_mode = 1;
+   pdata->flags = SPI_QE_CPU_MODE;
 
ret = of_mpc8xxx_spi_get_chipselects(dev);
if (ret)
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 43fc95d..39fd946 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -74,7 +74,7 @@ struct spi_device;
 struct fsl_

[PATCH 8/8] spi_mpc8xxx: Add support for QE DMA mode and CPM1/CPM2 chips

2009-08-18 Thread Anton Vorontsov
This patch adds QE buffer descriptors mode support for the
spi_mpc8xxx driver, and as a side effect we now support CPM1
and CPM2 SPI controllers.

That means that today we support almost all MPC SPI controllers:

- MPC834x-style controllers (support PIO mode only);
- CPM1 and CPM2 controllers (support DMA mode only);
- QE SPI controllers in CPU mode (PIO mode with shift quirks);
- QE SPI controllers in buffer descriptors (DMA) mode;

The only controller we don't currently support is a newer eSPI
(with a dedicated chip selects and a bit different registers map).

Signed-off-by: Anton Vorontsov 
---
 drivers/spi/Kconfig   |3 -
 drivers/spi/spi_mpc8xxx.c |  540 +
 2 files changed, 500 insertions(+), 43 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2c733c2..b22a4b4 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -146,9 +146,6 @@ config SPI_MPC8xxx
  This enables using the Freescale MPC8xxx SPI controllers in master
  mode.
 
- This driver uses a simple set of shift registers for data (opposed
- to the CPM based descriptor model).
-
 config SPI_OMAP_UWIRE
tristate "OMAP1 MicroWire"
depends on ARCH_OMAP1
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index 80374df..394b658 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -5,6 +5,10 @@
  *
  * Copyright (C) 2006 Polycom, Inc.
  *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov 
+ *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
@@ -27,6 +31,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -34,8 +41,19 @@
 #include 
 
 #include 
+#include 
+#include 
 #include 
 
+/* CPM1 and CPM2 are mutually exclusive. */
+#ifdef CONFIG_CPM1
+#include 
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
+#else
+#include 
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
+#endif
+
 /* SPI Controller registers */
 struct mpc8xxx_spi_reg {
u8 res1[0x20];
@@ -47,6 +65,28 @@ struct mpc8xxx_spi_reg {
__be32 receive;
 };
 
+/* SPI Parameter RAM */
+struct spi_pram {
+   __be16  rbase;  /* Rx Buffer descriptor base address */
+   __be16  tbase;  /* Tx Buffer descriptor base address */
+   u8  rfcr;   /* Rx function code */
+   u8  tfcr;   /* Tx function code */
+   __be16  mrblr;  /* Max receive buffer length */
+   __be32  rstate; /* Internal */
+   __be32  rdp;/* Internal */
+   __be16  rbptr;  /* Internal */
+   __be16  rbc;/* Internal */
+   __be32  rxtmp;  /* Internal */
+   __be32  tstate; /* Internal */
+   __be32  tdp;/* Internal */
+   __be16  tbptr;  /* Internal */
+   __be16  tbc;/* Internal */
+   __be32  txtmp;  /* Internal */
+   __be32  res;/* Tx temp. */
+   __be16  rpbase; /* Relocation pointer (CPM1 only) */
+   __be16  res1;   /* Reserved */
+};
+
 /* SPI Controller mode register definitions */
 #defineSPMODE_LOOP (1 << 30)
 #defineSPMODE_CI_INACTIVEHIGH  (1 << 29)
@@ -75,14 +115,40 @@ struct mpc8xxx_spi_reg {
 #defineSPIM_NE 0x0200  /* Not empty */
 #defineSPIM_NF 0x0100  /* Not full */
 
+#defineSPIE_TXB0x0200  /* Last char is written to tx 
fifo */
+#defineSPIE_RXB0x0100  /* Last char is written to rx 
buf */
+
+/* SPCOM register values */
+#defineSPCOM_STR   (1 << 23)   /* Start transmit */
+
+#defineSPI_PRAM_SIZE   0x100
+#defineSPI_MRBLR   ((unsigned int)PAGE_SIZE)
+
 /* SPI Controller driver's private data. */
 struct mpc8xxx_spi {
+   struct device *dev;
struct mpc8xxx_spi_reg __iomem *base;
 
/* rx & tx bufs from the spi_transfer */
const void *tx;
void *rx;
 
+   int subblock;
+   struct spi_pram __iomem *pram;
+   struct cpm_buf_desc __iomem *tx_bd;
+   struct cpm_buf_desc __iomem *rx_bd;
+
+   struct spi_transfer *xfer_in_progress;
+
+   /* dma addresses for CPM transfers */
+   dma_addr_t tx_dma;
+   dma_addr_t rx_dma;
+   bool map_tx_dma;
+   bool map_rx_dma;
+
+   dma_addr_t dma_dummy_tx;
+   dma_addr_t dma_dummy_rx;
+
/* functions to deal with different sized buffers */
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
u32(*get_tx) (struct mpc8xxx_spi *);
@@ -98,6 +164,10 @@ struct mpc8xxx_spi {
 
unsigned int flags;
 #define SPI_QE_CPU_MODE(1 << 0) /* QE CPU ("PIO") 

[PATCH] USB: fsl_qe_udc: Add fsl,mpc8323-qe-usb compatible entry

2009-08-18 Thread Anton Vorontsov
Current bindings specify that "fsl,mpc8323-qe-usb" compatible entry
should be used as a base match for QE UDCs, so update the driver to
comply with the bindings.

Signed-off-by: Anton Vorontsov 
---

On Thu, Apr 02, 2009 at 02:17:11PM -0500, Scott Wood wrote:
> Anton Vorontsov wrote:
> >On Thu, Apr 02, 2009 at 01:42:37PM -0500, Timur Tabi wrote:
> >>Anton Vorontsov wrote:
> >>
> >>>Oh, I was wrong. fsl_qe_udc driver uses mpc8360 compatible for
> >>>matching, so you can't remove it. :-/
> >>Ugh, that's a bug in the driver then.
> >
> >Yes, but that depends on what chip was the first one? MPC8323 or
> >MPC8360?
> 
> Actually, it depends on which one we picked in the devtree binding
> (assuming they're compatible both ways), which appears to be
> mpc8323.

A bit delayed, but here is a patch to fix the issue.

 drivers/usb/gadget/fsl_qe_udc.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index d701bf4..7881f12 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2751,6 +2751,10 @@ static int __devexit qe_udc_remove(struct of_device 
*ofdev)
 /*-*/
 static struct of_device_id __devinitdata qe_udc_match[] = {
{
+   .compatible = "fsl,mpc8323-qe-usb",
+   .data = (void *)PORT_QE,
+   },
+   {
.compatible = "fsl,mpc8360-qe-usb",
.data = (void *)PORT_QE,
},
-- 
1.6.3.3
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] qe_lib: Set gpio data before changing the direction to output

2009-08-18 Thread Anton Vorontsov
On Tue, Aug 18, 2009 at 05:33:00PM -0500, Timur Tabi wrote:
> Anton Vorontsov wrote:
> > On Tue, Aug 18, 2009 at 05:20:44PM -0400, Michael Barkowski wrote:
> >> This avoids having a short glitch if the desired initial value is not
> >> the same as what was previously in the data register.
> >>
> >> Signed-off-by: Michael Barkowski 
> > 
> > Acked-by: Anton Vorontsov 
> 
> I don't have the time to test this patch, so I abstain from acking. :-)
> If Anton likes it, that's good enough for me.

You made me doubt for a moment. :-) Thanks for the suspiciousness.

What happens if a pin was previously configured as input? Does our
write to the data register survive? For MPC8xxx GPIO controllers
it does. And randomly taken QE spec says:

  A write to CPDAT is latched, and if the corresponding CPDIR
  bits have configured the port pin as an output, the latched
  value is driven onto the respective pin. However, if the
  corresponding CPDIR bits have configured the port pin as an
  input, the latched value is prevented from reaching the pin.

I guess we're safe, but Michael, could you actually test it
(if not already)?

Thanks!

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/3] powerpc/82xx: Fix BCSR bits for MPC8272ADS boards

2009-08-18 Thread Anton Vorontsov
mpc8272_ads.c is using BCSR bits definitions from pq2ads.h, but
according to User's Guide the bits are wrong for MPC8272ADS boards
(I guess definitions from pq2ads should only be used for PQ2FADS
boards).

So, let's introduce our own definitions for MPC8272ADS, and don't
include pq2ads.h.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/platforms/82xx/mpc8272_ads.c |8 +++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c 
b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 8054c68..67e2184 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -29,7 +29,6 @@
 #include 
 #include 
 
-#include "pq2ads.h"
 #include "pq2.h"
 
 static void __init mpc8272_ads_pic_init(void)
@@ -144,6 +143,13 @@ static void __init mpc8272_ads_setup_arch(void)
return;
}
 
+#define BCSR1_FETHIEN  0x0800
+#define BCSR1_FETH_RST 0x0400
+#define BCSR1_RS232_EN10x0200
+#define BCSR1_RS232_EN20x0100
+#define BCSR3_FETHIEN2 0x1000
+#define BCSR3_FETH2_RST0x0800
+
clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
setbits32(&bcsr[1], BCSR1_FETH_RST);
 
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/3] powerpc/82xx: Add CPM USB Gadget support for MPC8272ADS boards

2009-08-18 Thread Anton Vorontsov
- Add usb node;
- Configure pins and clocks;
- Enable USB function in BCSR.

The support was successfully tested using serial and ethernet gadget
drivers.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/boot/dts/mpc8272ads.dts  |8 
 arch/powerpc/platforms/82xx/mpc8272_ads.c |   14 ++
 2 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts 
b/arch/powerpc/boot/dts/mpc8272ads.dts
index 60f3327..e802ebd 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -173,6 +173,14 @@
fsl,cpm-command = <0xce0>;
};
 
+   u...@11b60 {
+   compatible = "fsl,mpc8272-cpm-usb";
+   reg = <0x11b60 0x40 0x8b00 0x100>;
+   interrupts = <11 8>;
+   interrupt-parent = <&PIC>;
+   mode = "peripheral";
+   };
+
m...@10d40 {
device_type = "mdio";
compatible = "fsl,mpc8272ads-mdio-bitbang",
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c 
b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 67e2184..30394b4 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -99,6 +99,15 @@ static struct cpm_pin mpc8272_ads_pins[] = {
/* I2C */
{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
+
+   /* USB */
+   {2, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+   {2, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+   {2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+   {2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+   {3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+   {3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+   {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
 };
 
 static void __init init_ioports(void)
@@ -112,6 +121,8 @@ static void __init init_ioports(void)
 
cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
+   cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK8, CPM_CLK_RX);
+   cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK8, CPM_CLK_TX);
cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_RX);
cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_TX);
cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK11, CPM_CLK_RX);
@@ -147,6 +158,7 @@ static void __init mpc8272_ads_setup_arch(void)
 #define BCSR1_FETH_RST 0x0400
 #define BCSR1_RS232_EN10x0200
 #define BCSR1_RS232_EN20x0100
+#define BCSR3_USB_nEN  0x8000
 #define BCSR3_FETHIEN2 0x1000
 #define BCSR3_FETH2_RST0x0800
 
@@ -156,6 +168,8 @@ static void __init mpc8272_ads_setup_arch(void)
clrbits32(&bcsr[3], BCSR3_FETHIEN2);
setbits32(&bcsr[3], BCSR3_FETH2_RST);
 
+   clrbits32(&bcsr[3], BCSR3_USB_nEN);
+
iounmap(bcsr);
 
init_ioports();
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/3] powerpc/85xx: Add QE USB support for MPC8569E-MDS boards

2009-08-18 Thread Anton Vorontsov
- Add gpio-controller node for BCSR17, it is used to control USB
  speed and VBUS;
- Add timer node for QE GTM, needed for USB host;
- Add usb node itself;
- Add some probing code for BCSR GPIOs.

NOTE: QE USB doesn't work on prototype boards, but should work on
  pilot boards if specs and schematics are correct, though we
  don't have the pilot boards to actually test it.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/boot/dts/mpc8569mds.dts  |   45 +
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |4 ++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts 
b/arch/powerpc/boot/dts/mpc8569mds.dts
index a680165..880f896 100644
--- a/arch/powerpc/boot/dts/mpc8569mds.dts
+++ b/arch/powerpc/boot/dts/mpc8569mds.dts
@@ -99,8 +99,18 @@
};
 
b...@1,0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
compatible = "fsl,mpc8569mds-bcsr";
reg = <1 0 0x8000>;
+   ranges = <0 1 0 0x8000>;
+
+   bcsr17: gpio-control...@11 {
+   #gpio-cells = <2>;
+   compatible = "fsl,mpc8569mds-bcsr-gpio";
+   reg = <0x11 0x1>;
+   gpio-controller;
+   };
};
 
n...@3,0 {
@@ -315,6 +325,14 @@
gpio-controller;
};
 
+   qe_pio_f: gpio-control...@a0 {
+   #gpio-cells = <2>;
+   compatible = "fsl,mpc8569-qe-pario-bank",
+"fsl,mpc8323-qe-pario-bank";
+   reg = <0xa0 0x18>;
+   gpio-controller;
+   };
+
pio1: ucc_...@01 {
pio-map = <
/* port  pin  dir  open_drain  assignment  has_irq */
@@ -419,6 +437,16 @@
interrupt-parent = <&mpic>;
};
 
+   ti...@440 {
+   compatible = "fsl,mpc8569-qe-gtm",
+"fsl,qe-gtm", "fsl,gtm";
+   reg = <0x440 0x40>;
+   interrupts = <12 13 14 15>;
+   interrupt-parent = <&qeic>;
+   /* Filled in by U-Boot */
+   clock-frequency = <0>;
+   };
+
s...@4c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -446,6 +474,23 @@
mode = "cpu";
};
 
+   u...@6c0 {
+   compatible = "fsl,mpc8569-qe-usb",
+"fsl,mpc8323-qe-usb";
+   reg = <0x6c0 0x40 0x8b00 0x100>;
+   interrupts = <11>;
+   interrupt-parent = <&qeic>;
+   fsl,fullspeed-clock = "clk5";
+   fsl,lowspeed-clock = "brg10";
+   gpios = <&qe_pio_f 3 0   /* USBOE */
+&qe_pio_f 4 0   /* USBTP */
+&qe_pio_f 5 0   /* USBTN */
+&qe_pio_f 6 0   /* USBRP */
+&qe_pio_f 8 0   /* USBRN */
+&bcsr17   6 0   /* SPEED */
+&bcsr17   5 1>; /* POWER */
+   };
+
enet0: u...@2000 {
device_type = "network";
compatible = "ucc_geth";
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c 
b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 60ed9c0..173d459 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -47,6 +47,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -291,6 +292,9 @@ static struct of_device_id mpc85xx_ids[] = {
 
 static int __init mpc85xx_publish_devices(void)
 {
+   if (machine_is(mpc8569_mds))
+   simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
+
/* Publish the QE devices */
of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
 
-- 
1.6.3.3
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2] powerpc/85xx: Add eSDHC support for MPC8536DS boards

2009-08-18 Thread Anton Vorontsov
This patch simply adds sdhci node to the device tree.

We specify clock-frequency manually, so that eSDHC will work without
upgrading U-Boot. Though, that'll only work for default setup (1500
MHz) on new board revisions. For non-default setups, it's recommended
to upgrade U-Boot, since it will fixup clock-frequency automatically.

Signed-off-by: Anton Vorontsov 
---

On Tue, Aug 11, 2009 at 08:48:32AM -0500, Kumar Gala wrote:
> On Aug 7, 2009, at 2:58 PM, Anton Vorontsov wrote:
> >This patch simply adds sdhci node to the device tree.
> >
> >We specify clock-frequency manually, so that eSDHC will work without
> >upgrading U-Boot. Though, that'll only work for default setup (1500
> >MHz) on new board revisions. For non-default setups, it's recommended
> >to upgrade U-Boot, since it will fixup clock-frequency automatically.
> >
> >Signed-off-by: Anton Vorontsov 
> >---
> >arch/powerpc/boot/dts/mpc8536ds.dts |8 
> >1 files changed, 8 insertions(+), 0 deletions(-)
> 
> Can you update the mpc8536ds_36b.dts as well (its in my next branch)

Sure thing.

 arch/powerpc/boot/dts/mpc8536ds.dts |8 
 arch/powerpc/boot/dts/mpc8536ds_36b.dts |8 
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts 
b/arch/powerpc/boot/dts/mpc8536ds.dts
index 22caf69..815cebb 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -250,6 +250,14 @@
phy_type = "ulpi";
};
 
+   sd...@2e000 {
+   compatible = "fsl,mpc8536-esdhc", "fsl,esdhc";
+   reg = <0x2e000 0x1000>;
+   interrupts = <72 0x2>;
+   interrupt-parent = <&mpic>;
+   clock-frequency = <25000>;
+   };
+
serial0: ser...@4500 {
cell-index = <0>;
device_type = "serial";
diff --git a/arch/powerpc/boot/dts/mpc8536ds_36b.dts 
b/arch/powerpc/boot/dts/mpc8536ds_36b.dts
index 113ed8b..d95b260 100644
--- a/arch/powerpc/boot/dts/mpc8536ds_36b.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds_36b.dts
@@ -250,6 +250,14 @@
phy_type = "ulpi";
};
 
+   sd...@2e000 {
+   compatible = "fsl,mpc8536-esdhc", "fsl,esdhc";
+   reg = <0x2e000 0x1000>;
+   interrupts = <72 0x2>;
+   interrupt-parent = <&mpic>;
+   clock-frequency = <25000>;
+   };
+
serial0: ser...@4500 {
cell-index = <0>;
device_type = "serial";
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 4/8] powerpc/qe&cpm: Implement static inline stubs for non-QE/CPM builds

2009-08-18 Thread Anton Vorontsov
On Tue, Aug 18, 2009 at 03:27:47PM -0700, Greg KH wrote:
> On Wed, Aug 19, 2009 at 02:04:18AM +0400, Anton Vorontsov wrote:
> > This is needed to avoid ugly #ifdefs in drivers. Also update fsl_qe_udc
> > driver so that now it doesn't define its own versions that cause build
> > breakage when the generic stubs are used.
> > 
> > Signed-off-by: Anton Vorontsov 
> 
> As you're just deleting code, I'll ack that :)
> 
>   Acked-by: Greg Kroah-Hartman 
> 
> Hopefully you have tested building this thing...

Yep, thanks!

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] powerpc/85xx: Add eSDHC support for MPC8536DS boards

2009-08-18 Thread Anton Vorontsov
On Tue, Aug 18, 2009 at 08:24:17PM -0500, Kumar Gala wrote:
> 
> On Aug 18, 2009, at 6:38 PM, Anton Vorontsov wrote:
> 
> >This patch simply adds sdhci node to the device tree.
> >
> >We specify clock-frequency manually, so that eSDHC will work without
> >upgrading U-Boot. Though, that'll only work for default setup (1500
> >MHz) on new board revisions. For non-default setups, it's recommended
> >to upgrade U-Boot, since it will fixup clock-frequency automatically.
> >
> >Signed-off-by: Anton Vorontsov 
> 
> out of interest the 85xx eSDHC don't need the sdhci,wp-inverted
> property?

Yes, eSDHC controllers in MPC85xx report normal state in its
registers.

But the funny thing is that the switch itself is inverted,
so to enable writing, on MPC8569E-MDS and MPC8536DS boards
we have to place card's write protect tab into "lock" position.

Unfortunately we can't fix that in software since controller
doesn't permit write operations if it detects write-protected
state. On the bright side, IIRC MPC8536DS revision history
says that WP line level is fixed via BCSR upgrade. Not sure
if it is possible to fix it for MPC8569E-MDS.

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] qe_lib: Set gpio data before changing the direction to output

2009-08-19 Thread Anton Vorontsov
On Wed, Aug 19, 2009 at 09:30:20AM -0400, Michael Barkowski wrote:
> Anton Vorontsov wrote:
> > On Tue, Aug 18, 2009 at 05:33:00PM -0500, Timur Tabi wrote:
> >> Anton Vorontsov wrote:
> >>> On Tue, Aug 18, 2009 at 05:20:44PM -0400, Michael Barkowski wrote:
> >>>> This avoids having a short glitch if the desired initial value is not
> >>>> the same as what was previously in the data register.
> >>>>
> >>>> Signed-off-by: Michael Barkowski 
> >>> Acked-by: Anton Vorontsov 
> >> I don't have the time to test this patch, so I abstain from acking. :-)
> >> If Anton likes it, that's good enough for me.
> > 
> > You made me doubt for a moment. :-) Thanks for the suspiciousness.
> > 
> > What happens if a pin was previously configured as input? Does our
> > write to the data register survive? For MPC8xxx GPIO controllers
> > it does. And randomly taken QE spec says:
> > 
> >   A write to CPDAT is latched, and if the corresponding CPDIR
> >   bits have configured the port pin as an output, the latched
> >   value is driven onto the respective pin. However, if the
> >   corresponding CPDIR bits have configured the port pin as an
> >   input, the latched value is prevented from reaching the pin.
> > 
> > I guess we're safe, but Michael, could you actually test it
> > (if not already)?
> > 
> 
> I had tested it before with the pin initially configured as "disabled".
> 
> I have now also tested it with the pin initially configured as "input".
> 
> The value written to CPDAT seems to survive and is driven onto the pin
> once CPDIR is changed to 1, just as noted in the spec.
> 
> Tested on 8360, by probing with a logic analyzer.

Great, thanks a lot! I think the patch is perfect.

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/5] powerpc/qe: Increase MAX_QE_RISC to 4

2009-08-27 Thread Anton Vorontsov
MPC8569 CPUs have four QE RISCs, so we need to increase MAX_QE_RISC
constant, otherwise qe_upload_firmware() fails at sanity checking.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/sysdev/qe_lib/qe.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 237e365..b06564f 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -336,7 +336,7 @@ static int qe_sdma_init(void)
 }
 
 /* The maximum number of RISCs we support */
-#define MAX_QE_RISC 2
+#define MAX_QE_RISC 4
 
 /* Firmware information stored here for qe_get_firmware_info() */
 static struct qe_firmware_info qe_firmware_info;
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/5] powerpc/qe: Add qe_upload_firmware() stub for non-QE builds

2009-08-27 Thread Anton Vorontsov
This is needed to avoid #ifdefs in MPC85xx suspend/resume code.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/qe.h |7 +++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 791c67a..e8232bb 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -218,8 +218,15 @@ struct qe_firmware_info {
u64 extended_modes; /* Extended modes */
 };
 
+#ifdef CONFIG_QUICC_ENGINE
 /* Upload a firmware to the QE */
 int qe_upload_firmware(const struct qe_firmware *firmware);
+#else
+static inline int qe_upload_firmware(const struct qe_firmware *firmware)
+{
+   return -ENOSYS;
+}
+#endif /* CONFIG_QUICC_ENGINE */
 
 /* Obtain information on the uploaded firmware */
 struct qe_firmware_info *qe_get_firmware_info(void);
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/5] powerpc/qe: Make qe_reset() code path safe for repeated invocation

2009-08-27 Thread Anton Vorontsov
For MPC8569 CPUs we'll need to reset QE after each suspend, so make
qe_reset() code path suitable for repeated invocation, that is:

- Don't initialize rheap structures if already initialized;
- Don't allocate muram for SDMA if already allocated, just reinitialize
  registers with previously allocated muram offset;

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/sysdev/cpm_common.c |3 +++
 arch/powerpc/sysdev/qe_lib/qe.c  |   10 ++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index e4b6d66..ddfca52 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -81,6 +81,9 @@ int __init cpm_muram_init(void)
int i = 0;
int ret = 0;
 
+   if (muram_pbase)
+   return 0;
+
spin_lock_init(&cpm_muram_lock);
/* initialize the info header */
rh_init(&cpm_muram_info, 1,
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index b06564f..f485d5a 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -317,16 +317,18 @@ EXPORT_SYMBOL(qe_put_snum);
 static int qe_sdma_init(void)
 {
struct sdma __iomem *sdma = &qe_immr->sdma;
-   unsigned long sdma_buf_offset;
+   static unsigned long sdma_buf_offset;
 
if (!sdma)
return -ENODEV;
 
/* allocate 2 internal temporary buffers (512 bytes size each) for
 * the SDMA */
-   sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
-   if (IS_ERR_VALUE(sdma_buf_offset))
-   return -ENOMEM;
+   if (!sdma_buf_offset) {
+   sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
+   if (IS_ERR_VALUE(sdma_buf_offset))
+   return -ENOMEM;
+   }
 
out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 4/5] powerpc/85xx: Add suspend/resume support

2009-08-27 Thread Anton Vorontsov
This patch adds suspend/resume support for MPC8540-compatible and
MPC8569 CPUs.

MPC8540-compatible PMCs are trivial: we just write SLP bit into PM
control and status register.

MPC8569 is a bit trickier, QE turns off during suspend and so on
resume we must reload QE microcode firmware and reset QE.

So far we don't support Deep Sleep mode as found in newer MPC85xx
CPUs (i.e. MPC8536). It can be relatively easy implemented though,
and for it we reserve 'mem' suspend type.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/Kconfig  |2 +-
 arch/powerpc/platforms/85xx/Makefile  |1 +
 arch/powerpc/platforms/85xx/suspend.c |  115 +
 3 files changed, 117 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/suspend.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d00131c..46ebfe6 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -212,7 +212,7 @@ config ARCH_HIBERNATION_POSSIBLE
 
 config ARCH_SUSPEND_POSSIBLE
def_bool y
-   depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
+   depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || PPC_85xx
 
 config PPC_DCR_NATIVE
bool
diff --git a/arch/powerpc/platforms/85xx/Makefile 
b/arch/powerpc/platforms/85xx/Makefile
index 835733f..cd1ad6e 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SUSPEND) += suspend.o
 
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/suspend.c 
b/arch/powerpc/platforms/85xx/suspend.c
new file mode 100644
index 000..d4ca5e2
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/suspend.c
@@ -0,0 +1,115 @@
+/*
+ * Suspend/resume support
+ *
+ * Copyright © 2009  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct pmc_regs {
+   __be32 pmcsr;
+#define PMCSR_SLP  (1 << 17)
+};
+
+struct pmc_data {
+   unsigned int flags;
+#define PMC_NEED_QE_RELOAD (1 << 0)
+
+   const char *fw_name;
+};
+
+static struct device *pmc_dev;
+static struct pmc_regs __iomem *pmc_regs;
+static const struct pmc_data *pmc_data;
+static struct qe_firmware *pmc_qefw;
+
+static int pmc_suspend_enter(suspend_state_t state)
+{
+   out_be32(&pmc_regs->pmcsr, PMCSR_SLP);
+
+   if (pmc_qefw) {
+   int ret;
+
+   ret = qe_upload_firmware(pmc_qefw);
+   if (ret)
+   dev_err(pmc_dev, "could not upload firmware\n");
+
+   qe_reset();
+   }
+   return 0;
+}
+
+static int pmc_suspend_valid(suspend_state_t state)
+{
+   if (state != PM_SUSPEND_STANDBY)
+   return 0;
+
+   if (pmc_data && pmc_data->flags & PMC_NEED_QE_RELOAD && !pmc_qefw) {
+   const struct firmware *fw;
+   int ret;
+
+   ret = request_firmware(&fw, pmc_data->fw_name, pmc_dev);
+   if (ret) {
+   dev_err(pmc_dev, "could not request firmware %s\n",
+   pmc_data->fw_name);
+   return 0;
+   }
+
+   pmc_qefw = (struct qe_firmware *)fw->data;
+   }
+
+   return 1;
+}
+
+static struct platform_suspend_ops pmc_suspend_ops = {
+   .valid = pmc_suspend_valid,
+   .enter = pmc_suspend_enter,
+};
+
+static int pmc_probe(struct of_device *ofdev, const struct of_device_id *id)
+{
+   pmc_regs = of_iomap(ofdev->node, 0);
+   if (!pmc_regs)
+   return -ENOMEM;
+
+   pmc_dev = &ofdev->dev;
+   pmc_data = id->data;
+   suspend_set_ops(&pmc_suspend_ops);
+   return 0;
+}
+
+static struct pmc_data mpc8569_pmc_data = {
+   .flags = PMC_NEED_QE_RELOAD,
+   .fw_name = "fsl_qe_ucode_8569.bin",
+};
+
+static const struct of_device_id pmc_ids[] = {
+   { .compatible = "fsl,mpc8569-pmc", .data = &mpc8569_pmc_data, },
+   { .compatible = "fsl,mpc8548-pmc", },
+   { },
+};
+
+static struct of_platform_driver pmc_driver = {
+   .driver.name = "mpc85xx-pmc",
+   .match_table = pmc_ids,
+   .probe = pmc_probe,
+};
+
+static int pmc_init(void)
+{
+   return of_register_platform_driver(&pmc_driver);
+}
+device_initcall(pmc_init);
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 5/5] powerpc/85xx: Add power management support for MPC85xxMDS boards

2009-08-27 Thread Anton Vorontsov
- Add power management controller nodes;
- Add interrupts for RTC nodes, the RTC interrupt may be used as a
  wakeup source;

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/boot/dts/mpc8568mds.dts  |   15 +--
 arch/powerpc/boot/dts/mpc8569mds.dts  |   13 -
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |1 +
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts 
b/arch/powerpc/boot/dts/mpc8568mds.dts
index 00c2bbd..4d18ca3 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -107,6 +107,8 @@
r...@68 {
compatible = "dallas,ds1374";
reg = <0x68>;
+   interrupts = <3 1>;
+   interrupt-parent = <&mpic>;
};
};
 
@@ -252,10 +254,19 @@
interrupt-parent = <&mpic>;
};
 
-   global-utilit...@e {//global utilities block
-   compatible = "fsl,mpc8548-guts";
+   global-utilit...@e {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "fsl,mpc8568-guts", "fsl,mpc8548-guts";
reg = <0xe 0x1000>;
+   ranges = <0 0xe 0x1000>;
fsl,has-rstcr;
+
+   pmc: po...@80 {
+   compatible = "fsl,mpc8568-pmc",
+"fsl,mpc8548-pmc";
+   reg = <0x80 0x10>;
+   };
};
 
serial1: ser...@4600 {
diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts 
b/arch/powerpc/boot/dts/mpc8569mds.dts
index 880f896..88d96b8 100644
--- a/arch/powerpc/boot/dts/mpc8569mds.dts
+++ b/arch/powerpc/boot/dts/mpc8569mds.dts
@@ -171,6 +171,8 @@
r...@68 {
compatible = "dallas,ds1374";
reg = <0x68>;
+   interrupts = <3 1>;
+   interrupt-parent = <&mpic>;
};
};
 
@@ -304,9 +306,18 @@
};
 
global-utilit...@e {
-   compatible = "fsl,mpc8569-guts";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "fsl,mpc8569-guts", "fsl,mpc8548-guts";
reg = <0xe 0x1000>;
+   ranges = <0 0xe 0x1000>;
fsl,has-rstcr;
+
+   pmc: po...@80 {
+   compatible = "fsl,mpc8569-pmc",
+"fsl,mpc8548-pmc";
+   reg = <0x80 0x10>;
+   };
};
 
par...@e0100 {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c 
b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 20a61d0..995ddad 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -300,6 +300,7 @@ static struct of_device_id mpc85xx_ids[] = {
{ .compatible = "fsl,qe", },
{ .compatible = "gianfar", },
{ .compatible = "fsl,rapidio-delta", },
+   { .compatible = "fsl,mpc8548-guts", },
{},
 };
 
-- 
1.6.3.3
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/5] ucc_geth: Fix NULL pointer dereference in uec_get_ethtool_stats()

2009-08-27 Thread Anton Vorontsov
In commit 3e73fc9a12679a546284d597c1f19165792d0b83 ("ucc_geth: Fix IO
memory (un)mapping code") I fixed ug_regs IO memory leak by properly
freeing the allocated memory. But ethtool_stats() callback doesn't
check for ug_regs being NULL, and that causes following oops if
'ethtool -S' is executed on a closed eth device:

  Unable to handle kernel paging request for data at address 0x0180
  Faulting instruction address: 0xc0208228
  Oops: Kernel access of bad area, sig: 11 [#1]
  ...
  NIP [c0208228] uec_get_ethtool_stats+0x38/0x140
  LR [c02559a0] ethtool_get_stats+0xf8/0x23c
  Call Trace:
  [ef87bcd0] [c025597c] ethtool_get_stats+0xd4/0x23c (unreliable)
  [ef87bd00] [c025706c] dev_ethtool+0xfe8/0x11bc
  [ef87be00] [c0252b5c] dev_ioctl+0x454/0x6a8
  ...
  ---[ end trace 77fff1162a9586b0 ]---
  Segmentation fault

This patch fixes the issue.

Signed-off-by: Anton Vorontsov 
---
 drivers/net/ucc_geth_ethtool.c |8 ++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 61fe80d..304128f 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -319,9 +319,13 @@ static void uec_get_ethtool_stats(struct net_device 
*netdev,
int i, j = 0;
 
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
-   base = (u32 __iomem *)&ugeth->ug_regs->tx64;
+   if (ugeth->ug_regs)
+   base = (u32 __iomem *)&ugeth->ug_regs->tx64;
+   else
+   base = NULL;
+
for (i = 0; i < UEC_HW_STATS_LEN; i++)
-   data[j++] = in_be32(&base[i]);
+   data[j++] = base ? in_be32(&base[i]) : 0;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram;
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/5] powerpc/qe: Implement qe_alive_during_sleep() helper function

2009-08-27 Thread Anton Vorontsov
In some CPUs (i.e. MPC8569) QE shuts down completely during sleep,
drivers may want to know that to reinitialize registers and buffer
descriptors.

This patch implements qe_alive_during_sleep() helper function, so far
it just checks if MPC8569-compatible power management controller is
present, which is a sign that QE turns off during sleep.

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/qe.h   |1 +
 arch/powerpc/sysdev/qe_lib/qe.c |   13 +
 2 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index e8232bb..20c0b07 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -163,6 +163,7 @@ int qe_get_snum(void);
 void qe_put_snum(u8 snum);
 unsigned int qe_get_num_of_risc(void);
 unsigned int qe_get_num_of_snums(void);
+int qe_alive_during_sleep(void);
 
 /* we actually use cpm_muram implementation, define this for convenience */
 #define qe_muram_init cpm_muram_init
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index f485d5a..a765f9c 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -65,6 +65,19 @@ static unsigned int qe_num_of_snum;
 
 static phys_addr_t qebase = -1;
 
+int qe_alive_during_sleep(void)
+{
+   static int ret = -1;
+
+   if (ret != -1)
+   return ret;
+
+   ret = !of_find_compatible_node(NULL, NULL, "fsl,mpc8569-pmc");
+
+   return ret;
+}
+EXPORT_SYMBOL(qe_alive_during_sleep);
+
 phys_addr_t get_qe_base(void)
 {
struct device_node *qe;
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/5] ucc_geth: Factor out MAC initialization steps into a call

2009-08-27 Thread Anton Vorontsov
This patch factors out MAC initialization into ucc_geth_init_mac()
function that we'll use for suspend/resume.

Signed-off-by: Anton Vorontsov 
---
 drivers/net/ucc_geth.c |   87 ---
 1 files changed, 52 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 3b957e6..488b591 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3413,46 +3413,25 @@ static int ucc_geth_set_mac_addr(struct net_device 
*dev, void *p)
return 0;
 }
 
-/* Called when something needs to use the ethernet device */
-/* Returns 0 for success. */
-static int ucc_geth_open(struct net_device *dev)
+static int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
 {
-   struct ucc_geth_private *ugeth = netdev_priv(dev);
+   struct net_device *dev = ugeth->ndev;
int err;
 
-   ugeth_vdbg("%s: IN", __func__);
-
-   /* Test station address */
-   if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
-   if (netif_msg_ifup(ugeth))
-   ugeth_err("%s: Multicast address used for station 
address"
- " - is this what you wanted?", __func__);
-   return -EINVAL;
-   }
-
-   err = init_phy(dev);
-   if (err) {
-   if (netif_msg_ifup(ugeth))
-   ugeth_err("%s: Cannot initialize PHY, aborting.",
- dev->name);
-   return err;
-   }
-
err = ucc_struct_init(ugeth);
if (err) {
if (netif_msg_ifup(ugeth))
-   ugeth_err("%s: Cannot configure internal struct, 
aborting.", dev->name);
-   goto out_err_stop;
+   ugeth_err("%s: Cannot configure internal struct, "
+ "aborting.", dev->name);
+   goto err;
}
 
-   napi_enable(&ugeth->napi);
-
err = ucc_geth_startup(ugeth);
if (err) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot configure net device, aborting.",
  dev->name);
-   goto out_err;
+   goto err;
}
 
err = adjust_enet_interface(ugeth);
@@ -3460,7 +3439,7 @@ static int ucc_geth_open(struct net_device *dev)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot configure net device, aborting.",
  dev->name);
-   goto out_err;
+   goto err;
}
 
/*   Set MACSTNADDR1, MACSTNADDR2*/
@@ -3474,13 +3453,51 @@ static int ucc_geth_open(struct net_device *dev)
   &ugeth->ug_regs->macstnaddr1,
   &ugeth->ug_regs->macstnaddr2);
 
-   phy_start(ugeth->phydev);
-
err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
if (err) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot enable net device, aborting.", 
dev->name);
-   goto out_err;
+   goto err;
+   }
+
+   return 0;
+err:
+   ucc_geth_stop(ugeth);
+   return err;
+}
+
+/* Called when something needs to use the ethernet device */
+/* Returns 0 for success. */
+static int ucc_geth_open(struct net_device *dev)
+{
+   struct ucc_geth_private *ugeth = netdev_priv(dev);
+   int err;
+
+   ugeth_vdbg("%s: IN", __func__);
+
+   /* Test station address */
+   if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
+   if (netif_msg_ifup(ugeth))
+   ugeth_err("%s: Multicast address used for station "
+ "address - is this what you wanted?",
+ __func__);
+   return -EINVAL;
+   }
+
+   err = init_phy(dev);
+   if (err) {
+   if (netif_msg_ifup(ugeth))
+   ugeth_err("%s: Cannot initialize PHY, aborting.",
+ dev->name);
+   return err;
+   }
+
+   err = ucc_geth_init_mac(ugeth);
+   if (err) {
+   if (netif_msg_ifup(ugeth))
+   ugeth_err("%s: Cannot initialize MAC, aborting.",
+ dev->name);
+   goto err;
}
 
err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler,
@@ -3489,16 +3506,16 @@ static int ucc_geth_open(struct net_device *dev)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot get IRQ for net device, 
aborting.",
  dev->name);
-   goto out_err;
+   

[PATCH 5/5] ucc_geth: Implement suspend/resume and Wake-On-LAN support

2009-08-27 Thread Anton Vorontsov
This patch implements suspend/resume and WOL support for UCC Ethernet
driver.

We support two wake up events: wake on PHY/link changes and wake
on magic packet.

In some CPUs (like MPC8569) QE shuts down during sleep, so magic packet
detection is unusable, and also on resume we should fully reinitialize
UCC structures.

Signed-off-by: Anton Vorontsov 
---
 drivers/net/ucc_geth.c |   85 
 drivers/net/ucc_geth.h |1 +
 drivers/net/ucc_geth_ethtool.c |   40 +++
 3 files changed, 126 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index d4e51ee..33ed69e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3481,6 +3481,10 @@ static int ucc_geth_open(struct net_device *dev)
napi_enable(&ugeth->napi);
netif_start_queue(dev);
 
+   device_set_wakeup_capable(&dev->dev,
+   qe_alive_during_sleep() || ugeth->phydev->irq);
+   device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
+
return err;
 
 err:
@@ -3545,6 +3549,85 @@ static void ucc_geth_timeout(struct net_device *dev)
schedule_work(&ugeth->timeout_work);
 }
 
+
+#ifdef CONFIG_PM
+
+static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state)
+{
+   struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+   struct ucc_geth_private *ugeth = netdev_priv(ndev);
+
+   if (!netif_running(ndev))
+   return 0;
+
+   napi_disable(&ugeth->napi);
+
+   /*
+* Disable the controller, otherwise we'll wakeup on any network
+* activity.
+*/
+   ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+   if (ugeth->wol_en & WAKE_MAGIC) {
+   setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
+   setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
+   ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
+   } else if (!(ugeth->wol_en & WAKE_PHY)) {
+   phy_stop(ugeth->phydev);
+   }
+
+   return 0;
+}
+
+static int ucc_geth_resume(struct of_device *ofdev)
+{
+   struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+   struct ucc_geth_private *ugeth = netdev_priv(ndev);
+   int err;
+
+   if (!netif_running(ndev))
+   return 0;
+
+   if (qe_alive_during_sleep()) {
+   if (ugeth->wol_en & WAKE_MAGIC) {
+   ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX);
+   clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
+   clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
+   }
+   ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+   } else {
+   /*
+* Full reinitialization is required if QE shuts down
+* during sleep.
+*/
+   ucc_geth_memclean(ugeth);
+
+   err = ucc_geth_init_mac(ugeth);
+   if (err) {
+   ugeth_err("%s: Cannot initialize MAC, aborting.",
+ ndev->name);
+   return err;
+   }
+   }
+
+   ugeth->oldlink = 0;
+   ugeth->oldspeed = 0;
+   ugeth->oldduplex = -1;
+
+   phy_stop(ugeth->phydev);
+   phy_start(ugeth->phydev);
+
+   napi_enable(&ugeth->napi);
+   netif_start_queue(ndev);
+
+   return 0;
+}
+
+#else
+#define ucc_geth_suspend NULL
+#define ucc_geth_resume NULL
+#endif
+
 static phy_interface_t to_phy_interface(const char *phy_connection_type)
 {
if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -3836,6 +3919,8 @@ static struct of_platform_driver ucc_geth_driver = {
.match_table= ucc_geth_match,
.probe  = ucc_geth_probe,
.remove = ucc_geth_remove,
+   .suspend= ucc_geth_suspend,
+   .resume = ucc_geth_resume,
 };
 
 static int __init ucc_geth_init(void)
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index 195ab26..fee97ee 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1220,6 +1220,7 @@ struct ucc_geth_private {
int oldspeed;
int oldduplex;
int oldlink;
+   int wol_en;
 
struct device_node *node;
 };
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 304128f..7075f26 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -359,6 +359,44 @@ uec_get_drvinfo(struct net_device *netdev,
drvinfo->regdump_len = uec_get_regs_len(netdev);
 }
 
+#ifdef CONFIG_PM
+
+static void uec_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+   struct ucc_geth_private *ugeth = netdev_priv(netdev);
+   struct phy_device *phydev = uget

[PATCH 4/5] ucc_geth: Remove UGETH_MAGIC_PACKET Kconfig symbol and code

2009-08-27 Thread Anton Vorontsov
This patch removes currently unused UGETH_MAGIC_PACKET Kconfig symbol
and code, i.e. magic_packet_detection_{enable,disable} functions.

The two functions each contain just two steps that we'll place into
suspend/resume code path under CONFIG_PM.

Signed-off-by: Anton Vorontsov 
---
 drivers/net/Kconfig|4 
 drivers/net/ucc_geth.c |   32 
 2 files changed, 0 insertions(+), 36 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f6509a..d171131 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2367,10 +2367,6 @@ config UCC_GETH
  This driver supports the Gigabit Ethernet mode of the QUICC Engine,
  which is available on some Freescale SOCs.
 
-config UGETH_MAGIC_PACKET
-   bool "Magic Packet detection support"
-   depends on UCC_GETH
-
 config UGETH_TX_ON_DEMAND
bool "Transmit on Demand support"
depends on UCC_GETH
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 488b591..d4e51ee 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -437,38 +437,6 @@ static void hw_add_addr_in_hash(struct ucc_geth_private 
*ugeth,
 QE_CR_PROTOCOL_ETHERNET, 0);
 }
 
-#ifdef CONFIG_UGETH_MAGIC_PACKET
-static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
-{
-   struct ucc_fast_private *uccf;
-   struct ucc_geth __iomem *ug_regs;
-
-   uccf = ugeth->uccf;
-   ug_regs = ugeth->ug_regs;
-
-   /* Enable interrupts for magic packet detection */
-   setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
-
-   /* Enable magic packet detection */
-   setbits32(&ug_regs->maccfg2, MACCFG2_MPE);
-}
-
-static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
-{
-   struct ucc_fast_private *uccf;
-   struct ucc_geth __iomem *ug_regs;
-
-   uccf = ugeth->uccf;
-   ug_regs = ugeth->ug_regs;
-
-   /* Disable interrupts for magic packet detection */
-   clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
-
-   /* Disable magic packet detection */
-   clrbits32(&ug_regs->maccfg2, MACCFG2_MPE);
-}
-#endif /* MAGIC_PACKET */
-
 static inline int compare_addr(u8 **addr1, u8 **addr2)
 {
return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] rtc: Set wakeup capability for I2C and SPI RTC drivers

2009-08-27 Thread Anton Vorontsov
RTC core won't allow wakeup alarms to be set if RTC devices' parent
(i.e. i2c_client or spi_device) isn't wakeup capable.

For I2C devices there is I2C_CLIENT_WAKE flag exists that we can pass
via board info, and if set, I2C core will initialize wakeup capability.
For SPI devices there is no such flag at all.

I believe that it's not platform code responsibility to allow or
disallow wakeups, instead, drivers themselves should set the capability
if a device can trigger wakeups.

That's what drivers/base/power/sysfs.c says:

 * It is the responsibility of device drivers to enable (or disable)
 * wakeup signaling as part of changing device power states, respecting
 * the policy choices provided through the driver model.

I2C and SPI RTC devices send wakeup events via interrupt lines, so we
should set the wakeup capability if IRQ is routed.

Ideally we should also check irq for wakeup capability before setting
device's capability, i.e.

if (can_irq_wake(irq))
device_set_wakeup_capable(&client->dev, 1);

But there is no can_irq_wake() call exist, and it is not that trivial
to implement it for all interrupts controllers and complex/cascaded
setups.

drivers/base/power/sysfs.c also covers these cases:

 * Devices may not be able to generate wakeup events from all power
 * states.  Also, the events may be ignored in some configurations;
 * for example, they might need help from other devices that aren't
 * active

So there is no guarantee that wakeup will actually work, and so I think
there is no point in being pedantic wrt checking IRQ wakeup capability.

Signed-off-by: Anton Vorontsov 
---
 drivers/rtc/rtc-ds1305.c |2 ++
 drivers/rtc/rtc-ds1307.c |2 ++
 drivers/rtc/rtc-ds1374.c |2 ++
 3 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 2736b11..e256c03 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -780,6 +780,8 @@ static int __devinit ds1305_probe(struct spi_device *spi)
spi->irq, status);
goto fail1;
}
+
+   device_set_wakeup_capable(&spi->dev, 1);
}
 
/* export NVRAM */
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 47a93c0..87097d4 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -881,6 +881,8 @@ read_rtc:
"unable to request IRQ!\n");
goto exit_irq;
}
+
+   device_set_wakeup_capable(&client->dev, 1);
set_bit(HAS_ALARM, &ds1307->flags);
dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
}
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 713f7bf..5317bbc 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -383,6 +383,8 @@ static int ds1374_probe(struct i2c_client *client,
dev_err(&client->dev, "unable to request IRQ\n");
goto out_free;
}
+
+   device_set_wakeup_capable(&client->dev, 1);
}
 
ds1374->rtc = rtc_device_register(client->name, &client->dev,
-- 
1.6.3.3
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] rtc: Set wakeup capability for I2C and SPI RTC drivers

2009-08-27 Thread Anton Vorontsov
On Thu, Aug 27, 2009 at 02:52:36PM -0700, David Brownell wrote:
[...]
> > I believe that it's not platform code responsibility to allow or
> > disallow wakeups, instead, drivers themselves should set the capability
> > if a device can trigger wakeups.
> 
> Drivers can't generally know if that's possible though.
> They need to be told that it is, by platform code.

Um? Of course they know, DS1374 device driver knows that DS1374
chips can issue wakeups, what it doesn't know is if that wakeup
event will trigger CPU resume/power-up.

And even platform code doesn't know that. For example, on PowerPC
CPUs there could be several 'suspend' states, some allow wakeup
on particular IRQs, some don't. In some cases wakeup event will be
ignored, in other cases it will take effect. The suspend mode
depends on user's decision ('echo  > /sys/power/state').

> Most devices can't issue wakeup events.

The device drivers I modified know that devices can issue wakeup
events.

> > That's what drivers/base/power/sysfs.c says:
> > 
> >  * It is the responsibility of device drivers to enable (or disable)
> >  * wakeup signaling as part of changing device power states, respecting
> >  * the policy choices provided through the driver model.
> > 
> > I2C and SPI RTC devices send wakeup events via interrupt lines, so we
> > should set the wakeup capability if IRQ is routed.
> 
> Re-read the quoted sentence.  You're saying that policy
> choices should be hard-wired into the driver; contrary
> to that quote.  (In this case the choice is one that
> platform code must report, and which the hardware
> designer made:  if the device can issue wakeup events.)

The patch doesn't hard-wire the policy, quite the contrary: it
removes the "can't do wakeup" policy.

I'm just adding device_set_wakeup_capable() calls, telling everybody
that the devices can issue wakeup events (and they truly can).

Yes, it could be that the IRQ line is wired not to a CPU, but
to some power switch, and so nobody pass any IRQs to the drivers.
In that case platform-specific I2C_CLIENT_WAKE may be useful.

> > Ideally we should also check irq for wakeup capability before setting
> > device's capability, i.e.
> > 
> > if (can_irq_wake(irq))
> > device_set_wakeup_capable(&client->dev, 1);
> > 
> > But there is no can_irq_wake() call exist, and it is not that trivial
> > to implement it for all interrupts controllers and complex/cascaded
> > setups.
> 
> That is why platform code should device_init_wakeup() and
> drivers should check device_can_wakeup(dev) ...

They should (and do) check may_wakeup() (i.e. should_wakeup) before
suspending, not can_wakeup().

static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
{
if (client->irq >= 0 && device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
return 0;
}

(quite funny, they issue enable_irq_wake(), assuming that otherwise
IRQ line won't trigger CPU wakeup. But in reality, there are interrupt
controllers that you can't control in that regard: any IRQ activity
will always resume CPU. And so 'echo disable > /sys/.../wakeup' won't
guarantee anything. Unreliable, nasty? Could be.)

> > drivers/base/power/sysfs.c also covers these cases:
> > 
> >  * Devices may not be able to generate wakeup events from all power
> >  * states.  Also, the events may be ignored in some configurations;
> >  * for example, they might need help from other devices that aren't
> >  * active
> > 
> > So there is no guarantee that wakeup will actually work, 
> 
> Yes there is ... it's only **exceptional** cases where it can't
> work.  Your patch would make it routine that those flags be
> unreliable; pretty nasty.

It's not exceptional at all, you really can't tell if device's wakeup
event will take any effect. It depends on so many factors that it's
virtually impossible to account them all. And hiding wakeup capability
only because you aren't sure _is_ policy hard-wiring, no?

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] rtc: Set wakeup capability for I2C and SPI RTC drivers

2009-08-27 Thread Anton Vorontsov
On Fri, Aug 28, 2009 at 03:19:25AM +0400, Anton Vorontsov wrote:
[...]
> > That is why platform code should device_init_wakeup() and
> > drivers should check device_can_wakeup(dev) ...
> 
> They should (and do) check may_wakeup() (i.e. should_wakeup) before
> suspending, not can_wakeup().
> 
> static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
> {
> if (client->irq >= 0 && device_may_wakeup(&client->dev))
> enable_irq_wake(client->irq);
> return 0;
> }
> 
> (quite funny, they issue enable_irq_wake(), assuming that otherwise
> IRQ line won't trigger CPU wakeup. But in reality, there are interrupt
> controllers that you can't control in that regard: any IRQ activity
> will always resume CPU. And so 'echo disable > /sys/.../wakeup' won't
> guarantee anything. Unreliable, nasty? Could be.)

BTW, of course we can fix this by masking interrupts before
suspending, but nobody actually do this (but should, I think).

And if RTC's IRQ is wired to power switch you're in trouble
without any way to fix this.

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/5] powerpc/qe: Make qe_reset() code path safe for repeated invocation

2009-08-28 Thread Anton Vorontsov
On Fri, Aug 28, 2009 at 12:34:50AM -0500, Kumar Gala wrote:
[...]
> >static int qe_sdma_init(void)
> >{
> > struct sdma __iomem *sdma = &qe_immr->sdma;
> >-unsigned long sdma_buf_offset;
> >+static unsigned long sdma_buf_offset;
> >
> > if (!sdma)
> > return -ENODEV;
> >
> > /* allocate 2 internal temporary buffers (512 bytes size each) for
> >  * the SDMA */
> >-sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
> >-if (IS_ERR_VALUE(sdma_buf_offset))
> >-return -ENOMEM;
> >+if (!sdma_buf_offset) {
> >+sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
> >+if (IS_ERR_VALUE(sdma_buf_offset))
> 
> shouldn't we zero out sdma_buf_offset otherwise if we call this
> again we'll think its set.

Technically, no. If qe_sdma_init() fails, kernel will panic:

void __init qe_reset(void)
{
...
if (qe_sdma_init())
panic("sdma init failed!");
}

But I see your point, it isn't obvious and may lead to a bug if
we'll decide to not panic later on. Therefore I'd better make the
change.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 4/5] powerpc/85xx: Add suspend/resume support

2009-08-28 Thread Anton Vorontsov
On Fri, Aug 28, 2009 at 12:38:51AM -0500, Kumar Gala wrote:
> 
> On Aug 27, 2009, at 12:30 PM, Anton Vorontsov wrote:
> 
> >This patch adds suspend/resume support for MPC8540-compatible and
> >MPC8569 CPUs.
> >
> >MPC8540-compatible PMCs are trivial: we just write SLP bit into PM
> >control and status register.
> >
> >MPC8569 is a bit trickier, QE turns off during suspend and so on
> >resume we must reload QE microcode firmware and reset QE.
> >
> >So far we don't support Deep Sleep mode as found in newer MPC85xx
> >CPUs (i.e. MPC8536). It can be relatively easy implemented though,
> >and for it we reserve 'mem' suspend type.
> >
> >Signed-off-by: Anton Vorontsov 
> >---
> >arch/powerpc/Kconfig  |2 +-
> >arch/powerpc/platforms/85xx/Makefile  |1 +
> >arch/powerpc/platforms/85xx/suspend.c |  115
> >+
> >3 files changed, 117 insertions(+), 1 deletions(-)
> >create mode 100644 arch/powerpc/platforms/85xx/suspend.c
> 
> How did you test this?

--- Prerequisites:

1. Following patches should be applied in addition:

   rtc: Set wakeup capability for I2C and SPI RTC drivers
   [5/5] ucc_geth: Implement suspend/resume and Wake-On-LAN support
   [4/5] ucc_geth: Remove UGETH_MAGIC_PACKET Kconfig symbol and code
   [3/5] ucc_geth: Factor out MAC initialization steps into a call
   [2/5] powerpc/qe: Implement qe_alive_during_sleep() helper function
   [1/5] ucc_geth: Fix NULL pointer dereference in uec_get_ethtool_stats()

2. QE microcode should be placed into /lib/firmware/, i.e.
   wget http://opensource.freescale.com/firmware/fsl_qe_ucode_8569_10.zip
   unzip fsl_qe_ucode_8569_10.zip
   cp fsl_qe_ucode_8569_10.bin //lib/firmware/fsl_qe_ucode_8569.bin

--- Wakeup on RTC alarm:

# cd /sys/class/rtc/rtc0/
# echo $(( `cat since_epoch` + 10 )) > wakealarm
# echo standby > /sys/power/state
mpc85xx-pmc e00e0080.power: firmware: requesting fsl_qe_ucode_8569.bin
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.02 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.


The board is now suspended, CPU asserted ASLEEP signal that is
reflected by the ASLEEP LED on the board (the LED is near UEC2
port). 10 seconds later the board will wakeup:

qe-firmware: firmware 'MPC8569 QE Microcode Rel_B6900155' for 8569 V1.0
qe-firmware: uploading microcode 'MPC8569 QE Microcode Rel_B69001' version 1.0.0
pci :00:00.0: enabling device (0106 -> 0107)
Restarting tasks ... done.
PHY: m...@e0082120:07 - Link is Up - 100/Full

--- Wakeup on PHY/link changes (no magic packet support in MPC8569, as
QE turns off during sleep):

# ethtool -s eth0 wol p
# echo standby > /sys/power/state
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.


To wakeup, trigger the PHY interrupt (e.g. pull out the ethernet
cable from eth0):

qe-firmware: firmware 'MPC8569 QE Microcode Rel_B6900155' for 8569 V1.0
qe-firmware: uploading microcode 'MPC8569 QE Microcode Rel_B69001' version 1.0.0
pci :00:00.0: enabling device (0106 -> 0107)
Restarting tasks ... done.


UCC magic packet detection was tested on MPC8360E-MDS boards
(ethtool -s eth0 wol g), I'll send power management support
patches for 83xx QE boards soon.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] powerpc/85xx: Add eSDHC support for MPC8536DS boards

2009-08-28 Thread Anton Vorontsov
On Fri, Aug 28, 2009 at 07:02:51PM +0800, Hu Mingkai-B21284 wrote:
> > On Tue, Aug 18, 2009 at 08:24:17PM -0500, Kumar Gala wrote:
> > > 
> > > On Aug 18, 2009, at 6:38 PM, Anton Vorontsov wrote:
> > > 
> > > >This patch simply adds sdhci node to the device tree.
> > > >
> > > >We specify clock-frequency manually, so that eSDHC will 
> > work without 
> > > >upgrading U-Boot. Though, that'll only work for default setup (1500
> > > >MHz) on new board revisions. For non-default setups, it's 
> > recommended 
> > > >to upgrade U-Boot, since it will fixup clock-frequency 
> > automatically.
> > > >
> > > >Signed-off-by: Anton Vorontsov 
> > > 
> > > out of interest the 85xx eSDHC don't need the sdhci,wp-inverted 
> > > property?
> > 
> > Yes, eSDHC controllers in MPC85xx report normal state in its 
> > registers.
> > 
> 
> Hi Anton,
> 
> The eSDHC controller in different silicon version on MPC8536  reports
> different WP state in the register PRSSTAT:

Thanks a million for the heads up!

Yes, the manual I used ("MPC8536ERM Rev. 0 10/2008") doesn't mention
that, but the newer manual that I just downloaded ("MPC8536ERM Rev. 1
05/2009") does.

[...]
> For silicon 1.0,  the macro SDHCI_QUIRK_INVERTED_WRITE_PROTECT is also
> defined,
> so the dirver will report the error WP state in function sdhci_get_ro.

Not any longer. We don't actually define it for any 85xx CPUs.

I need to think how should we handle all these WP inversions. :-)

So, we have inversion in BCSR (depending on the BCSR revision),
configurable inversion in CPU via GENCFGR for 1.1 silicon, and
non-configurable non-inverted reporting for 1.0 silicon...

Do you know if there are any plans to fix the WP inversion for
MPC8569E-MDS boards, or make something like GENCFGR for MPC8569
CPUs?

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2 0/5] Suspend/resume support for some 83xx/85xx/86xx boards

2009-08-30 Thread Anton Vorontsov
On Fri, Aug 28, 2009 at 12:38:51AM -0500, Kumar Gala wrote:
> >This patch adds suspend/resume support for MPC8540-compatible and
> >MPC8569 CPUs.
[...] 
> I'd also like to get Scott's Ack on this and the device tree patches
> before accepting them.

Heh, I didn't notice that the PMC bindings for 85xx describe devdisr
registers (and thus sleep = <> properties).

So here are updated patches that should comply with the bindings.
Plus,

- It appears that 86xx PMCs registers-compatible with 85xx, so we
  can support both. Thus move 85xx/suspend.c to sysdev/fsl_pmc.c;
- New patch that adds suspend/resume for MPC8610HPCD;
- New patch that adds suspend/resume for 83xx QE boards;
- Some fixes in "Make qe_reset() code path safe for repeated
  invocation" patch.

Thanks,

-- 
Anton Vorontsov
email: cbouatmai...@gmail.com
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/5] powerpc/qe: Make qe_reset() code path safe for repeated invocation

2009-08-30 Thread Anton Vorontsov
For MPC8569 CPUs we'll need to reset QE after each suspend, so make
qe_reset() code path suitable for repeated invocation, that is:

- Don't initialize rheap structures if already initialized;
- Don't allocate muram for SDMA if already allocated, just reinitialize
  registers with previously allocated muram offset;
- Remove __init attributes from qe_reset() and cpm_muram_init();

Signed-off-by: Anton Vorontsov 
---
 arch/powerpc/include/asm/qe.h|2 +-
 arch/powerpc/sysdev/cpm_common.c |5 -
 arch/powerpc/sysdev/qe_lib/qe.c  |   12 +++-
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index e8232bb..2f44754 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -87,7 +87,7 @@ extern spinlock_t cmxgcr_lock;
 
 /* Export QE common operations */
 #ifdef CONFIG_QUICC_ENGINE
-extern void __init qe_reset(void);
+extern void qe_reset(void);
 #else
 static inline void qe_reset(void) {}
 #endif
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index e4b6d66..9de72c9 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -72,7 +72,7 @@ static phys_addr_t muram_pbase;
 /* Max address size we deal with */
 #define OF_MAX_ADDR_CELLS  4
 
-int __init cpm_muram_init(void)
+int cpm_muram_init(void)
 {
struct device_node *np;
struct resource r;
@@ -81,6 +81,9 @@ int __init cpm_muram_init(void)
int i = 0;
int ret = 0;
 
+   if (muram_pbase)
+   return 0;
+
spin_lock_init(&cpm_muram_lock);
/* initialize the info header */
rh_init(&cpm_muram_info, 1,
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index b06564f..4eaf2a9 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -91,7 +91,7 @@ phys_addr_t get_qe_base(void)
 
 EXPORT_SYMBOL(get_qe_base);
 
-void __init qe_reset(void)
+void qe_reset(void)
 {
if (qe_immr == NULL)
qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
@@ -317,16 +317,18 @@ EXPORT_SYMBOL(qe_put_snum);
 static int qe_sdma_init(void)
 {
struct sdma __iomem *sdma = &qe_immr->sdma;
-   unsigned long sdma_buf_offset;
+   static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
 
if (!sdma)
return -ENODEV;
 
/* allocate 2 internal temporary buffers (512 bytes size each) for
 * the SDMA */
-   sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
-   if (IS_ERR_VALUE(sdma_buf_offset))
-   return -ENOMEM;
+   if (IS_ERR_VALUE(sdma_buf_offset)) {
+   sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
+   if (IS_ERR_VALUE(sdma_buf_offset))
+   return -ENOMEM;
+   }
 
out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
-- 
1.6.3.3

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


  1   2   3   4   5   6   7   8   9   10   >