LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH-stable] powerpc: Fix incorrect setting of __HAVE_ARCH_PTE_SPECIAL
From: Benjamin Herrenschmidt @ 2009-09-24  7:16 UTC (permalink / raw)
  To: stable; +Cc: linuxppc-dev list, bernhard.weirich, RFeany

From: Weirich, Bernhard <Bernhard.Weirich@riedel.net>

The test that decides whether to define __HAVE_ARCH_PTE_SPECIAL on
powerpc is bogus and will end up always defining it, even when
_PAGE_SPECIAL is not supported (in which case it's 0) such as on
8xx or 40x processors.

Signed-off-by: Bernhard Weirich <bernhard.weirich@riedel.net>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/pte-common.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Greg: I'm going to fix upstream differently, by having all CPU types
actually support _PAGE_SPECIAL, but I prefer the simple and obvious
fix for -stable.

This should apply to v2.6.30 and v2.6.31


diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h
index a7e210b..0cd2e34 100644
--- a/arch/powerpc/include/asm/pte-common.h
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -176,7 +176,7 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
 #define HAVE_PAGE_AGP
 
 /* Advertise support for _PAGE_SPECIAL */
-#ifdef _PAGE_SPECIAL
+#if _PAGE_SPECIAL != 0
 #define __HAVE_ARCH_PTE_SPECIAL
 #endif
 

^ permalink raw reply related

* [PATCH-stable] powerpc/8xx: Fix regression introduced by cache coherency rewrite
From: Benjamin Herrenschmidt @ 2009-09-24  7:16 UTC (permalink / raw)
  To: stable; +Cc: linuxppc-dev list, RFeany

From: Rex Feany <RFeany@mrv.com>

After upgrading to the latest kernel on my mpc875 userspace started
running incredibly slow (hours to get to a shell, even!).
I tracked it down to commit 8d30c14cab30d405a05f2aaceda1e9ad57800f36,
that patch removed a work-around for the 8xx. Adding it
back makes my problem go away.

Signed-off-by: Rex Feany <rfeany@mrv.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/mm/pgtable.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)

I'm going to push an upstream variant of this patch upstream tomorrow,
it will be a bit different due to significant changes in that file
and the affected functions.

This should apply to v2.6.30 (with fuzz) and v2.6.31

diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 627767d..d8e6725 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -30,6 +30,8 @@
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
+#include "mmu_decl.h"
+
 static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 static unsigned long pte_freelist_forced_free;
 
@@ -119,7 +121,7 @@ void pte_free_finish(void)
 /*
  * Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags()
  */
-static pte_t do_dcache_icache_coherency(pte_t pte)
+static pte_t do_dcache_icache_coherency(pte_t pte, unsigned long addr)
 {
 	unsigned long pfn = pte_pfn(pte);
 	struct page *page;
@@ -128,6 +130,17 @@ static pte_t do_dcache_icache_coherency(pte_t pte)
 		return pte;
 	page = pfn_to_page(pfn);
 
+#ifdef CONFIG_8xx
+       /* On 8xx, cache control instructions (particularly
+        * "dcbst" from flush_dcache_icache) fault as write
+        * operation if there is an unpopulated TLB entry
+        * for the address in question. To workaround that,
+        * we invalidate the TLB here, thus avoiding dcbst
+        * misbehaviour.
+        */
+       _tlbil_va(addr, 0 /* 8xx doesn't care about PID */);
+#endif
+
 	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
 		pr_devel("do_dcache_icache_coherency... flushing\n");
 		flush_dcache_icache_page(page);
@@ -198,7 +211,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte
 	 */
 	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 	if (pte_need_exec_flush(pte, 1))
-		pte = do_dcache_icache_coherency(pte);
+		pte = do_dcache_icache_coherency(pte, addr);
 
 	/* Perform the setting of the PTE */
 	__set_pte_at(mm, addr, ptep, pte, 0);
@@ -216,7 +229,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
 {
 	int changed;
 	if (!dirty && pte_need_exec_flush(entry, 0))
-		entry = do_dcache_icache_coherency(entry);
+		entry = do_dcache_icache_coherency(entry, address);
 	changed = !pte_same(*(ptep), entry);
 	if (changed) {
 		if (!(vma->vm_flags & VM_HUGETLB))

^ permalink raw reply related

* Bunch of fixes for upstream
From: Benjamin Herrenschmidt @ 2009-09-24  7:05 UTC (permalink / raw)
  To: linuxppc-dev list

Here's what I'll ask Linus to pull tomorrow, currently sitting in
powerpc merge branch:

Anton Blanchard (4):
      powerpc: Move 64bit heap above 1TB on machines with 1TB segments
      powerpc/perf_counter: Fix vdso detection
      powerpc: Increase NODES_SHIFT on 64bit from 4 to 8
      powerpc: Fix ibm,client-architecture-support printout

Becky Bruce (2):
      powerpc: Rename get_dma_direct_offset get_dma_offset
      powerpc: Change archdata dma_data to a union

Benjamin Herrenschmidt (3):
      powerpc/pmc: Don't access lppaca on Book3E
      powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
      Fix build of cpm_uart due to core changes

Hendrik Brueckner (1):
      hvc_console: Provide (un)locked version for hvc_resize()

Huang Weiyi (2):
      powerpc/book3e-64: Remove duplicated #include
      powerpc/mm: Remove duplicated #include

Josh Boyer (1):
      powerpc/4xx: Fix erroneous xmon warning on PowerPC 4xx

Rex Feany (1):
      powerpc/8xx: Fix regression introduced by cache coherency rewrite

Tim Abbott (1):
      powerpc: Cleanup linker script using new linker script macros.

Tony Breeds (1):
      powerpc: Check for unsupported relocs when using CONFIG_RELOCATABLE

roel kluin (1):
      powerpc: kmalloc failure ignored in vio_build_iommu_table()

 arch/powerpc/Kconfig                     |    6 +++
 arch/powerpc/Makefile                    |   11 +++++
 arch/powerpc/include/asm/device.h        |   11 ++++-
 arch/powerpc/include/asm/dma-mapping.h   |   27 ++++++++++-
 arch/powerpc/include/asm/iommu.h         |   10 ++++
 arch/powerpc/include/asm/pmc.h           |    2 +-
 arch/powerpc/include/asm/pte-40x.h       |    1 +
 arch/powerpc/include/asm/pte-8xx.h       |    1 +
 arch/powerpc/include/asm/pte-common.h    |    5 --
 arch/powerpc/kernel/dma-iommu.c          |   16 +++---
 arch/powerpc/kernel/dma.c                |   15 ++-----
 arch/powerpc/kernel/exceptions-64e.S     |    1 -
 arch/powerpc/kernel/pci-common.c         |    2 +-
 arch/powerpc/kernel/process.c            |   17 +++++++-
 arch/powerpc/kernel/prom_init.c          |    3 +-
 arch/powerpc/kernel/vdso.c               |   14 ++++--
 arch/powerpc/kernel/vio.c                |    4 +-
 arch/powerpc/kernel/vmlinux.lds.S        |   69 ++++++-----------------------
 arch/powerpc/mm/pgtable.c                |   19 +++++++-
 arch/powerpc/mm/tlb_low_64e.S            |    1 -
 arch/powerpc/platforms/cell/beat_iommu.c |    2 +-
 arch/powerpc/platforms/cell/iommu.c      |    9 +---
 arch/powerpc/platforms/iseries/iommu.c   |    2 +-
 arch/powerpc/platforms/pasemi/iommu.c    |    2 +-
 arch/powerpc/platforms/pseries/iommu.c   |    8 ++--
 arch/powerpc/relocs_check.pl             |   56 ++++++++++++++++++++++++
 arch/powerpc/sysdev/dart_iommu.c         |    2 +-
 arch/powerpc/xmon/xmon.c                 |   16 ++++++-
 drivers/char/hvc_console.c               |    6 +-
 drivers/char/hvc_console.h               |   12 +++++-
 drivers/char/hvc_iucv.c                  |    4 +-
 drivers/serial/cpm_uart/cpm_uart_core.c  |    2 +-
 32 files changed, 237 insertions(+), 119 deletions(-)
 create mode 100755 arch/powerpc/relocs_check.pl

^ permalink raw reply

* Re: [PATCH] Fix build of cpm_uart due to core changes
From: Benjamin Herrenschmidt @ 2009-09-24  7:01 UTC (permalink / raw)
  To: linuxppc-dev list; +Cc: alan
In-Reply-To: <1253772553.7103.402.camel@pasglop>

On Thu, 2009-09-24 at 16:09 +1000, Benjamin Herrenschmidt wrote:
> Commit ebd2c8f6d2ec4012c267ecb95e72a57b8355a705
> "serial: kill off uart_info"
> 
> broke the build of this driver, possibly because the driver isn't
> in drivers/serial and thus was missed by Alan. This fixes it.

I must have a serious amount of shit in my eyes :-) For some reason
I was persuaded the driver was in arch/powerpc .. well, it -is- in
drivers/serial, so yes, Alan did miss it somewhat but not because
it was in the wrong place :-)

Patch is still good tho, I'll fix up the comment in my tree.

Sorry,
Ben.

^ permalink raw reply

* Re: [PATCH] powerpc/8xx: fix regression introduced by cache coherency rewrite
From: Benjamin Herrenschmidt @ 2009-09-24  6:44 UTC (permalink / raw)
  To: Rex Feany; +Cc: linuxppc-dev
In-Reply-To: <20090924004552.GA11737@compile2.chatsunix.int.mrv.com>

On Wed, 2009-09-23 at 17:45 -0700, Rex Feany wrote:
> After upgrading to the latest kernel on my mpc875 userspace started
> running incredibly slow (hours to get to a shell, even!).
> I tracked it down to commit 8d30c14cab30d405a05f2aaceda1e9ad57800f36,
> that patch removed a work-around for the 8xx. Adding it
> back makes my problem go away.
> 
> Signed-off-by: Rex Feany <rfeany@mrv.com>

Note that while your patch applies to earlier kernels such as 2.6.31, it
doesn't apply with current Linus tree due to changes in that file. I've
updated the powerpc "merge" branch of my tree with a hand-modified
version, please test and let me know. That should also contain the
_PAGE_SPECIAL fix.
 
You can get my tree at:

git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git

(To get the "merge" branch, just add "merge" after the clone if you
are cloning it, or just create a local branch and manually pull
into it)

Note that i just pushed out so it may take a little while for
the kernel.org mirrors to get it, the commit ID is: 

ae48e383e3299c2f87723d21df2db97927774b1e

Cheers,
Ben. 

> diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
> index 627767d..d8e6725 100644
> --- a/arch/powerpc/mm/pgtable.c
> +++ b/arch/powerpc/mm/pgtable.c
> @@ -30,6 +30,8 @@
>  #include <asm/tlbflush.h>
>  #include <asm/tlb.h>
>  
> +#include "mmu_decl.h"
> +
>  static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
>  static unsigned long pte_freelist_forced_free;
>  
> @@ -119,7 +121,7 @@ void pte_free_finish(void)
>  /*
>   * Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags()
>   */
> -static pte_t do_dcache_icache_coherency(pte_t pte)
> +static pte_t do_dcache_icache_coherency(pte_t pte, unsigned long addr)
>  {
>  	unsigned long pfn = pte_pfn(pte);
>  	struct page *page;
> @@ -128,6 +130,17 @@ static pte_t do_dcache_icache_coherency(pte_t pte)
>  		return pte;
>  	page = pfn_to_page(pfn);
>  
> +#ifdef CONFIG_8xx
> +       /* On 8xx, cache control instructions (particularly
> +        * "dcbst" from flush_dcache_icache) fault as write
> +        * operation if there is an unpopulated TLB entry
> +        * for the address in question. To workaround that,
> +        * we invalidate the TLB here, thus avoiding dcbst
> +        * misbehaviour.
> +        */
> +       _tlbil_va(addr, 0 /* 8xx doesn't care about PID */);
> +#endif
> +
>  	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
>  		pr_devel("do_dcache_icache_coherency... flushing\n");
>  		flush_dcache_icache_page(page);
> @@ -198,7 +211,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte
>  	 */
>  	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
>  	if (pte_need_exec_flush(pte, 1))
> -		pte = do_dcache_icache_coherency(pte);
> +		pte = do_dcache_icache_coherency(pte, addr);
>  
>  	/* Perform the setting of the PTE */
>  	__set_pte_at(mm, addr, ptep, pte, 0);
> @@ -216,7 +229,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
>  {
>  	int changed;
>  	if (!dirty && pte_need_exec_flush(entry, 0))
> -		entry = do_dcache_icache_coherency(entry);
> +		entry = do_dcache_icache_coherency(entry, address);
>  	changed = !pte_same(*(ptep), entry);
>  	if (changed) {
>  		if (!(vma->vm_flags & VM_HUGETLB))

^ permalink raw reply

* [PATCH] Fix build of cpm_uart due to core changes
From: Benjamin Herrenschmidt @ 2009-09-24  6:09 UTC (permalink / raw)
  To: linuxppc-dev list; +Cc: alan

Commit ebd2c8f6d2ec4012c267ecb95e72a57b8355a705
"serial: kill off uart_info"

broke the build of this driver, possibly because the driver isn't
in drivers/serial and thus was missed by Alan. This fixes it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Vitaly: Care to send a patch to move the whole driver to drivers/serial where
it belongs or there's too many nasty dependencies to headers inside of
arch/powerpc/ ?

In the meantime, I'll put that in my merge branch which I'll ask Linus to
pull hopefully tomorrow (waiting for a test result from Rex to see if the
8xx problems are all gone)

Cheers,
Ben.

---
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 8d349b2..300cea7 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -649,7 +649,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
 	u8 *p;
 	int count;
 	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-	struct circ_buf *xmit = &port->info->xmit;
+	struct circ_buf *xmit = &port->state->xmit;
 
 	/* Handle xon/xoff */
 	if (port->x_char) {

^ permalink raw reply related

* linux-next: tree build failure
From: Stephen Rothwell @ 2009-09-24  5:21 UTC (permalink / raw)
  To: ppc-dev
  Cc: Hollis Blanchard, linux-kernel, kvm-ppc, linux-next, Jan Beulich,
	Andrew Morton

Hi all,

Today's linux-next build (powerpc ppc44x_defconfig) failed like this:

In file included from arch/powerpc/kvm/booke.c:31:
arch/powerpc/kvm/timing.h: In function 'kvmppc_account_exit_stat':
arch/powerpc/kvm/timing.h:51: error: bit-field '<anonymous>' width not an integer constant
In file included from arch/powerpc/kvm/booke.h:26,
                 from arch/powerpc/kvm/booke_emulate.c:23:
arch/powerpc/kvm/timing.h: In function 'kvmppc_account_exit_stat':
arch/powerpc/kvm/timing.h:51: error: bit-field '<anonymous>' width not an integer constant

Presumably caused by commit 8c87df457cb58fe75b9b893007917cf8095660a0
("BUILD_BUG_ON(): fix it and a couple of bogus uses of it").

I applied the following patch for today.  This inline function is
only called from one place in one file ...

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Thu, 24 Sep 2009 15:13:20 +1000
Subject: [PATCH] powerpc/kvm: build fix for new BUILD_BUG_ON

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kvm/timing.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kvm/timing.h b/arch/powerpc/kvm/timing.h
index bb13b1f..4c34099 100644
--- a/arch/powerpc/kvm/timing.h
+++ b/arch/powerpc/kvm/timing.h
@@ -48,7 +48,7 @@ static inline void kvmppc_set_exit_type(struct kvm_vcpu *vcpu, int type) {}
 static inline void kvmppc_account_exit_stat(struct kvm_vcpu *vcpu, int type)
 {
 	/* type has to be known at build time for optimization */
-	BUILD_BUG_ON(__builtin_constant_p(type));
+	//BUILD_BUG_ON(__builtin_constant_p(type));
 	switch (type) {
 	case EXT_INTR_EXITS:
 		vcpu->stat.ext_intr_exits++;
-- 
1.6.4.3


-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

^ permalink raw reply related

* Re: [v6 PATCH 0/7]: cpuidle/x86/POWER: Cleanup idle power management code in x86, cleanup drivers/cpuidle/cpuidle.c and introduce cpuidle to POWER.
From: Arun R Bharadwaj @ 2009-09-24  5:12 UTC (permalink / raw)
  To: Len Brown, Peter Zijlstra, Joel Schopp, Benjamin Herrenschmidt,
	Paul Mackerras, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Gautham R Shenoy, Shaohua Li,
	Venkatesh Pallipadi, Arun Bharadwaj
  Cc: linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20090922112526.GA7788@linux.vnet.ibm.com>

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-22 16:55:27]:

Hi Len, (or other acpi folks),

I had a question regarding ACPI-cpuidle interaction in the current
implementation.

Currently, every cpu (i.e. acpi_processor) registers to cpuidle as
a cpuidle_device. So every cpu has to go through the process of
setting up the idle states and then registering as a cpuidle device.

What exactly is the reason behind this?

Is this really necessary or can we have a system-wide one-time registering
to cpuidle by ACPI?

I'm currently in the process of enabling cpuidle for POWER systems and
find that having a system-wide registering mechanism to be a cleaner
design.

--arun

^ permalink raw reply

* Re: [PATCH 00/10] Add support for GCC's __builtin_unreachable() and use it in BUG.
From: Benjamin Herrenschmidt @ 2009-09-24  3:37 UTC (permalink / raw)
  To: David Daney
  Cc: linux-mips, Heiko Carstens, linuxppc-dev, Paul Mackerras,
	H. Peter Anvin, linux-s390, linux-am33-list, Helge Deller, x86,
	Ingo Molnar, Mike Frysinger, Ivan Kokshaysky, uclinux-dist-devel,
	Thomas Gleixner, Richard Henderson, Haavard Skinnemoen,
	linux-parisc, ralf, Kyle McMartin, linux-alpha,
	Martin Schwidefsky, linux390, Andrew Morton, Koichi Yasutake,
	Linus Torvalds
In-Reply-To: <4AA991C1.1050800@caviumnetworks.com>

On Thu, 2009-09-10 at 16:54 -0700, David Daney wrote:
> Starting with version 4.5, GCC has a new built-in function called
> __builtin_unreachable().  The function tells the compiler that control
> flow will never reach that point.  Currently we trick the compiler by
> putting in for(;;); but this has the disadvantage that extra code is
> emitted for an endless loop.  For an i386 kernel using
> __builtin_unreachable() results in an allyesconfig that is nearly 4000
> bytes smaller.

For the powerpc part:

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
From: Benjamin Herrenschmidt @ 2009-09-24  2:53 UTC (permalink / raw)
  To: Rex Feany; +Cc: Scott Wood, linuxppc-dev list, Weirich, Bernhard
In-Reply-To: <20090924023840.GA16381@compile2.chatsunix.int.mrv.com>

On Wed, 2009-09-23 at 19:38 -0700, Rex Feany wrote:
> Thus spake Benjamin Herrenschmidt (benh@kernel.crashing.org):
> 
> > Hrm. This is really strange...
> 
> Is this a problem? in pte-8xx.h you added:
> 
> +#define _PAGE_SPECIAL  0x0008  /* SW entry, forced to 0 by the TLB miss */
> 
> but there is already this:
> 
> #define _PAGE_EXEC      0x0008  /* software: i-cache coherency required */

Ohhh... you aren't using upstream ! That explains :-)

I removed _PAGE_EXEC from 8xx (since it doesn't use it for anything)
recently.

I think the best option is to go for Bernhard's patch for "stable" and
my patch for upstream, so that "stable" gets the bug fix without the
feature of _PAGE_SPECIAL and upstream gets it both.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
From: Rex Feany @ 2009-09-24  2:38 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev list, Weirich, Bernhard
In-Reply-To: <1253756434.7103.377.camel@pasglop>

Thus spake Benjamin Herrenschmidt (benh@kernel.crashing.org):

> Hrm. This is really strange...

Is this a problem? in pte-8xx.h you added:

+#define _PAGE_SPECIAL  0x0008  /* SW entry, forced to 0 by the TLB miss */

but there is already this:

#define _PAGE_EXEC      0x0008  /* software: i-cache coherency required */

take care!
/rex.

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
From: Benjamin Herrenschmidt @ 2009-09-24  1:40 UTC (permalink / raw)
  To: Rex Feany; +Cc: Scott Wood, linuxppc-dev list, Weirich, Bernhard
In-Reply-To: <20090924005300.GB11737@compile2.chatsunix.int.mrv.com>

On Wed, 2009-09-23 at 17:53 -0700, Rex Feany wrote:
> Thus spake Benjamin Herrenschmidt (benh@kernel.crashing.org):
> 
> > Bernhard, Rex, please let me know if that works for you.
> 
> it doesn't work for me, it crashes differently then before though!

Hrm. This is really strange...

> trunk+benh complicated patch:
> 
> crashes earlier:
> 
> BUG: Bad page map in process swapper  pte:001f88e9 pmd:020d8001

It's complaining because for some reason a PTE ends up with
_PAGE_SPECIAL set which indeed shouldn't be the case for a stack
page which is what is being accessed in our case. However, I have
no idea how that bit ended up being set. The generic code shouldn't
be setting it, and I looked several times at the TLB miss handling
on 8xx and can't find how in hell it would inadvertently set that
bit in the PTE...

Scott, I don't have any 8xx HW, any chance you can have a look at
what's going on here ?

The other bits in there look fine. So something must be whacking
_PAGE_SPECIAL in somewhere or at least whacking 0x8 in there.

Also, _PAGE_HWWRITE isn't set, but the DataTLBError code will
set it when setting dirty, so the page must have been created
pre-dirtied or something... all very weird I must say.

> addr:7ffffff6 vm_flags:00100177 anon_vma:c20d95e0 mapping:(null) index:7ffff
> Call Trace:
> [c341fd20] [c00067d0] show_stack+0x44/0x14c (unreliable)
> [c341fd60] [c0056860] print_bad_pte+0x1b4/0x1d0
> [c341fd90] [c00568c8] vm_normal_page+0x4c/0x78
> [c341fda0] [c0056988] follow_page+0x94/0x1b8
> [c341fdc0] [c005854c] __get_user_pages+0x324/0x3c4
> [c341fe20] [c006c12c] get_arg_page+0x40/0xac
> [c341fe40] [c006c374] copy_strings+0xec/0x1d4
> [c341fe80] [c006c47c] copy_strings_kernel+0x20/0x38
> [c341fea0] [c006d3cc] do_execve+0x110/0x240
> [c341fee0] [c00070c4] sys_execve+0x50/0x7c
> [c341ff00] [c000d0dc] ret_from_syscall+0x0/0x38
> [c341ffc0] [c00023ac] init_post+0x5c/0x168
> [c341ffe0] [c01df22c] kernel_init+0x10c/0x124
> [c341fff0] [c000cf3c] kernel_thread+0x4c/0x68
> 
> this is running on a MPC 875, and I'm happy to test any patches or
> add any debugging code if it helps.
> 
> thanks!
> /rex

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
From: Benjamin Herrenschmidt @ 2009-09-24  1:13 UTC (permalink / raw)
  To: Rex Feany; +Cc: linuxppc-dev list, Weirich, Bernhard
In-Reply-To: <20090924005300.GB11737@compile2.chatsunix.int.mrv.com>

On Wed, 2009-09-23 at 17:53 -0700, Rex Feany wrote:
> this is running on a MPC 875, and I'm happy to test any patches or
> add any debugging code if it helps.

Hrm... smells like something screwy in the 8xx PTE handling.

Let me have another look.

Cheers,
Ben.

^ permalink raw reply

* [PATCH] powerpc/8xx: fix regression introduced by cache coherency rewrite
From: Rex Feany @ 2009-09-24  0:45 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev

After upgrading to the latest kernel on my mpc875 userspace started
running incredibly slow (hours to get to a shell, even!).
I tracked it down to commit 8d30c14cab30d405a05f2aaceda1e9ad57800f36,
that patch removed a work-around for the 8xx. Adding it
back makes my problem go away.

Signed-off-by: Rex Feany <rfeany@mrv.com>

diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 627767d..d8e6725 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -30,6 +30,8 @@
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
+#include "mmu_decl.h"
+
 static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 static unsigned long pte_freelist_forced_free;
 
@@ -119,7 +121,7 @@ void pte_free_finish(void)
 /*
  * Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags()
  */
-static pte_t do_dcache_icache_coherency(pte_t pte)
+static pte_t do_dcache_icache_coherency(pte_t pte, unsigned long addr)
 {
 	unsigned long pfn = pte_pfn(pte);
 	struct page *page;
@@ -128,6 +130,17 @@ static pte_t do_dcache_icache_coherency(pte_t pte)
 		return pte;
 	page = pfn_to_page(pfn);
 
+#ifdef CONFIG_8xx
+       /* On 8xx, cache control instructions (particularly
+        * "dcbst" from flush_dcache_icache) fault as write
+        * operation if there is an unpopulated TLB entry
+        * for the address in question. To workaround that,
+        * we invalidate the TLB here, thus avoiding dcbst
+        * misbehaviour.
+        */
+       _tlbil_va(addr, 0 /* 8xx doesn't care about PID */);
+#endif
+
 	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
 		pr_devel("do_dcache_icache_coherency... flushing\n");
 		flush_dcache_icache_page(page);
@@ -198,7 +211,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte
 	 */
 	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 	if (pte_need_exec_flush(pte, 1))
-		pte = do_dcache_icache_coherency(pte);
+		pte = do_dcache_icache_coherency(pte, addr);
 
 	/* Perform the setting of the PTE */
 	__set_pte_at(mm, addr, ptep, pte, 0);
@@ -216,7 +229,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
 {
 	int changed;
 	if (!dirty && pte_need_exec_flush(entry, 0))
-		entry = do_dcache_icache_coherency(entry);
+		entry = do_dcache_icache_coherency(entry, address);
 	changed = !pte_same(*(ptep), entry);
 	if (changed) {
 		if (!(vma->vm_flags & VM_HUGETLB))

^ permalink raw reply related

* Re: [PATCH v3 0/3] cpu: pseries: Cpu offline states framework
From: Benjamin Herrenschmidt @ 2009-09-24  0:55 UTC (permalink / raw)
  To: dipankar
  Cc: Peter Zijlstra, Gautham R Shenoy, linux-kernel,
	Venkatesh Pallipadi, Arun R Bharadwaj, linuxppc-dev,
	Darrick J. Wong
In-Reply-To: <20090916162459.GB12571@in.ibm.com>

On Wed, 2009-09-16 at 21:54 +0530, Dipankar Sarma wrote:
> You aren't, I did :)
> 
> No, for this specific case, latency isn't an issue. The issue is -
> how do we cede unused vcpus to hypervisor for better energy
> management ?
> Yes, it can be done by a hypervisor manager telling the kernel to
> offline and make a bunch of vcpus "inactive". It does have to choose
> offline (release vcpu) vs. inactive (cede but guranteed if needed).
> The problem is that long ago we exported a lot of hotplug stuff to
> userspace through the sysfs interface and we cannot do something
> inside the kernel without keeping the sysfs stuff consistent.
> This seems like a sane way to do that without undoing all the
> virtual cpu hotplug infrastructure in different supporting archs.
> 
Well, I did bring the latency into the picture. To some extent it -is- a
latency issue. Though we aren't talking milliseconds here... if the
CPU's been reallocated to another partition we are talking seconds or
minutes or more until we can get it back :-)

In any case, this sounds to me like a perfectly valid feature to have,
which s390 already does via arch specific hooks, so I fail to see why it
wouldn't be legitimate to have a common attribute for it.

I don't buy into the layering violation. It's too often a straw man and
an excuse for a lack of a proper reason.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH v3 0/3] cpu: pseries: Cpu offline states framework
From: Benjamin Herrenschmidt @ 2009-09-24  0:52 UTC (permalink / raw)
  To: Heiko Carstens
  Cc: Darrick J. Wong, Peter Zijlstra, Gautham R Shenoy,
	Venkatesh Pallipadi, linux-kernel, Arun R Bharadwaj, linuxppc-dev,
	Balbir Singh
In-Reply-To: <20090916074848.GB4870@osiris.boeblingen.de.ibm.com>

On Wed, 2009-09-16 at 09:48 +0200, Heiko Carstens wrote:
> FWIW, this sounds exactly like the same we have already on s390.
> But back then I didn't consider adding a common code infrastructure
> would make sense :)
> 
> Besides the "online" attribute we have an additional "configure"
> attribute to which can only be written if the cpu is offline.
> Writing a "0" to it would mean that you currently won't need the cpu
> anymore and the hypervisor is free to reassign the cpu to a different
> LPAR.
> Writing a "1" to it means you want to use it. If there are enough
> resources you will get it. If not.. bad luck.
> 
Maybe we should use a common API for that then. And the right way to do
so is via a generically located attribute.

Ben.

^ permalink raw reply

* Re: [PATCH v3 0/3] cpu: pseries: Cpu offline states framework
From: Benjamin Herrenschmidt @ 2009-09-24  0:51 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Gautham R Shenoy, linux-kernel, Venkatesh Pallipadi,
	Arun R Bharadwaj, linuxppc-dev, Darrick J. Wong
In-Reply-To: <1253016701.5506.73.camel@laptop>

On Tue, 2009-09-15 at 14:11 +0200, Peter Zijlstra wrote:
> I still think its a layering violation... its the hypervisor manager
> that should be bothered in what state an off-lined cpu is in. 
> 
That's not how our hypervisor works.

If you ask through the management interface, to remove a CPU from a
partition, the HV will communicate with a daemon inside the partition
that will then unplug the CPU via the right call.

I don't really understand your objections to be honest. And I fail to
see why it would be a layering violation to have the ability for the OS
to indicate in what state it wishes to relinguish a CPU to the
hypervisor, which more or less defines what is the expected latency for
getting it back later on.

Ben.

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Fix 40x and 8xx vs. _PAGE_SPECIAL
From: Rex Feany @ 2009-09-24  0:53 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Weirich, Bernhard
In-Reply-To: <1253679146.7103.270.camel@pasglop>

Thus spake Benjamin Herrenschmidt (benh@kernel.crashing.org):

> Bernhard, Rex, please let me know if that works for you.

it doesn't work for me, it crashes differently then before though!

This patch worked for me:
> 
> Signed-off-by: Bernhard Weirich <bernhard.weirich@riedel.net>
> --- linux/arch/powerpc/include/asm/pte-common.h 2009-09-16 11:23:44.000000000 +0200
> +++ linux/arch/powerpc/include/asm/pte-common.h 2009-09-22 11:13:08.000000000 +0200
> @@ -176,7 +176,7 @@
>  #define HAVE_PAGE_AGP
>  
>  /* Advertise support for _PAGE_SPECIAL */
> -#ifdef _PAGE_SPECIAL
> +#if _PAGE_SPECIAL != 0
>  #define __HAVE_ARCH_PTE_SPECIAL
>  #endif
> 

without either patch:

boots into userspace, starts running my code
which uses mmap to access an fpga:

BUG: Bad page map in process loadfpga  pte:ff1008d3 pmd:02103001
addr:30028000 vm_flags:400844fb anon_vma:(null) mapping:c30000e8 index:ff100
vma->vm_ops->fault: 0x0
vma->vm_file->f_op->mmap: mmap_mem+0x0/0xa8
Call Trace:
[c2107db0] [c00067d0] show_stack+0x44/0x14c (unreliable)
[c2107df0] [c0056854] print_bad_pte+0x1b4/0x1d0
[c2107e20] [c0056898] vm_normal_page+0x28/0x50
[c2107e30] [c0056c30] unmap_vmas+0x1b8/0x510
[c2107eb0] [c005b17c] unmap_region+0x94/0x124
[c2107ef0] [c005c110] do_munmap+0x264/0x2dc
[c2107f20] [c005c1c0] sys_munmap+0x38/0x5c
[c2107f40] [c000d0dc] ret_from_syscall+0x0/0x38

trunk+benh complicated patch:

crashes earlier:

BUG: Bad page map in process swapper  pte:001f88e9 pmd:020d8001
addr:7ffffff6 vm_flags:00100177 anon_vma:c20d95e0 mapping:(null) index:7ffff
Call Trace:
[c341fd20] [c00067d0] show_stack+0x44/0x14c (unreliable)
[c341fd60] [c0056860] print_bad_pte+0x1b4/0x1d0
[c341fd90] [c00568c8] vm_normal_page+0x4c/0x78
[c341fda0] [c0056988] follow_page+0x94/0x1b8
[c341fdc0] [c005854c] __get_user_pages+0x324/0x3c4
[c341fe20] [c006c12c] get_arg_page+0x40/0xac
[c341fe40] [c006c374] copy_strings+0xec/0x1d4
[c341fe80] [c006c47c] copy_strings_kernel+0x20/0x38
[c341fea0] [c006d3cc] do_execve+0x110/0x240
[c341fee0] [c00070c4] sys_execve+0x50/0x7c
[c341ff00] [c000d0dc] ret_from_syscall+0x0/0x38
[c341ffc0] [c00023ac] init_post+0x5c/0x168
[c341ffe0] [c01df22c] kernel_init+0x10c/0x124
[c341fff0] [c000cf3c] kernel_thread+0x4c/0x68

this is running on a MPC 875, and I'm happy to test any patches or
add any debugging code if it helps.

thanks!
/rex

^ permalink raw reply

* Re: [PATCH v2 0/2] cpu: pseries: Offline state framework.
From: Benjamin Herrenschmidt @ 2009-09-24  0:48 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Gautham R Shenoy, Venkatesh Pallipadi, linux-kernel, linuxppc-dev,
	Darrick J. Wong
In-Reply-To: <1251869611.7547.38.camel@twins>

On Wed, 2009-09-02 at 07:33 +0200, Peter Zijlstra wrote:
> 
> I'm still thinking this is a bad idea.
> 
> The OS should only know about online/offline.
> 
> Use the hypervisor interface to deal with the cpu once its offline.
> 
> That is, I think this interface you propose is a layering violation.
> 
I don't quite follow your logic here. This is useful for more than just
hypervisors. For example, take the HV out of the picture for a moment
and imagine that the HW has the ability to offline CPU in various power
levels, with varying latencies to bring them back.

For example, the HW can put them in some low power state where they can
be re-plugged quickly, or can shutdown entire power planes completely,
possibly allowing physical hotplug, but that takes much longer to bring
them back into the pool.

In any case, regarding the pseries case, this is how our hypervisor
works and I don't think we can change it, other than by always going
into the "cede" function and having some weird separate interface in the
arch to then whack them into some different state.

Ben.

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/44x: Fix xmon single step on PowerPC 44x
From: David Gibson @ 2009-09-23 23:22 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1253741674.7103.327.camel@pasglop>

On Thu, Sep 24, 2009 at 07:34:34AM +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2009-09-23 at 09:51 -0400, Josh Boyer wrote:
[snip]
> > +static int do_step(struct pt_regs *regs)
> > +{
> > +	regs->msr |= MSR_DE;
> > +	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
> 
> I'm not sure about setting IDM... Won't that be a problem if you have
> an external debugger connected ?

Not in theory.  It should be possible to set both IDM and EDM
simultaneously.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH] perf_event, powerpc: Fix compilation after big perf_counter rename
From: Michael Ellerman @ 2009-09-23 23:19 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, linux-kernel, linuxppc-dev, Paul Mackerras,
	Linus Torvalds, David S. Miller
In-Reply-To: <20090923124420.GA5525@elte.hu>

[-- Attachment #1: Type: text/plain, Size: 1255 bytes --]

On Wed, 2009-09-23 at 14:44 +0200, Ingo Molnar wrote:
> * Michael Ellerman <michael@ellerman.id.au> wrote:
> 
> > On Tue, 2009-09-22 at 18:00 +1000, Benjamin Herrenschmidt wrote:
> > > On Tue, 2009-09-22 at 09:28 +0200, Ingo Molnar wrote:
> > > > 
> > > > Nevertheless you are right that i should have caught this particular 
> > > > PowerPC build bug - i missed it - sorry about that!
> > > > 
> > > Allright. Well, to help in general, we are setting up a build-bot
> > > here too that will build -tip HEAD for at least powerpc daily with
> > > a few configs too.
> > 
> > Results here:
> > 
> > http://kisskb.ellerman.id.au/kisskb/branch/12/
> 
> ok, seems green for today - the two failures are: one a powerpc 
> toolchain problem it appears, plus a mainline warning.

Yep that looks more or less normal.

> Btw., for me to be able to notice failures there it would have to email 
> me automatically if there's any -tip build failures that do not occur 
> with the upstream branch. Does it have such a feature?

Not really, it sends mails to me, but it doesn't have a way to filter
them by branch. I think the plan is we'll keep an eye on it and either
send you patches or at least let you know that it's broken.

cheers

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

^ permalink raw reply

* RE: [PATCH v3] xilinx_spi: Splitted into generic, of and platform driver, added support for DS570
From: John Linn @ 2009-09-23 22:44 UTC (permalink / raw)
  To: Richard Röjfors
  Cc: spi-devel-general, Andrew Morton, dbrownell, linuxppc-dev
In-Reply-To: <4AB948AB.8080002@mocean-labs.com>

> -----Original Message-----
> From: Richard R=F6jfors [mailto:richard.rojfors@mocean-labs.com]
> Sent: Tuesday, September 22, 2009 3:59 PM
> To: John Linn
> Cc: spi-devel-general@lists.sourceforge.net; linuxppc-dev@ozlabs.org; And=
rew Morton;
> dbrownell@users.sourceforge.net
> Subject: Re: [PATCH v3] xilinx_spi: Splitted into generic, of and platfor=
m driver, added support for
> DS570
> =

> John Linn wrote:
> >> -----Original Message-----
> >> From: linuxppc-dev-bounces+john.linn=3Dxilinx.com@lists.ozlabs.org [ma=
ilto:linuxppc-dev-
> >> bounces+john.linn=3Dxilinx.com@lists.ozlabs.org] On Behalf Of Richard =
R=F6jfors
> >> Sent: Tuesday, September 22, 2009 6:55 AM
> >> To: spi-devel-general@lists.sourceforge.net
> >> Cc: linuxppc-dev@ozlabs.org; Andrew Morton; dbrownell@users.sourceforg=
e.net
> >> Subject: [PATCH v3] xilinx_spi: Splitted into generic, of and platform=
 driver, added support for
> >> DS570
> >>
> >> This patch splits xilinx_spi into three parts, an OF and a platform
> >> driver and generic part.
> >>
> >> The generic part now also works on X86 and also supports the Xilinx
> >> SPI IP DS570
> >
> > Hi Richard,
> =

> Hi John,
> =

> >
> > The current driver (without this change) works for the newer XPS SPI de=
vice already as I run tests
> on it each day using an SPI EEPROM.
> =

> I'm not an expert of the Xilinx SPI blocks, I have only used one, the DS5=
70.
> =

> I don't think you use the DS570. I don't have the datasheet of the older =
one, but the register
> offsets of the DS570 don't match the driver you are using. All the regist=
ers of the DS570 are at 4
> bytes boundries.
> =


I just verified that I am using the same IP block as you are, the DS570. Bu=
t I'm not testing on the other IP you mention, the DS464.

> For instance the Status register of the code (DS464 is at offset 0x67), w=
hile the "Xilinx DS570 XPS
> Serial Peripheral Interface (SPI) (v2.00b), Data Sheet", clearly specifie=
s that the Status register
> offset of the DS570 is 0x64, which also matches the FPGA IP we run.
> =

> >
> > Do you think that's not the case, or it doesn't work for some other typ=
e of devices that I'm not
> testing with?

Did you test with some SPI device that didn't work as I'm using it with an =
SPI EEPROM?

> =

> I think you use some other IP block. Could that be the case?
> =

> >
> > I'll hold off commenting on the rest of the code changes for a bit.
> >
> > Thanks,
> > John
> >
> >> Signed-off-by: Richard R=F6jfors <richard.rojfors.ext@mocean-labs.com>=

> >> ---
> >> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> >> index 2c733c2..eca491b 100644
> >> --- a/drivers/spi/Kconfig
> >> +++ b/drivers/spi/Kconfig
> >> @@ -218,8 +218,8 @@ config SPI_TXX9
> >>  	  SPI driver for Toshiba TXx9 MIPS SoCs
> >>
> >>  config SPI_XILINX
> >> -	tristate "Xilinx SPI controller"
> >> -	depends on (XILINX_VIRTEX || MICROBLAZE) && EXPERIMENTAL
> >> +	tristate "Xilinx SPI controller common module"
> >> +	depends on (XILINX_VIRTEX || MICROBLAZE || HAS_IOMEM) && EXPERIMENTA=
L
> >>  	select SPI_BITBANG
> >>  	help
> >>  	  This exposes the SPI controller IP from the Xilinx EDK.
> >> @@ -227,6 +227,22 @@ config SPI_XILINX
> >>  	  See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
> >>  	  Product Specification document (DS464) for hardware details.
> >>
> >> +	  Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.0=
0b)"
> >> +
> >> +
> >> +config SPI_XILINX_OF
> >> +	tristate "Xilinx SPI controller OF device"
> >> +	depends on SPI_XILINX && XILINX_VIRTEX
> >> +	help
> >> +	  This is the OF driver for the SPI controller IP from the Xilinx ED=
K.
> >> +
> >> +config SPI_XILINX_PLTFM
> >> +	tristate "Xilinx SPI controller platform device"
> >> +	depends on SPI_XILINX
> >> +	help
> >> +	  This is the platform driver for the SPI controller IP
> >> +	  from the Xilinx EDK.
> >> +
> >>  #
> >>  # Add new SPI master controllers in alphabetical order above this lin=
e
> >>  #
> >> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> >> index 3de408d..5a91cf5 100644
> >> --- a/drivers/spi/Makefile
> >> +++ b/drivers/spi/Makefile
> >> @@ -30,6 +30,8 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO)		+=3D spi_s3c24xx_gpi=
o.o
> >>  obj-$(CONFIG_SPI_S3C24XX)		+=3D spi_s3c24xx.o
> >>  obj-$(CONFIG_SPI_TXX9)			+=3D spi_txx9.o
> >>  obj-$(CONFIG_SPI_XILINX)		+=3D xilinx_spi.o
> >> +obj-$(CONFIG_SPI_XILINX_OF)		+=3D xilinx_spi_of.o
> >> +obj-$(CONFIG_SPI_XILINX_PLTFM)		+=3D xilinx_spi_pltfm.o
> >>  obj-$(CONFIG_SPI_SH_SCI)		+=3D spi_sh_sci.o
> >>  # 	... add above this line ...
> >>
> >> diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
> >> index 46b8c5c..0490820 100644
> >> --- a/drivers/spi/xilinx_spi.c
> >> +++ b/drivers/spi/xilinx_spi.c
> >> @@ -14,22 +14,103 @@
> >>  #include <linux/module.h>
> >>  #include <linux/init.h>
> >>  #include <linux/interrupt.h>
> >> -#include <linux/platform_device.h>
> >> -
> >> -#include <linux/of_platform.h>
> >> -#include <linux/of_device.h>
> >> -#include <linux/of_spi.h>
> >>
> >>  #include <linux/spi/spi.h>
> >>  #include <linux/spi/spi_bitbang.h>
> >>  #include <linux/io.h>
> >>
> >> -#define XILINX_SPI_NAME "xilinx_spi"
> >> +#include "xilinx_spi.h"
> >> +
> >> +struct xilinx_spi {
> >> +	/* bitbang has to be first */
> >> +	struct spi_bitbang bitbang;
> >> +	struct completion done;
> >> +	struct resource mem; /* phys mem */
> >> +	void __iomem	*regs;	/* virt. address of the control registers */
> >> +	u32 irq;
> >> +	u8 *rx_ptr;		/* pointer in the Tx buffer */
> >> +	const u8 *tx_ptr;	/* pointer in the Rx buffer */
> >> +	int remaining_bytes;	/* the number of bytes left to transfer */
> >> +	/* offset to the XSPI regs, these might vary... */
> >> +	u8 cr_offset;
> >> +	u8 sr_offset;
> >> +	u8 txd_offset;
> >> +	u8 rxd_offset;
> >> +	u8 ssr_offset;
> >> +	u8 bits_per_word;
> >> +	u8 model;
> >> +};
> >> +
> >> +#ifdef CONFIG_X86
> >> +/* on X86 the block often resides behind a PCI(e) interface which fli=
ps the
> >> + * endian from little to big
> >> + */
> >> +#define xspi_in8(addr) ioread8(addr)
> >> +#define xspi_in16(addr) ioread16(addr)
> >> +#define xspi_in32(addr) ioread32(addr)
> >> +
> >> +#define xspi_out8(addr, b) iowrite8(b, addr)
> >> +#define xspi_out16(addr, w) iowrite16(w, addr)
> >> +#define xspi_out32(addr, l) iowrite32(l, addr)
> >> +#else
> >> +/* While on for instance PPC we use big endian */
> >> +#define xspi_in8(addr) in_8(addr)
> >> +#define xspi_in16(addr) in_be16(addr)
> >> +#define xspi_in32(addr) in_be32(addr)
> >> +
> >> +#define xspi_out8(addr, b) out_8(addr, b)
> >> +#define xspi_out16(addr, w) out_be16(addr, w)
> >> +#define xspi_out32(addr, l) out_be32(addr, l)
> >> +#endif
> >> +
> >> +
> >> +static inline void xspi_write8(struct xilinx_spi *xspi, u32 offs, u8 =
val)
> >> +{
> >> +	if (xspi->model =3D=3D XILINX_SPI_MODEL_DS464)
> >> +		xspi_out8(xspi->regs + offs, val & 0xff);
> >> +	else
> >> +		xspi_out32(xspi->regs + offs, val);
> >> +}
> >> +
> >> +static inline void xspi_write16(struct xilinx_spi *xspi, u32 offs, u1=
6 val)
> >> +{
> >> +	if (xspi->model =3D=3D XILINX_SPI_MODEL_DS464)
> >> +		xspi_out16(xspi->regs + offs, val & 0xffff);
> >> +	else
> >> +		xspi_out32(xspi->regs + offs, val);
> >> +}
> >> +
> >> +static inline void xspi_write32(struct xilinx_spi *xspi, u32 offs, u3=
2 val)
> >> +{
> >> +	xspi_out32(xspi->regs + offs, val);
> >> +}
> >> +
> >> +static inline u8 xspi_read8(struct xilinx_spi *xspi, u32 offs)
> >> +{
> >> +	if (xspi->model =3D=3D XILINX_SPI_MODEL_DS464)
> >> +		return xspi_in8(xspi->regs + offs);
> >> +	else
> >> +		return xspi_in32(xspi->regs + offs);
> >> +}
> >> +
> >> +static inline u16 xspi_read16(struct xilinx_spi *xspi, u32 offs)
> >> +{
> >> +	if (xspi->model =3D=3D XILINX_SPI_MODEL_DS464)
> >> +		return xspi_in16(xspi->regs + offs);
> >> +	else
> >> +		return xspi_in32(xspi->regs + offs);
> >> +}
> >> +
> >> +static inline u32 xspi_read32(struct xilinx_spi *xspi, u32 offs)
> >> +{
> >> +	return xspi_in32(xspi->regs + offs);
> >> +}
> >>
> >>  /* Register definitions as per "OPB Serial Peripheral Interface (SPI)=
 (v1.00e)
> >>   * Product Specification", DS464
> >>   */
> >> -#define XSPI_CR_OFFSET		0x62	/* 16-bit Control Register */
> >> +#define XSPI_CR_OFFSET_DS464	0x62	/* 16-bit Control Register */
> >> +#define XSPI_CR_OFFSET_DS570	0x60
> >>
> >>  #define XSPI_CR_ENABLE		0x02
> >>  #define XSPI_CR_MASTER_MODE	0x04
> >> @@ -40,8 +121,10 @@
> >>  #define XSPI_CR_RXFIFO_RESET	0x40
> >>  #define XSPI_CR_MANUAL_SSELECT	0x80
> >>  #define XSPI_CR_TRANS_INHIBIT	0x100
> >> +#define XSPI_CR_LSB_FIRST	0x200
> >>
> >> -#define XSPI_SR_OFFSET		0x67	/* 8-bit Status Register */
> >> +#define XSPI_SR_OFFSET_DS464	0x67	/* 8-bit Status Register */
> >> +#define XSPI_SR_OFFSET_DS570	0x64
> >>
> >>  #define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
> >>  #define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
> >> @@ -49,10 +132,13 @@
> >>  #define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
> >>  #define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
> >>
> >> -#define XSPI_TXD_OFFSET		0x6b	/* 8-bit Data Transmit Register */
> >> -#define XSPI_RXD_OFFSET		0x6f	/* 8-bit Data Receive Register */
> >> +#define XSPI_TXD_OFFSET_DS464	0x6b	/* 8-bit Data Transmit Register */=

> >> +#define XSPI_TXD_OFFSET_DS570	0x68
> >> +#define XSPI_RXD_OFFSET_DS464	0x6f	/* 8-bit Data Receive Register */
> >> +#define XSPI_RXD_OFFSET_DS570	0x6C
> >>
> >> -#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
> >> +#define XSPI_SSR_OFFSET_DS464	0x70	/* 32-bit Slave Select Register */=

> >> +#define XSPI_SSR_OFFSET_DS570	0x70
> >>
> >>  /* Register definitions as per "OPB IPIF (v3.01c) Product Specificati=
on", DS414
> >>   * IPIF registers are 32 bit
> >> @@ -70,43 +156,27 @@
> >>  #define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
> >>  #define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
> >>  #define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
> >> +#define XSPI_INTR_TX_HALF_EMPTY		0x40	/* TxFIFO is half empty */
> >>
> >>  #define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
> >>  #define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
> >>
> >> -struct xilinx_spi {
> >> -	/* bitbang has to be first */
> >> -	struct spi_bitbang bitbang;
> >> -	struct completion done;
> >> -
> >> -	void __iomem	*regs;	/* virt. address of the control registers */
> >> -
> >> -	u32		irq;
> >> -
> >> -	u32		speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
> >> -
> >> -	u8 *rx_ptr;		/* pointer in the Tx buffer */
> >> -	const u8 *tx_ptr;	/* pointer in the Rx buffer */
> >> -	int remaining_bytes;	/* the number of bytes left to transfer */
> >> -};
> >> -
> >> -static void xspi_init_hw(void __iomem *regs_base)
> >> +static void xspi_init_hw(struct xilinx_spi *xspi)
> >>  {
> >>  	/* Reset the SPI device */
> >> -	out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
> >> -		 XIPIF_V123B_RESET_MASK);
> >> +	xspi_write32(xspi, XIPIF_V123B_RESETR_OFFSET, XIPIF_V123B_RESET_MASK=
);
> >>  	/* Disable all the interrupts just in case */
> >> -	out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0);
> >> +	xspi_write32(xspi, XIPIF_V123B_IIER_OFFSET, 0);
> >>  	/* Enable the global IPIF interrupt */
> >> -	out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
> >> -		 XIPIF_V123B_GINTR_ENABLE);
> >> +	xspi_write32(xspi, XIPIF_V123B_DGIER_OFFSET, XIPIF_V123B_GINTR_ENABL=
E);
> >>  	/* Deselect the slave on the SPI bus */
> >> -	out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
> >> +	xspi_write32(xspi, xspi->ssr_offset, 0xffff);
> >>  	/* Disable the transmitter, enable Manual Slave Select Assertion,
> >>  	 * put SPI controller into master mode, and enable it */
> >> -	out_be16(regs_base + XSPI_CR_OFFSET,
> >> -		 XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
> >> -		 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
> >> +	xspi_write16(xspi, xspi->cr_offset,
> >> +		 XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
> >> +		 XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
> >> +		 XSPI_CR_RXFIFO_RESET);
> >>  }
> >>
> >>  static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
> >> @@ -115,16 +185,16 @@ static void xilinx_spi_chipselect(struct spi_dev=
ice *spi, int is_on)
> >>
> >>  	if (is_on =3D=3D BITBANG_CS_INACTIVE) {
> >>  		/* Deselect the slave on the SPI bus */
> >> -		out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
> >> +		xspi_write32(xspi, xspi->ssr_offset, 0xffff);
> >>  	} else if (is_on =3D=3D BITBANG_CS_ACTIVE) {
> >>  		/* Set the SPI clock phase and polarity */
> >> -		u16 cr =3D in_be16(xspi->regs + XSPI_CR_OFFSET)
> >> +		u32 cr =3D xspi_read16(xspi, xspi->cr_offset)
> >>  			 & ~XSPI_CR_MODE_MASK;
> >>  		if (spi->mode & SPI_CPHA)
> >>  			cr |=3D XSPI_CR_CPHA;
> >>  		if (spi->mode & SPI_CPOL)
> >>  			cr |=3D XSPI_CR_CPOL;
> >> -		out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
> >> +		xspi_write16(xspi, xspi->cr_offset, cr);
> >>
> >>  		/* We do not check spi->max_speed_hz here as the SPI clock
> >>  		 * frequency is not software programmable (the IP block design
> >> @@ -132,24 +202,27 @@ static void xilinx_spi_chipselect(struct spi_dev=
ice *spi, int is_on)
> >>  		 */
> >>
> >>  		/* Activate the chip select */
> >> -		out_be32(xspi->regs + XSPI_SSR_OFFSET,
> >> +		xspi_write32(xspi, xspi->ssr_offset,
> >>  			 ~(0x0001 << spi->chip_select));
> >>  	}
> >>  }
> >>
> >>  /* spi_bitbang requires custom setup_transfer() to be defined if ther=
e is a
> >>   * custom txrx_bufs(). We have nothing to setup here as the SPI IP bl=
ock
> >> - * supports just 8 bits per word, and SPI clock can't be changed in s=
oftware.
> >> - * Check for 8 bits per word. Chip select delay calculations could be=

> >> + * supports 8 or 16 bits per word, which can not be changed in softwa=
re.
> >> + * SPI clock can't be changed in software.
> >> + * Check for correct bits per word. Chip select delay calculations co=
uld be
> >>   * added here as soon as bitbang_work() can be made aware of the dela=
y value.
> >>   */
> >>  static int xilinx_spi_setup_transfer(struct spi_device *spi,
> >> -		struct spi_transfer *t)
> >> +	struct spi_transfer *t)
> >>  {
> >>  	u8 bits_per_word;
> >> +	struct xilinx_spi *xspi =3D spi_master_get_devdata(spi->master);
> >>
> >> -	bits_per_word =3D (t) ? t->bits_per_word : spi->bits_per_word;
> >> -	if (bits_per_word !=3D 8) {
> >> +	bits_per_word =3D (t->bits_per_word) ? t->bits_per_word :
> >> +		spi->bits_per_word;
> >> +	if (bits_per_word !=3D xspi->bits_per_word) {
> >>  		dev_err(&spi->dev, "%s, unsupported bits_per_word=3D%d\n",
> >>  			__func__, bits_per_word);
> >>  		return -EINVAL;
> >> @@ -160,34 +233,50 @@ static int xilinx_spi_setup_transfer(struct spi_=
device *spi,
> >>
> >>  static int xilinx_spi_setup(struct spi_device *spi)
> >>  {
> >> -	struct spi_bitbang *bitbang;
> >> -	struct xilinx_spi *xspi;
> >> -	int retval;
> >> -
> >> -	xspi =3D spi_master_get_devdata(spi->master);
> >> -	bitbang =3D &xspi->bitbang;
> >> -
> >> -	retval =3D xilinx_spi_setup_transfer(spi, NULL);
> >> -	if (retval < 0)
> >> -		return retval;
> >> -
> >> +	/* always return 0, we can not check the number of bits.
> >> +	 * There are cases when SPI setup is called before any driver is
> >> +	 * there, in that case the SPI core defaults to 8 bits, which we
> >> +	 * do not support in some cases. But if we return an error, the
> >> +	 * SPI device would not be registered and no driver can get hold of =
it
> >> +	 * When the driver is there, it will call SPI setup again with the
> >> +	 * correct number of bits per transfer.
> >> +	 * If a driver setups with the wrong bit number, it will fail when
> >> +	 * it tries to do a transfer
> >> +	 */
> >>  	return 0;
> >>  }
> >>
> >>  static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
> >>  {
> >> -	u8 sr;
> >> +	u32 sr;
> >> +	u8 wsize;
> >> +	if (xspi->bits_per_word =3D=3D 8)
> >> +		wsize =3D 1;
> >> +	else if (xspi->bits_per_word =3D=3D 16)
> >> +		wsize =3D 2;
> >> +	else
> >> +		wsize =3D 4;
> >>
> >>  	/* Fill the Tx FIFO with as many bytes as possible */
> >> -	sr =3D in_8(xspi->regs + XSPI_SR_OFFSET);
> >> -	while ((sr & XSPI_SR_TX_FULL_MASK) =3D=3D 0 && xspi->remaining_bytes=
 > 0) {
> >> +	sr =3D xspi_read8(xspi, xspi->sr_offset);
> >> +	while ((sr & XSPI_SR_TX_FULL_MASK) =3D=3D 0 &&
> >> +		xspi->remaining_bytes > 0) {
> >>  		if (xspi->tx_ptr) {
> >> -			out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
> >> -		} else {
> >> -			out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
> >> -		}
> >> -		xspi->remaining_bytes--;
> >> -		sr =3D in_8(xspi->regs + XSPI_SR_OFFSET);
> >> +			if (wsize =3D=3D 1)
> >> +				xspi_write8(xspi, xspi->txd_offset,
> >> +					*xspi->tx_ptr);
> >> +			else if (wsize =3D=3D 2)
> >> +				xspi_write16(xspi, xspi->txd_offset,
> >> +					*(u16 *)(xspi->tx_ptr));
> >> +			else if (wsize =3D=3D 4)
> >> +				xspi_write32(xspi, xspi->txd_offset,
> >> +					*(u32 *)(xspi->tx_ptr));
> >> +
> >> +			xspi->tx_ptr +=3D wsize;
> >> +		} else
> >> +			xspi_write8(xspi, xspi->txd_offset, 0);
> >> +		xspi->remaining_bytes -=3D wsize;
> >> +		sr =3D xspi_read8(xspi, xspi->sr_offset);
> >>  	}
> >>  }
> >>
> >> @@ -195,7 +284,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device =
*spi, struct spi_transfer
> *t)
> >>  {
> >>  	struct xilinx_spi *xspi =3D spi_master_get_devdata(spi->master);
> >>  	u32 ipif_ier;
> >> -	u16 cr;
> >> +	u32 cr;
> >>
> >>  	/* We get here with transmitter inhibited */
> >>
> >> @@ -209,23 +298,22 @@ static int xilinx_spi_txrx_bufs(struct spi_devic=
e *spi, struct spi_transfer
> *t)
> >>  	/* Enable the transmit empty interrupt, which we use to determine
> >>  	 * progress on the transmission.
> >>  	 */
> >> -	ipif_ier =3D in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET);
> >> -	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET,
> >> +	ipif_ier =3D xspi_read32(xspi, XIPIF_V123B_IIER_OFFSET);
> >> +	xspi_write32(xspi, XIPIF_V123B_IIER_OFFSET,
> >>  		 ipif_ier | XSPI_INTR_TX_EMPTY);
> >>
> >>  	/* Start the transfer by not inhibiting the transmitter any longer *=
/
> >> -	cr =3D in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT=
;
> >> -	out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
> >> +	cr =3D xspi_read16(xspi, xspi->cr_offset) & ~XSPI_CR_TRANS_INHIBIT;
> >> +	xspi_write16(xspi, xspi->cr_offset, cr);
> >>
> >>  	wait_for_completion(&xspi->done);
> >>
> >>  	/* Disable the transmit empty interrupt */
> >> -	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier);
> >> +	xspi_write32(xspi, XIPIF_V123B_IIER_OFFSET, ipif_ier);
> >>
> >>  	return t->len - xspi->remaining_bytes;
> >>  }
> >>
> >> -
> >>  /* This driver supports single master mode only. Hence Tx FIFO Empty
> >>   * is the only interrupt we care about.
> >>   * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slav=
e Mode
> >> @@ -237,32 +325,50 @@ static irqreturn_t xilinx_spi_irq(int irq, void =
*dev_id)
> >>  	u32 ipif_isr;
> >>
> >>  	/* Get the IPIF interrupts, and clear them immediately */
> >> -	ipif_isr =3D in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
> >> -	out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);
> >> +	ipif_isr =3D xspi_read32(xspi, XIPIF_V123B_IISR_OFFSET);
> >> +	xspi_write32(xspi, XIPIF_V123B_IISR_OFFSET, ipif_isr);
> >>
> >>  	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
> >> -		u16 cr;
> >> -		u8 sr;
> >> +		u32 cr;
> >> +		u32 sr;
> >> +		u8 rsize;
> >> +		if (xspi->bits_per_word =3D=3D 8)
> >> +			rsize =3D 1;
> >> +		else if (xspi->bits_per_word =3D=3D 16)
> >> +			rsize =3D 2;
> >> +		else
> >> +			rsize =3D 4;
> >>
> >>  		/* A transmit has just completed. Process received data and
> >>  		 * check for more data to transmit. Always inhibit the
> >>  		 * transmitter while the Isr refills the transmit register/FIFO,
> >>  		 * or make sure it is stopped if we're done.
> >>  		 */
> >> -		cr =3D in_be16(xspi->regs + XSPI_CR_OFFSET);
> >> -		out_be16(xspi->regs + XSPI_CR_OFFSET,
> >> -			 cr | XSPI_CR_TRANS_INHIBIT);
> >> +		cr =3D xspi_read16(xspi, xspi->cr_offset);
> >> +		xspi_write16(xspi, xspi->cr_offset, cr | XSPI_CR_TRANS_INHIBIT);
> >>
> >>  		/* Read out all the data from the Rx FIFO */
> >> -		sr =3D in_8(xspi->regs + XSPI_SR_OFFSET);
> >> +		sr =3D xspi_read8(xspi, xspi->sr_offset);
> >>  		while ((sr & XSPI_SR_RX_EMPTY_MASK) =3D=3D 0) {
> >> -			u8 data;
> >> +			u32 data;
> >> +			if (rsize =3D=3D 1)
> >> +				data =3D xspi_read8(xspi, xspi->rxd_offset);
> >> +			else if (rsize =3D=3D 2)
> >> +				data =3D xspi_read16(xspi, xspi->rxd_offset);
> >> +			else
> >> +				data =3D xspi_read32(xspi, xspi->rxd_offset);
> >>
> >> -			data =3D in_8(xspi->regs + XSPI_RXD_OFFSET);
> >>  			if (xspi->rx_ptr) {
> >> -				*xspi->rx_ptr++ =3D data;
> >> +				if (rsize =3D=3D 1)
> >> +					*xspi->rx_ptr =3D data & 0xff;
> >> +				else if (rsize =3D=3D 2)
> >> +					*(u16 *)(xspi->rx_ptr) =3D data & 0xffff;
> >> +				else
> >> +					*((u32 *)(xspi->rx_ptr)) =3D data;
> >> +				xspi->rx_ptr +=3D rsize;
> >>  			}
> >> -			sr =3D in_8(xspi->regs + XSPI_SR_OFFSET);
> >> +
> >> +			sr =3D xspi_read8(xspi, xspi->sr_offset);
> >>  		}
> >>
> >>  		/* See if there is more data to send */
> >> @@ -271,7 +377,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *d=
ev_id)
> >>  			/* Start the transfer by not inhibiting the
> >>  			 * transmitter any longer
> >>  			 */
> >> -			out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
> >> +			xspi_write16(xspi, xspi->cr_offset, cr);
> >>  		} else {
> >>  			/* No more data to send.
> >>  			 * Indicate the transfer is completed.
> >> @@ -279,44 +385,20 @@ static irqreturn_t xilinx_spi_irq(int irq, void =
*dev_id)
> >>  			complete(&xspi->done);
> >>  		}
> >>  	}
> >> -
> >>  	return IRQ_HANDLED;
> >>  }
> >>
> >> -static int __init xilinx_spi_of_probe(struct of_device *ofdev,
> >> -					const struct of_device_id *match)
> >> +struct spi_master *xilinx_spi_init(struct device *dev, struct resourc=
e *mem,
> >> +	u32 irq, u8 model, s16 bus_num, u16 num_chipselect, u8 bits_per_word=
)
> >>  {
> >>  	struct spi_master *master;
> >>  	struct xilinx_spi *xspi;
> >> -	struct resource r_irq_struct;
> >> -	struct resource r_mem_struct;
> >> +	int ret =3D 0;
> >>
> >> -	struct resource *r_irq =3D &r_irq_struct;
> >> -	struct resource *r_mem =3D &r_mem_struct;
> >> -	int rc =3D 0;
> >> -	const u32 *prop;
> >> -	int len;
> >> +	master =3D spi_alloc_master(dev, sizeof(struct xilinx_spi));
> >>
> >> -	/* Get resources(memory, IRQ) associated with the device */
> >> -	master =3D spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));=

> >> -
> >> -	if (master =3D=3D NULL) {
> >> -		return -ENOMEM;
> >> -	}
> >> -
> >> -	dev_set_drvdata(&ofdev->dev, master);
> >> -
> >> -	rc =3D of_address_to_resource(ofdev->node, 0, r_mem);
> >> -	if (rc) {
> >> -		dev_warn(&ofdev->dev, "invalid address\n");
> >> -		goto put_master;
> >> -	}
> >> -
> >> -	rc =3D of_irq_to_resource(ofdev->node, 0, r_irq);
> >> -	if (rc =3D=3D NO_IRQ) {
> >> -		dev_warn(&ofdev->dev, "no IRQ found\n");
> >> -		goto put_master;
> >> -	}
> >> +	if (master =3D=3D NULL)
> >> +		return ERR_PTR(-ENOMEM);
> >>
> >>  	/* the spi->mode bits understood by this driver: */
> >>  	master->mode_bits =3D SPI_CPOL | SPI_CPHA;
> >> @@ -329,128 +411,87 @@ static int __init xilinx_spi_of_probe(struct of=
_device *ofdev,
> >>  	xspi->bitbang.master->setup =3D xilinx_spi_setup;
> >>  	init_completion(&xspi->done);
> >>
> >> -	xspi->irq =3D r_irq->start;
> >> -
> >> -	if (!request_mem_region(r_mem->start,
> >> -			r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
> >> -		rc =3D -ENXIO;
> >> -		dev_warn(&ofdev->dev, "memory request failure\n");
> >> +	if (!request_mem_region(mem->start, resource_size(mem),
> >> +		XILINX_SPI_NAME)) {
> >> +		ret =3D -ENXIO;
> >>  		goto put_master;
> >>  	}
> >>
> >> -	xspi->regs =3D ioremap(r_mem->start, r_mem->end - r_mem->start + 1);=

> >> +	xspi->regs =3D ioremap(mem->start, resource_size(mem));
> >>  	if (xspi->regs =3D=3D NULL) {
> >> -		rc =3D -ENOMEM;
> >> -		dev_warn(&ofdev->dev, "ioremap failure\n");
> >> -		goto release_mem;
> >> +		ret =3D -ENOMEM;
> >> +		dev_warn(dev, "ioremap failure\n");
> >> +		goto map_failed;
> >>  	}
> >> -	xspi->irq =3D r_irq->start;
> >> -
> >> -	/* dynamic bus assignment */
> >> -	master->bus_num =3D -1;
> >>
> >> -	/* number of slave select bits is required */
> >> -	prop =3D of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
> >> -	if (!prop || len < sizeof(*prop)) {
> >> -		dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
> >> -		goto unmap_io;
> >> +	master->bus_num =3D bus_num;
> >> +	master->num_chipselect =3D num_chipselect;
> >> +
> >> +	xspi->mem =3D *mem;
> >> +	xspi->irq =3D irq;
> >> +	xspi->bits_per_word =3D bits_per_word;
> >> +	xspi->model =3D model;
> >> +
> >> +	if (model =3D=3D XILINX_SPI_MODEL_DS464) {
> >> +		xspi->cr_offset =3D XSPI_CR_OFFSET_DS464;
> >> +		xspi->sr_offset =3D XSPI_SR_OFFSET_DS464;
> >> +		xspi->txd_offset =3D XSPI_TXD_OFFSET_DS464;
> >> +		xspi->rxd_offset =3D XSPI_RXD_OFFSET_DS464;
> >> +		xspi->ssr_offset =3D XSPI_SSR_OFFSET_DS464;
> >> +	} else {
> >> +		xspi->cr_offset =3D XSPI_CR_OFFSET_DS570;
> >> +		xspi->sr_offset =3D XSPI_SR_OFFSET_DS570;
> >> +		xspi->txd_offset =3D XSPI_TXD_OFFSET_DS570;
> >> +		xspi->rxd_offset =3D XSPI_RXD_OFFSET_DS570;
> >> +		xspi->ssr_offset =3D XSPI_SSR_OFFSET_DS570;
> >>  	}
> >> -	master->num_chipselect =3D *prop;
> >>
> >>  	/* SPI controller initializations */
> >> -	xspi_init_hw(xspi->regs);
> >> +	xspi_init_hw(xspi);
> >>
> >>  	/* Register for SPI Interrupt */
> >> -	rc =3D request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xs=
pi);
> >> -	if (rc !=3D 0) {
> >> -		dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
> >> +	ret =3D request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, x=
spi);
> >> +	if (ret !=3D 0)
> >>  		goto unmap_io;
> >> -	}
> >>
> >> -	rc =3D spi_bitbang_start(&xspi->bitbang);
> >> -	if (rc !=3D 0) {
> >> -		dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
> >> +	ret =3D spi_bitbang_start(&xspi->bitbang);
> >> +	if (ret !=3D 0) {
> >> +		dev_err(dev, "spi_bitbang_start FAILED\n");
> >>  		goto free_irq;
> >>  	}
> >>
> >> -	dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=3D%d\n",
> >> -			(unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
> >> -
> >> -	/* Add any subnodes on the SPI bus */
> >> -	of_register_spi_devices(master, ofdev->node);
> >> -
> >> -	return rc;
> >> +	dev_info(dev, "at 0x%08X mapped to 0x%08X, irq=3D%d\n",
> >> +		(u32)mem->start, (u32)xspi->regs, xspi->irq);
> >> +	return master;
> >>
> >>  free_irq:
> >>  	free_irq(xspi->irq, xspi);
> >>  unmap_io:
> >>  	iounmap(xspi->regs);
> >> -release_mem:
> >> -	release_mem_region(r_mem->start, resource_size(r_mem));
> >> +map_failed:
> >> +	release_mem_region(mem->start, resource_size(mem));
> >>  put_master:
> >>  	spi_master_put(master);
> >> -	return rc;
> >> +	return ERR_PTR(ret);
> >>  }
> >> +EXPORT_SYMBOL(xilinx_spi_init);
> >>
> >> -static int __devexit xilinx_spi_remove(struct of_device *ofdev)
> >> +void xilinx_spi_deinit(struct spi_master *master)
> >>  {
> >>  	struct xilinx_spi *xspi;
> >> -	struct spi_master *master;
> >> -	struct resource r_mem;
> >>
> >> -	master =3D platform_get_drvdata(ofdev);
> >>  	xspi =3D spi_master_get_devdata(master);
> >>
> >>  	spi_bitbang_stop(&xspi->bitbang);
> >>  	free_irq(xspi->irq, xspi);
> >>  	iounmap(xspi->regs);
> >> -	if (!of_address_to_resource(ofdev->node, 0, &r_mem))
> >> -		release_mem_region(r_mem.start, resource_size(&r_mem));
> >> -	dev_set_drvdata(&ofdev->dev, 0);
> >> -	spi_master_put(xspi->bitbang.master);
> >> -
> >> -	return 0;
> >> -}
> >> -
> >> -/* work with hotplug and coldplug */
> >> -MODULE_ALIAS("platform:" XILINX_SPI_NAME);
> >> -
> >> -static int __exit xilinx_spi_of_remove(struct of_device *op)
> >> -{
> >> -	return xilinx_spi_remove(op);
> >> -}
> >> -
> >> -static struct of_device_id xilinx_spi_of_match[] =3D {
> >> -	{ .compatible =3D "xlnx,xps-spi-2.00.a", },
> >> -	{ .compatible =3D "xlnx,xps-spi-2.00.b", },
> >> -	{}
> >> -};
> >> -
> >> -MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
> >> -
> >> -static struct of_platform_driver xilinx_spi_of_driver =3D {
> >> -	.owner =3D THIS_MODULE,
> >> -	.name =3D "xilinx-xps-spi",
> >> -	.match_table =3D xilinx_spi_of_match,
> >> -	.probe =3D xilinx_spi_of_probe,
> >> -	.remove =3D __exit_p(xilinx_spi_of_remove),
> >> -	.driver =3D {
> >> -		.name =3D "xilinx-xps-spi",
> >> -		.owner =3D THIS_MODULE,
> >> -	},
> >> -};
> >>
> >> -static int __init xilinx_spi_init(void)
> >> -{
> >> -	return of_register_platform_driver(&xilinx_spi_of_driver);
> >> +	release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
> >> +	spi_master_put(xspi->bitbang.master);
> >>  }
> >> -module_init(xilinx_spi_init);
> >> +EXPORT_SYMBOL(xilinx_spi_deinit);
> >>
> >> -static void __exit xilinx_spi_exit(void)
> >> -{
> >> -	of_unregister_platform_driver(&xilinx_spi_of_driver);
> >> -}
> >> -module_exit(xilinx_spi_exit);
> >>  MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
> >>  MODULE_DESCRIPTION("Xilinx SPI driver");
> >>  MODULE_LICENSE("GPL");
> >> +
> >> diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h
> >> new file mode 100644
> >> index 0000000..d951b11
> >> --- /dev/null
> >> +++ b/drivers/spi/xilinx_spi.h
> >> @@ -0,0 +1,32 @@
> >> +/*
> >> + * xilinx_spi.h
> >> + * Copyright (c) 2009 Intel Corporation
> >> + *
> >> + * This program is free software; you can redistribute it and/or modi=
fy
> >> + * it under the terms of the GNU General Public License version 2 as
> >> + * published by the Free Software Foundation.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program; if not, write to the Free Software
> >> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >> + */
> >> +
> >> +#ifndef _XILINX_SPI_H_
> >> +#define _XILINX_SPI_H_ 1
> >> +
> >> +#include <linux/spi/spi.h>
> >> +#include <linux/spi/spi_bitbang.h>
> >> +#include <linux/spi/xilinx_spi.h>
> >> +
> >> +#define XILINX_SPI_NAME "xilinx_spi"
> >> +
> >> +struct spi_master *xilinx_spi_init(struct device *dev, struct resourc=
e *mem,
> >> +	u32 irq, u8 model, s16 bus_num, u16 num_chipselect, u8 bits_per_word=
);
> >> +
> >> +void xilinx_spi_deinit(struct spi_master *master);
> >> +#endif
> >> diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c=

> >> new file mode 100644
> >> index 0000000..4f54ddd
> >> --- /dev/null
> >> +++ b/drivers/spi/xilinx_spi_of.c
> >> @@ -0,0 +1,120 @@
> >> +/*
> >> + * xilinx_spi_of.c
> >> + *
> >> + * Xilinx SPI controller driver (master mode only)
> >> + *
> >> + * Author: MontaVista Software, Inc.
> >> + *	source@mvista.com
> >> + *
> >> + * 2002-2007 (c) MontaVista Software, Inc.  This file is licensed und=
er the
> >> + * terms of the GNU General Public License version 2.  This program i=
s licensed
> >> + * "as is" without any warranty of any kind, whether express or impli=
ed.
> >> + */
> >> +
> >> +#include <linux/module.h>
> >> +#include <linux/init.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/platform_device.h>
> >> +
> >> +#include <linux/of_platform.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/of_spi.h>
> >> +
> >> +#include <linux/spi/spi.h>
> >> +#include <linux/spi/spi_bitbang.h>
> >> +
> >> +#include "xilinx_spi.h"
> >> +
> >> +
> >> +static int __init xilinx_spi_of_probe(struct of_device *ofdev,
> >> +					const struct of_device_id *match)
> >> +{
> >> +	struct resource r_irq_struct;
> >> +	struct resource r_mem_struct;
> >> +	struct spi_master *master;
> >> +
> >> +	struct resource *r_irq =3D &r_irq_struct;
> >> +	struct resource *r_mem =3D &r_mem_struct;
> >> +	int rc =3D 0;
> >> +	const u32 *prop;
> >> +	int len;
> >> +
> >> +	rc =3D of_address_to_resource(ofdev->node, 0, r_mem);
> >> +	if (rc) {
> >> +		dev_warn(&ofdev->dev, "invalid address\n");
> >> +		return rc;
> >> +	}
> >> +
> >> +	rc =3D of_irq_to_resource(ofdev->node, 0, r_irq);
> >> +	if (rc =3D=3D NO_IRQ) {
> >> +		dev_warn(&ofdev->dev, "no IRQ found\n");
> >> +		return -ENODEV;
> >> +	}
> >> +
> >> +	/* number of slave select bits is required */
> >> +	prop =3D of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
> >> +	if (!prop || len < sizeof(*prop)) {
> >> +		dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
> >> +		return -EINVAL;
> >> +	}
> >> +	master =3D xilinx_spi_init(&ofdev->dev, r_mem, r_irq->start,
> >> +		XILINX_SPI_MODEL_DS464, -1, *prop, 8);
> >> +	if (IS_ERR(master))
> >> +		return PTR_ERR(master);
> >> +
> >> +	dev_set_drvdata(&ofdev->dev, master);
> >> +
> >> +	/* Add any subnodes on the SPI bus */
> >> +	of_register_spi_devices(master, ofdev->node);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int __devexit xilinx_spi_remove(struct of_device *ofdev)
> >> +{
> >> +	xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev));
> >> +	dev_set_drvdata(&ofdev->dev, 0);
> >> +	return 0;
> >> +}
> >> +
> >> +static int __exit xilinx_spi_of_remove(struct of_device *op)
> >> +{
> >> +	return xilinx_spi_remove(op);
> >> +}
> >> +
> >> +static struct of_device_id xilinx_spi_of_match[] =3D {
> >> +	{ .compatible =3D "xlnx,xps-spi-2.00.a", },
> >> +	{ .compatible =3D "xlnx,xps-spi-2.00.b", },
> >> +	{}
> >> +};
> >> +
> >> +MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
> >> +
> >> +static struct of_platform_driver xilinx_spi_of_driver =3D {
> >> +	.owner =3D THIS_MODULE,
> >> +	.name =3D "xilinx-xps-spi",
> >> +	.match_table =3D xilinx_spi_of_match,
> >> +	.probe =3D xilinx_spi_of_probe,
> >> +	.remove =3D __exit_p(xilinx_spi_of_remove),
> >> +	.driver =3D {
> >> +		.name =3D "xilinx-xps-spi",
> >> +		.owner =3D THIS_MODULE,
> >> +	},
> >> +};
> >> +
> >> +static int __init xilinx_spi_of_init(void)
> >> +{
> >> +	return of_register_platform_driver(&xilinx_spi_of_driver);
> >> +}
> >> +module_init(xilinx_spi_of_init);
> >> +
> >> +static void __exit xilinx_spi_of_exit(void)
> >> +{
> >> +	of_unregister_platform_driver(&xilinx_spi_of_driver);
> >> +}
> >> +module_exit(xilinx_spi_of_exit);
> >> +MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
> >> +MODULE_DESCRIPTION("Xilinx SPI driver");
> >> +MODULE_LICENSE("GPL");
> >> +
> >> diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_p=
ltfm.c
> >> new file mode 100644
> >> index 0000000..d59d509
> >> --- /dev/null
> >> +++ b/drivers/spi/xilinx_spi_pltfm.c
> >> @@ -0,0 +1,104 @@
> >> +/*
> >> + * xilinx_spi_pltfm.c Support for Xilinx SPI platform devices
> >> + * Copyright (c) 2009 Intel Corporation
> >> + *
> >> + * This program is free software; you can redistribute it and/or modi=
fy
> >> + * it under the terms of the GNU General Public License version 2 as
> >> + * published by the Free Software Foundation.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program; if not, write to the Free Software
> >> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >> + */
> >> +
> >> +/* Supports:
> >> + * Xilinx SPI devices as platform devices
> >> + *
> >> + * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
> >> + */
> >> +
> >> +#include <linux/module.h>
> >> +#include <linux/init.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/platform_device.h>
> >> +
> >> +#include <linux/spi/spi.h>
> >> +#include <linux/spi/spi_bitbang.h>
> >> +#include <linux/spi/xilinx_spi.h>
> >> +
> >> +#include "xilinx_spi.h"
> >> +
> >> +static int __devinit xilinx_spi_probe(struct platform_device *dev)
> >> +{
> >> +	struct xspi_platform_data *pdata;
> >> +	struct resource *r;
> >> +	int irq;
> >> +	struct spi_master *master;
> >> +	u8 i;
> >> +
> >> +	pdata =3D dev->dev.platform_data;
> >> +	if (pdata =3D=3D NULL)
> >> +		return -ENODEV;
> >> +
> >> +	r =3D platform_get_resource(dev, IORESOURCE_MEM, 0);
> >> +	if (r =3D=3D NULL)
> >> +		return -ENODEV;
> >> +
> >> +	irq =3D platform_get_irq(dev, 0);
> >> +	if (irq < 0)
> >> +		return -ENXIO;
> >> +
> >> +	master =3D xilinx_spi_init(&dev->dev, r, irq, pdata->model,
> >> +		dev->id, pdata->num_chipselect, pdata->bits_per_word);
> >> +	if (IS_ERR(master))
> >> +		return PTR_ERR(master);
> >> +
> >> +	for (i =3D 0; i < pdata->num_devices; i++)
> >> +		spi_new_device(master, pdata->devices + i);
> >> +
> >> +	platform_set_drvdata(dev, master);
> >> +	return 0;
> >> +}
> >> +
> >> +static int __devexit xilinx_spi_remove(struct platform_device *dev)
> >> +{
> >> +	xilinx_spi_deinit(platform_get_drvdata(dev));
> >> +	platform_set_drvdata(dev, 0);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +/* work with hotplug and coldplug */
> >> +MODULE_ALIAS("platform:" XILINX_SPI_NAME);
> >> +
> >> +static struct platform_driver xilinx_spi_driver =3D {
> >> +	.probe	=3D xilinx_spi_probe,
> >> +	.remove	=3D __devexit_p(xilinx_spi_remove),
> >> +	.driver =3D {
> >> +		.name =3D XILINX_SPI_NAME,
> >> +		.owner =3D THIS_MODULE,
> >> +	},
> >> +};
> >> +
> >> +static int __init xilinx_spi_pltfm_init(void)
> >> +{
> >> +	return platform_driver_register(&xilinx_spi_driver);
> >> +}
> >> +module_init(xilinx_spi_pltfm_init);
> >> +
> >> +static void __exit xilinx_spi_pltfm_exit(void)
> >> +{
> >> +	platform_driver_unregister(&xilinx_spi_driver);
> >> +}
> >> +module_exit(xilinx_spi_pltfm_exit);
> >> +
> >> +MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
> >> +MODULE_DESCRIPTION("Xilinx SPI platform driver");
> >> +MODULE_LICENSE("GPL v2");
> >> +
> >> diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx=
_spi.h
> >> new file mode 100644
> >> index 0000000..e9e6a84
> >> --- /dev/null
> >> +++ b/include/linux/spi/xilinx_spi.h
> >> @@ -0,0 +1,18 @@
> >> +#ifndef __LINUX_SPI_XILINX_SPI_H
> >> +#define __LINUX_SPI_XILINX_SPI_H
> >> +
> >> +#define XILINX_SPI_MODEL_DS464 0
> >> +#define XILINX_SPI_MODEL_DS570 1
> >> +
> >> +/* SPI Controller IP */
> >> +struct xspi_platform_data {
> >> +	u16 num_chipselect;
> >> +	u8 model;
> >> +	u8 bits_per_word;
> >> +	/* devices to add to the bus when the host is up */
> >> +	struct spi_board_info *devices;
> >> +	u8 num_devices;
> >> +};
> >> +
> >> +#endif /* __LINUX_SPI_XILINX_SPI_H */
> >> +
> >> _______________________________________________
> >> Linuxppc-dev mailing list
> >> Linuxppc-dev@lists.ozlabs.org
> >> https://lists.ozlabs.org/listinfo/linuxppc-dev
> >
> >
> > This email and any attachments are intended for the sole use of the nam=
ed recipient(s) and
> contain(s) confidential information that may be proprietary, privileged o=
r copyrighted under
> applicable law. If you are not the intended recipient, do not read, copy,=
 or forward this email
> message or any attachments. Delete this email message and any attachments=
 immediately.
> >
> >
> =



This email and any attachments are intended for the sole use of the named r=
ecipient(s) and contain(s) confidential information that may be proprietary=
, privileged or copyrighted under applicable law. If you are not the intend=
ed recipient, do not read, copy, or forward this email message or any attac=
hments. Delete this email message and any attachments immediately.

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/44x: Fix xmon single step on PowerPC 44x
From: Benjamin Herrenschmidt @ 2009-09-23 22:40 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <20090923223539.GJ14261@zod.rchland.ibm.com>

On Wed, 2009-09-23 at 18:35 -0400, Josh Boyer wrote:

> >Any reason why that couldn't be in CONFIG_BOOKE ?
> 
> Off the top of my head, no.  I haven't tested on 40x yet though.  Will try
> and do that and revise.

Does 40x have CONFIG_BOOKE ? I was thinking more about FSL etc... but
yeah, 40x is worth having a look too.

> It could be.  I have no external debugger, thus no way to check it.  You don't
> get an exception without IDM set though, so it won't trap back into xmon like
> it should.  This is how we did it in arch/ppc (which isn't always a great
> thing) as well.

Ok, let's leave it there for now.

> I don't see how you could get it working without IDM, unless you inserted a
> trap (aka breakpoint) every time.  That seems sort of suboptimal when we have
> the IC event we can use.

The question is more whether IDM should be set once for all at boot (or
not) but let's ignore that for now.

Ben.

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/44x: Fix xmon single step on PowerPC 44x
From: Josh Boyer @ 2009-09-23 22:35 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1253741674.7103.327.camel@pasglop>

On Thu, Sep 24, 2009 at 07:34:34AM +1000, Benjamin Herrenschmidt wrote:
>On Wed, 2009-09-23 at 09:51 -0400, Josh Boyer wrote:
>> Prior to the arch/ppc -> arch/powerpc transition, xmon had support for single
>> stepping on 4xx boards.  The functionality was lost when arch/ppc was removed.
>> This patch restores single step support for 44x boards.
>> 
>> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
>> ---
>>  arch/powerpc/xmon/xmon.c |   20 +++++++++++++++++++-
>>  1 files changed, 19 insertions(+), 1 deletions(-)
>> 
>> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
>> index c6f0a71..fe2ad71 100644
>> --- a/arch/powerpc/xmon/xmon.c
>> +++ b/arch/powerpc/xmon/xmon.c
>> @@ -517,6 +517,15 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
>>  	in_xmon = 0;
>>  #endif
>>  
>> +#ifdef CONFIG_4xx
>> +	if ((regs->msr & (MSR_DE)) == (MSR_DE)) {
>
>Why not just if (regs->msr & MSR_DE) ?

Blind duplication of existing if case.  Will fix.

>> +		bp = at_breakpoint(regs->nip);
>> +		if (bp != NULL) {
>> +			regs->nip = (unsigned long) &bp->instr[0];
>> +			atomic_inc(&bp->ref_count);
>> +		}
>> +	}
>> +#else
>
>Any reason why that couldn't be in CONFIG_BOOKE ?

Off the top of my head, no.  I haven't tested on 40x yet though.  Will try
and do that and revise.

>>  	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
>>  		bp = at_breakpoint(regs->nip);
>>  		if (bp != NULL) {
>> @@ -530,7 +539,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
>>  			}
>>  		}
>>  	}
>> -
>> +#endif
>>  	insert_cpu_bpts();
>>  
>>  	local_irq_restore(flags);
>> @@ -894,6 +903,14 @@ cmds(struct pt_regs *excp)
>>  	}
>>  }
>>  
>> +#ifdef CONFIG_44x
>
>Same comment about BOOKE intead of 44x

Nod.

>> +static int do_step(struct pt_regs *regs)
>> +{
>> +	regs->msr |= MSR_DE;
>> +	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
>
>I'm not sure about setting IDM... Won't that be a problem if you have
>an external debugger connected ?

It could be.  I have no external debugger, thus no way to check it.  You don't
get an exception without IDM set though, so it won't trap back into xmon like
it should.  This is how we did it in arch/ppc (which isn't always a great
thing) as well.

I don't see how you could get it working without IDM, unless you inserted a
trap (aka breakpoint) every time.  That seems sort of suboptimal when we have
the IC event we can use.

josh

^ permalink raw reply

* Re: linux booting fails on ppc440x5 with SRAM
From: Benjamin Herrenschmidt @ 2009-09-23 21:40 UTC (permalink / raw)
  To: Vineeth _; +Cc: linuxppc-dev
In-Reply-To: <a9b543570909230749g5bb9c302wa48f310250068f5b@mail.gmail.com>

On Wed, 2009-09-23 at 20:19 +0530, Vineeth _ wrote:
> I am trying to port linux on IBM powerpc-440x5. I have this board
> which has this processor, a 16MB SRAM sits on location 0x0, uart and a
> flash.I have a simple bootloader which does the following.
>     1. Initialize the processor (as part of it, we Generates the tlbs
> for UART,16MB flash,16MB SRAM)
>     2. Initialize the UART
>     3. Copy the simple-boot linux_image (binary file) from flash to
> 0x400000 location of SRAM.
>     4. Kernel entry to 0x400000

Not sure yet, looks like things are being overwritten during boot.
Interestingly enough, the DEAR value looks like an MSR value..

Hard to tell what's up. You'll have to dig a bit more youself to
figure out how come the kernel's getting that bad pointer.

All I can tell you is that things work fine on 440x5 cores, though
I haven't tested a configuration with so little memory in a while.

Ben.

> zImage starting: loaded at 0x00400000 (sp: 0x004deeb0)
> Allocating 0x1dad84 bytes for kernel ...
> gunzipping (0x00000000 <- 0x0040c000:0x004dd3f1)...done 0x1c31cc bytes
> 
> Linux/PowerPC load: console=ttyS0 root=/dev/ram
> Finalizing device tree... flat tree at 0x4eb300
> id mach(): done
> inside skybeam_register_console function
> MMU:enterMMU:hw initMMU:mapinMMU:setioMMU:exitinside
> _setup_arch-begininginside _setup_arch-1inside
> _setup_arch-2setup_arch: bootmemarch: exit<7>Top of RAM: 0x1000000,
> Total RAM: 0x1000000
> Zone PFN ranges:
>  DMA      0x00000000 -> 0x00001000
>  Normal   0x00001000 -> 0x00001000
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
>    0: 0x00000000 -> 0x00001000
> MMU: Allocated 1088 bytes of context maps for 255 contexts
> Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 4064
> Kernel command line: console=ttyS0 root=/dev/ram
> Unable to handle kernel paging request for data at address 0x00021000
> Faulting instruction address: 0xc010a7c4
> Oops: Kernel access of bad area, sig: 11 [#1]
> PREEMPT PowerPC 44x Platform
> Modules linked in:
> NIP: c010a7c4 LR: c010dc50 CTR: 00000000
> REGS: c01bfeb0 TRAP: 0300   Not tainted  (2.6.30)
> MSR: 00021000 <ME,CE>  CR: 24000044  XER: 00000000
> DEAR: 00021000, ESR: 00000000
> TASK = c01a94b8[0] 'swapper' THREAD: c01be000
> GPR00: 00001180 c01bff60 c01a94b8 00021000 00000025 00000008 c0104968 00000000
> GPR08: 2f72616d c0110000 c0155938 c01a0000 22000024 00000000 fffff104 00000000
> GPR16: 00000000 00000000 00000000 00000000 fffffff8 000008b8 c010d758 c0104968
> GPR24: 00001198 00001190 c018a001 c01c5498 000008c0 00001188 00021000 c01c42f0
> NIP [c010a7c4] strchr+0x0/0x3c
> LR [c010dc50] match_token+0x138/0x228
> Call Trace:
> [c01bff60] [c016b99c] 0xc016b99c (unreliable)
> [c01bffa0] [c0104a00] sort_extable+0x28/0x38
> [c01bffb0] [c01938ec] sort_main_extable+0x20/0x30
> [c01bffc0] [c018c734] start_kernel+0x140/0x288
> [c01bfff0] [c0000200] skpinv+0x190/0x1cc
> Instruction dump:
> 7ca903a6 88040000 38a5ffff 38840001 2f800000 98090000 39290001 419e0010
> 4200ffe4 98a90000 4e800020 4e800020 <88030000> 5484063e 7f802000 4d9e0020
> ---[ end trace 31fd0ba7d8756001 ]---
> Kernel panic - not syncing: Attempted to kill the idle task!
> Call Trace:
> [c01bfd90] [c0005d5c] show_stack+0x4c/0x16c (unreliable)
> [c01bfdd0] [c002f17c] panic+0xa0/0x168
> [c01bfe20] [c0032eb8] do_exit+0x61c/0x638
> [c01bfe60] [c000b60c] kernel_bad_stack+0x0/0x4c
> [c01bfe90] [c000f310] bad_page_fault+0x90/0xd8
> [c01bfea0] [c000e184] handle_page_fault+0x7c/0x80
> [c01bff60] [c016b99c] 0xc016b99c
> [c01bffa0] [c0104a00] sort_extable+0x28/0x38
> [c01bffb0] [c01938ec] sort_main_extable+0x20/0x30
> [c01bffc0] [c018c734] start_kernel+0x140/0x288
> [c01bfff0] [c0000200] skpinv+0x190/0x1cc
> Rebooting in 180 seconds..
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply


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