[PATCH v2 00/15] powerpc/boot: 64bit little endian wrapper (rebased on v3.15-rc2)

2014-04-24 Thread Cédric Le Goater
Hi,

The following patchset adds support for 64bit little endian boot 
wrapper. It is based on original code from Andrew Tauferner. 

The first patches provide fixes for 64bit support. I also changed 
the prom code to make it converge with the prom_init kernel code. 
They have a lot in common and they could probably be merged.

  powerpc/boot: fix do_div for 64bit wrapper
  powerpc/boot: use a common prom_args struct in oflib
  powerpc/boot: use prom_arg_t in oflib
  powerpc/boot: add byteswapping routines in oflib
  powerpc/boot: add PROM_ERROR define in oflib
  powerpc/boot: rework of_claim() to make it 64bit friendly
  powerpc/boot: define typedef ihandle as u32
  powerpc/boot: fix compile warning in 64bit

These are for little endian only:

  powerpc/boot: define byteswapping routines for little endian
  powerpc/boot: add 64bit and little endian support to addnote
  powerpc/boot: add little endian support to elf utils

and finally, these add support for the 64bit little endian boot 
wrapper :

  powerpc/boot: define a routine to enter prom
  powerpc/boot: modify entry point for 64bit
  powerpc/boot: add a global entry point for pseries
  powerpc/boot: add support for 64bit little endian wrapper

Here are some topics to discuss :

  - to compile in 64bit, -m64 is added to the cross32 compiler.
  - There are still some compile warnings due to 64bit, in addnote 
and in the device tree library.
  - the wrapper is compiled as a position independent executable. 

This patchset is based on a 3.15-rc2 and was tested on qemu with 
the -kernel option, yaboot and grub for little and big endian 
guests. Tests were also done to check that the PowerVM stack was
not broken by these changes.

It is also available from :

https://github.com/legoater/linux v3.15-rc2-zimagev2 

Cheers,

C. 

Changes since v1 :

  - Fixed Makefile for platforms generating a zImage.pseries 
  - used PROM_ERROR (-1u) to test return addr when claiming memory
  - removed patch modifying the call to the kernel entry point
  - merged last 3 patches to preserve bisectability 

Cédric Le Goater (15):
  powerpc/boot: fix do_div for 64bit wrapper
  powerpc/boot: use a common prom_args struct in oflib
  powerpc/boot: use prom_arg_t in oflib
  powerpc/boot: add byteswapping routines in oflib
  powerpc/boot: add PROM_ERROR define in oflib
  powerpc/boot: rework of_claim() to make it 64bit friendly
  powerpc/boot: define typedef ihandle as u32
  powerpc/boot: fix compile warning in 64bit
  powerpc/boot: define byteswapping routines for little endian
  powerpc/boot: add 64bit and little endian support to addnote
  powerpc/boot: add little endian support to elf utils
  powerpc/boot: define a routine to enter prom
  powerpc/boot: modify entry point for 64bit
  powerpc/boot: add a global entry point for pseries
  powerpc/boot: add support for 64bit little endian wrapper

 arch/powerpc/boot/Makefile |   21 +++-
 arch/powerpc/boot/addnote.c|  128 +++
 arch/powerpc/boot/crt0.S   |  180 +++-
 arch/powerpc/boot/elf_util.c   |4 +
 arch/powerpc/boot/of.c |4 +-
 arch/powerpc/boot/of.h |   19 +++-
 arch/powerpc/boot/ofconsole.c  |6 +-
 arch/powerpc/boot/oflib.c  |   92 
 arch/powerpc/boot/ppc_asm.h|   12 +++
 arch/powerpc/boot/pseries-head.S   |8 ++
 arch/powerpc/boot/stdio.c  |   14 +++
 arch/powerpc/boot/swab.h   |   29 +
 arch/powerpc/boot/wrapper  |   17 ++-
 arch/powerpc/boot/zImage.lds.S |   25 -
 arch/powerpc/platforms/Kconfig.cputype |5 +
 15 files changed, 464 insertions(+), 100 deletions(-)
 create mode 100644 arch/powerpc/boot/pseries-head.S
 create mode 100644 arch/powerpc/boot/swab.h

-- 
1.7.10.4

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

[PATCH v2 01/15] powerpc/boot: fix do_div for 64bit wrapper

2014-04-24 Thread Cédric Le Goater
When the boot wrapper is compiled in 64bit, there is no need to
use __div64_32.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/stdio.c |   14 ++
 1 file changed, 14 insertions(+)

diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 5b57800bbc67..a701261b1781 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -21,6 +21,18 @@ size_t strnlen(const char * s, size_t count)
return sc - s;
 }
 
+#ifdef __powerpc64__
+
+# define do_div(n, base) ({\
+   unsigned int __base = (base);   \
+   unsigned int __rem; \
+   __rem = ((unsigned long long)(n)) % __base; \
+   (n) = ((unsigned long long)(n)) / __base;   \
+   __rem;  \
+})
+
+#else
+
 extern unsigned int __div64_32(unsigned long long *dividend,
   unsigned int divisor);
 
@@ -39,6 +51,8 @@ extern unsigned int __div64_32(unsigned long long *dividend,
__rem;  \
  })
 
+#endif /* __powerpc64__ */
+
 static int skip_atoi(const char **s)
 {
int i, c;
-- 
1.7.10.4

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

[PATCH v2 03/15] powerpc/boot: use prom_arg_t in oflib

2014-04-24 Thread Cédric Le Goater
This patch updates the wrapper code to converge with the kernel code in
prom_init.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/oflib.c |   10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index c3288a3446b3..3b0c9458504f 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -16,6 +16,8 @@
 
 #include "of.h"
 
+typedef u32 prom_arg_t;
+
 /* The following structure is used to communicate with open firmware.
  * All arguments in and out are in big endian format. */
 struct prom_args {
@@ -46,7 +48,7 @@ int of_call_prom(const char *service, int nargs, int nret, 
...)
 
va_start(list, nret);
for (i = 0; i < nargs; i++)
-   args.args[i] = va_arg(list, unsigned int);
+   args.args[i] = va_arg(list, prom_arg_t);
va_end(list);
 
for (i = 0; i < nret; i++)
@@ -59,7 +61,7 @@ int of_call_prom(const char *service, int nargs, int nret, 
...)
 }
 
 static int of_call_prom_ret(const char *service, int nargs, int nret,
-   unsigned int *rets, ...)
+   prom_arg_t *rets, ...)
 {
int i;
struct prom_args args;
@@ -71,7 +73,7 @@ static int of_call_prom_ret(const char *service, int nargs, 
int nret,
 
va_start(list, rets);
for (i = 0; i < nargs; i++)
-   args.args[i] = va_arg(list, unsigned int);
+   args.args[i] = va_arg(list, prom_arg_t);
va_end(list);
 
for (i = 0; i < nret; i++)
@@ -148,7 +150,7 @@ static int check_of_version(void)
 void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
 {
int ret;
-   unsigned int result;
+   prom_arg_t result;
 
if (need_map < 0)
need_map = check_of_version();
-- 
1.7.10.4

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

[PATCH v2 02/15] powerpc/boot: use a common prom_args struct in oflib

2014-04-24 Thread Cédric Le Goater
This patch fixes warnings when the wrapper is compiled in 64bit and
updates the boot wrapper code related to prom to converge with the
kernel code in prom_init. This should make the review of changes easier.

The kernel has a different number of possible arguments (10) when
entering prom. There does not seem to be any good reason to have
12 in the wrapper, so the patch changes this value to args[10] in
the prom_args struct.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/of.h|2 ++
 arch/powerpc/boot/oflib.c |   29 +++--
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index e4c68f7391c5..5da03d9b9463 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -18,4 +18,6 @@ int of_setprop(const void *phandle, const char *name, const 
void *buf,
 /* Console functions */
 void of_console_init(void);
 
+typedef u32__be32;
+
 #endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index b0ec9cf3eaaf..c3288a3446b3 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -16,6 +16,15 @@
 
 #include "of.h"
 
+/* The following structure is used to communicate with open firmware.
+ * All arguments in and out are in big endian format. */
+struct prom_args {
+   __be32 service; /* Address of service name string. */
+   __be32 nargs;   /* Number of input arguments. */
+   __be32 nret;/* Number of output arguments. */
+   __be32 args[10];/* Input/output arguments. */
+};
+
 static int (*prom) (void *);
 
 void of_init(void *promptr)
@@ -23,18 +32,15 @@ void of_init(void *promptr)
prom = (int (*)(void *))promptr;
 }
 
+#define ADDR(x)(u32)(unsigned long)(x)
+
 int of_call_prom(const char *service, int nargs, int nret, ...)
 {
int i;
-   struct prom_args {
-   const char *service;
-   int nargs;
-   int nret;
-   unsigned int args[12];
-   } args;
+   struct prom_args args;
va_list list;
 
-   args.service = service;
+   args.service = ADDR(service);
args.nargs = nargs;
args.nret = nret;
 
@@ -56,15 +62,10 @@ static int of_call_prom_ret(const char *service, int nargs, 
int nret,
unsigned int *rets, ...)
 {
int i;
-   struct prom_args {
-   const char *service;
-   int nargs;
-   int nret;
-   unsigned int args[12];
-   } args;
+   struct prom_args args;
va_list list;
 
-   args.service = service;
+   args.service = ADDR(service);
args.nargs = nargs;
args.nret = nret;
 
-- 
1.7.10.4

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

[PATCH v2 04/15] powerpc/boot: add byteswapping routines in oflib

2014-04-24 Thread Cédric Le Goater
Values will need to be byte-swapped when calling prom (big endian) from
a little endian boot wrapper.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/of.h|3 +++
 arch/powerpc/boot/ofconsole.c |6 --
 arch/powerpc/boot/oflib.c |   22 +++---
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index 5da03d9b9463..40d95bf7402b 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -20,4 +20,7 @@ void of_console_init(void);
 
 typedef u32__be32;
 
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+
 #endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
index ce0e02424453..8b754702460a 100644
--- a/arch/powerpc/boot/ofconsole.c
+++ b/arch/powerpc/boot/ofconsole.c
@@ -18,7 +18,7 @@
 
 #include "of.h"
 
-static void *of_stdout_handle;
+static unsigned int of_stdout_handle;
 
 static int of_console_open(void)
 {
@@ -27,8 +27,10 @@ static int of_console_open(void)
if (((devp = of_finddevice("/chosen")) != NULL)
&& (of_getprop(devp, "stdout", &of_stdout_handle,
   sizeof(of_stdout_handle))
-   == sizeof(of_stdout_handle)))
+   == sizeof(of_stdout_handle))) {
+   of_stdout_handle = be32_to_cpu(of_stdout_handle);
return 0;
+   }
 
return -1;
 }
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 3b0c9458504f..0f72b1a42133 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -42,13 +42,13 @@ int of_call_prom(const char *service, int nargs, int nret, 
...)
struct prom_args args;
va_list list;
 
-   args.service = ADDR(service);
-   args.nargs = nargs;
-   args.nret = nret;
+   args.service = cpu_to_be32(ADDR(service));
+   args.nargs = cpu_to_be32(nargs);
+   args.nret = cpu_to_be32(nret);
 
va_start(list, nret);
for (i = 0; i < nargs; i++)
-   args.args[i] = va_arg(list, prom_arg_t);
+   args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
va_end(list);
 
for (i = 0; i < nret; i++)
@@ -57,7 +57,7 @@ int of_call_prom(const char *service, int nargs, int nret, 
...)
if (prom(&args) < 0)
return -1;
 
-   return (nret > 0)? args.args[nargs]: 0;
+   return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
 }
 
 static int of_call_prom_ret(const char *service, int nargs, int nret,
@@ -67,13 +67,13 @@ static int of_call_prom_ret(const char *service, int nargs, 
int nret,
struct prom_args args;
va_list list;
 
-   args.service = ADDR(service);
-   args.nargs = nargs;
-   args.nret = nret;
+   args.service = cpu_to_be32(ADDR(service));
+   args.nargs = cpu_to_be32(nargs);
+   args.nret = cpu_to_be32(nret);
 
va_start(list, rets);
for (i = 0; i < nargs; i++)
-   args.args[i] = va_arg(list, prom_arg_t);
+   args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
va_end(list);
 
for (i = 0; i < nret; i++)
@@ -84,9 +84,9 @@ static int of_call_prom_ret(const char *service, int nargs, 
int nret,
 
if (rets != (void *) 0)
for (i = 1; i < nret; ++i)
-   rets[i-1] = args.args[nargs+i];
+   rets[i-1] = be32_to_cpu(args.args[nargs+i]);
 
-   return (nret > 0)? args.args[nargs]: 0;
+   return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
 }
 
 /* returns true if s2 is a prefix of s1 */
-- 
1.7.10.4

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

[PATCH v2 05/15] powerpc/boot: add PROM_ERROR define in oflib

2014-04-24 Thread Cédric Le Goater
This is mostly useful to make to the boot wrapper code closer with
the kernel code in prom_init.

Signed-off-by: Cédric Le Goater 
---

Changes since v1:

 - moved PROM_ERROR definition in of.h. of_try_claim() will make 
   use of it in the next patch.

 arch/powerpc/boot/of.h|2 ++
 arch/powerpc/boot/oflib.c |6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index 40d95bf7402b..0f058ef69521 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -23,4 +23,6 @@ typedef u32   __be32;
 #define cpu_to_be32(x) (x)
 #define be32_to_cpu(x) (x)
 
+#define PROM_ERROR (-1u)
+
 #endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 0f72b1a42133..7f61f2eb5653 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -55,7 +55,7 @@ int of_call_prom(const char *service, int nargs, int nret, 
...)
args.args[nargs+i] = 0;
 
if (prom(&args) < 0)
-   return -1;
+   return PROM_ERROR;
 
return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
 }
@@ -80,9 +80,9 @@ static int of_call_prom_ret(const char *service, int nargs, 
int nret,
args.args[nargs+i] = 0;
 
if (prom(&args) < 0)
-   return -1;
+   return PROM_ERROR;
 
-   if (rets != (void *) 0)
+   if (rets != NULL)
for (i = 1; i < nret; ++i)
rets[i-1] = be32_to_cpu(args.args[nargs+i]);
 
-- 
1.7.10.4

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

[PATCH v2 07/15] powerpc/boot: define typedef ihandle as u32

2014-04-24 Thread Cédric Le Goater
This makes ihandle 64bit friendly.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/of.h|2 +-
 arch/powerpc/boot/oflib.c |   10 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index 504a0a31b685..e1ef620082f7 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -2,7 +2,7 @@
 #define _PPC_BOOT_OF_H_
 
 typedef void *phandle;
-typedef void *ihandle;
+typedef u32 ihandle;
 
 void of_init(void *promptr);
 int of_call_prom(const char *service, int nargs, int nret, ...);
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 329437d0e943..956443fb9f65 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -106,7 +106,7 @@ static int string_match(const char *s1, const char *s2)
  */
 static int need_map = -1;
 static ihandle chosen_mmu;
-static phandle memory;
+static ihandle memory;
 
 static int check_of_version(void)
 {
@@ -135,10 +135,10 @@ static int check_of_version(void)
printf("no mmu\n");
return 0;
}
-   memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
-   if (memory == (ihandle) -1) {
-   memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
-   if (memory == (ihandle) -1) {
+   memory = of_call_prom("open", 1, 1, "/memory");
+   if (memory == PROM_ERROR) {
+   memory = of_call_prom("open", 1, 1, "/memory@0");
+   if (memory == PROM_ERROR) {
printf("no memory node\n");
return 0;
}
-- 
1.7.10.4

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

[PATCH v2 06/15] powerpc/boot: rework of_claim() to make it 64bit friendly

2014-04-24 Thread Cédric Le Goater
This patch fixes 64bit compile warnings and updates the wrapper code
to converge the kernel code in prom_init.

Signed-off-by: Cédric Le Goater 
---

Changes since v1:

 - use PROM_ERROR to test return addr

 arch/powerpc/boot/of.c|4 ++--
 arch/powerpc/boot/of.h|3 ++-
 arch/powerpc/boot/oflib.c |   15 ---
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 62e2f43ec1df..7ca910cb2fc6 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -40,8 +40,8 @@ static void *of_try_claim(unsigned long size)
 #ifdef DEBUG
printf("trying: 0x%08lx\n\r", claim_base);
 #endif
-   addr = (unsigned long)of_claim(claim_base, size, 0);
-   if ((void *)addr != (void *)-1)
+   addr = (unsigned long) of_claim(claim_base, size, 0);
+   if (addr != PROM_ERROR)
break;
}
if (addr == 0)
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index 0f058ef69521..504a0a31b685 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -6,7 +6,8 @@ typedef void *ihandle;
 
 void of_init(void *promptr);
 int of_call_prom(const char *service, int nargs, int nret, ...);
-void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+unsigned int of_claim(unsigned long virt, unsigned long size,
+   unsigned long align);
 void *of_vmlinux_alloc(unsigned long size);
 void of_exit(void);
 void *of_finddevice(const char *name);
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 7f61f2eb5653..329437d0e943 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -147,7 +147,8 @@ static int check_of_version(void)
return 1;
 }
 
-void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+unsigned int of_claim(unsigned long virt, unsigned long size,
+ unsigned long align)
 {
int ret;
prom_arg_t result;
@@ -155,32 +156,32 @@ void *of_claim(unsigned long virt, unsigned long size, 
unsigned long align)
if (need_map < 0)
need_map = check_of_version();
if (align || !need_map)
-   return (void *) of_call_prom("claim", 3, 1, virt, size, align);
+   return of_call_prom("claim", 3, 1, virt, size, align);
 
ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
   align, size, virt);
if (ret != 0 || result == -1)
-   return (void *) -1;
+   return  -1;
ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", 
chosen_mmu,
   align, size, virt);
/* 0x12 == coherent + read/write */
ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
   0x12, size, virt, virt);
-   return (void *) virt;
+   return virt;
 }
 
 void *of_vmlinux_alloc(unsigned long size)
 {
unsigned long start = (unsigned long)_start, end = (unsigned long)_end;
-   void *addr;
+   unsigned long addr;
void *p;
 
/* With some older POWER4 firmware we need to claim the area the kernel
 * will reside in.  Newer firmwares don't need this so we just ignore
 * the return value.
 */
-   addr = of_claim(start, end - start, 0);
-   printf("Trying to claim from 0x%lx to 0x%lx (0x%lx) got %p\r\n",
+   addr = (unsigned long) of_claim(start, end - start, 0);
+   printf("Trying to claim from 0x%lx to 0x%lx (0x%lx) got %lx\r\n",
   start, end, end - start, addr);
 
p = malloc(size);
-- 
1.7.10.4

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

[PATCH v2 09/15] powerpc/boot: define byteswapping routines for little endian

2014-04-24 Thread Cédric Le Goater
These are not the most efficient versions of swab but the wrapper does
not do much byte swapping. On a big endian cpu, these routines are
a no-op.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/of.h   |7 +++
 arch/powerpc/boot/swab.h |   29 +
 2 files changed, 36 insertions(+)
 create mode 100644 arch/powerpc/boot/swab.h

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index e1ef620082f7..c8c1750aba0c 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -1,6 +1,8 @@
 #ifndef _PPC_BOOT_OF_H_
 #define _PPC_BOOT_OF_H_
 
+#include "swab.h"
+
 typedef void *phandle;
 typedef u32 ihandle;
 
@@ -21,8 +23,13 @@ void of_console_init(void);
 
 typedef u32__be32;
 
+#ifdef __LITTLE_ENDIAN__
+#define cpu_to_be32(x) swab32(x)
+#define be32_to_cpu(x) swab32(x)
+#else
 #define cpu_to_be32(x) (x)
 #define be32_to_cpu(x) (x)
+#endif
 
 #define PROM_ERROR (-1u)
 
diff --git a/arch/powerpc/boot/swab.h b/arch/powerpc/boot/swab.h
new file mode 100644
index ..d0e1431084ca
--- /dev/null
+++ b/arch/powerpc/boot/swab.h
@@ -0,0 +1,29 @@
+#ifndef _PPC_BOOT_SWAB_H_
+#define _PPC_BOOT_SWAB_H_
+
+static inline u16 swab16(u16 x)
+{
+   return  ((x & (u16)0x00ffU) << 8) |
+   ((x & (u16)0xff00U) >> 8);
+}
+
+static inline u32 swab32(u32 x)
+{
+   return  ((x & (u32)0x00ffUL) << 24) |
+   ((x & (u32)0xff00UL) <<  8) |
+   ((x & (u32)0x00ffUL) >>  8) |
+   ((x & (u32)0xff00UL) >> 24);
+}
+
+static inline u64 swab64(u64 x)
+{
+   return  (u64)((x & (u64)0x00ffULL) << 56) |
+   (u64)((x & (u64)0xff00ULL) << 40) |
+   (u64)((x & (u64)0x00ffULL) << 24) |
+   (u64)((x & (u64)0xff00ULL) <<  8) |
+   (u64)((x & (u64)0x00ffULL) >>  8) |
+   (u64)((x & (u64)0xff00ULL) >> 24) |
+   (u64)((x & (u64)0x00ffULL) >> 40) |
+   (u64)((x & (u64)0xff00ULL) >> 56);
+}
+#endif /* _PPC_BOOT_SWAB_H_ */
-- 
1.7.10.4

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

[PATCH v2 08/15] powerpc/boot: fix compile warning in 64bit

2014-04-24 Thread Cédric Le Goater
 arch/powerpc/boot/oflib.c:211:9: warning: cast to pointer from integer of \
  different size [-Wint-to-pointer-cast]
  return (phandle) of_call_prom("finddevice", 1, 1, name);

This is a work around. The definite solution would be to define the
phandle typedef as a u32, as in the kernel, but this would break the
device tree ops API.

Let it be for the moment.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/oflib.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 956443fb9f65..cdfe762d2b2b 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -201,7 +201,7 @@ void of_exit(void)
  */
 void *of_finddevice(const char *name)
 {
-   return (phandle) of_call_prom("finddevice", 1, 1, name);
+   return (void *) (unsigned long) of_call_prom("finddevice", 1, 1, name);
 }
 
 int of_getprop(const void *phandle, const char *name, void *buf,
-- 
1.7.10.4

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

[PATCH v2 10/15] powerpc/boot: add 64bit and little endian support to addnote

2014-04-24 Thread Cédric Le Goater
It could certainly be improved using Elf macros and byteswapping
routines, but the initial version of the code is organised to be a
single file program with limited dependencies. yaboot is the same.

Please scream if you want a total rewrite.

Signed-off-by: Cédric Le Goater 
---

Changes since RFC:

 - fixed the note creation which was done with the wrong endianess 
 - increased 'buf' as ELF structures are larger in 64bit

 arch/powerpc/boot/addnote.c |  128 ---
 1 file changed, 85 insertions(+), 43 deletions(-)

diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c
index 349b5530d2c4..9d9f6f334d3c 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -6,6 +6,8 @@
  *
  * Copyright 2000 Paul Mackerras.
  *
+ * Adapted for 64 bit little endian images by Andrew Tauferner.
+ *
  * 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
@@ -55,36 +57,61 @@ unsigned int rpanote[N_RPA_DESCR] = {
 
 #define ROUNDUP(len)   (((len) + 3) & ~3)
 
-unsigned char buf[512];
+unsigned char buf[1024];
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+static int e_data = ELFDATA2MSB;
+#define ELFCLASS32  1
+#define ELFCLASS64  2
+static int e_class = ELFCLASS32;
 
 #define GET_16BE(off)  ((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off)  ((GET_16BE(off) << 16) + GET_16BE((off)+2))
-
-#define PUT_16BE(off, v)   (buf[off] = ((v) >> 8) & 0xff, \
-buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v)   (PUT_16BE((off), (v) >> 16), \
-PUT_16BE((off) + 2, (v)))
+#define GET_32BE(off)  ((GET_16BE(off) << 16U) + GET_16BE((off)+2U))
+#define GET_64BE(off)  unsigned long long)GET_32BE(off)) << 32ULL) + \
+   ((unsigned long long)GET_32BE((off)+4ULL)))
+#define PUT_16BE(off, v)(buf[off] = ((v) >> 8) & 0xff, \
+buf[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(off, v)(PUT_16BE((off), (v) >> 16L), PUT_16BE((off) + 2, (v)))
+#define PUT_64BE(off, v)((PUT_32BE((off), (v) >> 32L), \
+ PUT_32BE((off) + 4, (v
+
+#define GET_16LE(off)  ((buf[off]) + (buf[(off)+1] << 8))
+#define GET_32LE(off)  (GET_16LE(off) + (GET_16LE((off)+2U) << 16U))
+#define GET_64LE(off)  ((unsigned long long)GET_32LE(off) + \
+   (((unsigned long long)GET_32LE((off)+4ULL)) << 32ULL))
+#define PUT_16LE(off, v) (buf[off] = (v) & 0xff, \
+ buf[(off) + 1] = ((v) >> 8) & 0xff)
+#define PUT_32LE(off, v) (PUT_16LE((off), (v)), PUT_16LE((off) + 2, (v) >> 
16L))
+#define PUT_64LE(off, v) (PUT_32LE((off), (v)), PUT_32LE((off) + 4, (v) >> 
32L))
+
+#define GET_16(off)(e_data == ELFDATA2MSB ? GET_16BE(off) : GET_16LE(off))
+#define GET_32(off)(e_data == ELFDATA2MSB ? GET_32BE(off) : GET_32LE(off))
+#define GET_64(off)(e_data == ELFDATA2MSB ? GET_64BE(off) : GET_64LE(off))
+#define PUT_16(off, v) (e_data == ELFDATA2MSB ? PUT_16BE(off, v) : \
+PUT_16LE(off, v))
+#define PUT_32(off, v)  (e_data == ELFDATA2MSB ? PUT_32BE(off, v) : \
+PUT_32LE(off, v))
+#define PUT_64(off, v)  (e_data == ELFDATA2MSB ? PUT_64BE(off, v) : \
+PUT_64LE(off, v))
 
 /* Structure of an ELF file */
 #define E_IDENT0   /* ELF header */
-#defineE_PHOFF 28
-#define E_PHENTSIZE42
-#define E_PHNUM44
-#define E_HSIZE52  /* size of ELF header */
+#defineE_PHOFF (e_class == ELFCLASS32 ? 28 : 32)
+#define E_PHENTSIZE(e_class == ELFCLASS32 ? 42 : 54)
+#define E_PHNUM(e_class == ELFCLASS32 ? 44 : 56)
+#define E_HSIZE(e_class == ELFCLASS32 ? 52 : 64)
 
 #define EI_MAGIC   0   /* offsets in E_IDENT area */
 #define EI_CLASS   4
 #define EI_DATA5
 
 #define PH_TYPE0   /* ELF program header */
-#define PH_OFFSET  4
-#define PH_FILESZ  16
-#define PH_HSIZE   32  /* size of program header */
+#define PH_OFFSET  (e_class == ELFCLASS32 ? 4 : 8)
+#define PH_FILESZ  (e_class == ELFCLASS32 ? 16 : 32)
+#define PH_HSIZE   (e_class == ELFCLASS32 ? 32 : 56)
 
 #define PT_NOTE4   /* Program header type = note */
 
-#define ELFCLASS32 1
-#define ELFDATA2MSB2
 
 unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
 
@@ -92,8 +119,8 @@ int
 main(int ac, char **av)
 {
int fd, n, i;
-   int ph, ps, np;
-   int nnote, nnote2, ns;
+   unsigned long ph, ps, np;
+   long nnote, nnote2, ns;
 
if (ac != 2) {
fprintf(stderr, "Usage: %s elf-file\n", av[0]);
@@ -114,26 +141,27 @@ main(int ac, char **av)
exit(1);
}
 
-   if (n < E_HSIZE || memc

[PATCH v2 12/15] powerpc/boot: define a routine to enter prom

2014-04-24 Thread Cédric Le Goater
This patch defines a 'prom' routine similar to 'enter_prom' in the
kernel.

The difference is in the MSR which is built before entering prom. Big
endian order is enforced as in the kernel but 32bit mode is not. It
prepares ground for the next patches which will introduce Little endian
order.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/crt0.S  |   71 +
 arch/powerpc/boot/oflib.c |6 
 2 files changed, 77 insertions(+)

diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 0f7428a37efb..dbd99d064828 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -126,3 +126,74 @@ RELACOUNT = 0x6ff9
 
/* Call start */
b   start
+
+#ifdef __powerpc64__
+
+#define PROM_FRAME_SIZE 512
+#define SAVE_GPR(n, base)   std n,8*(n)(base)
+#define REST_GPR(n, base)   ld  n,8*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base)SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base)REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+/* prom handles the jump into and return from firmware.  The prom args pointer
+   is loaded in r3. */
+.globl prom
+prom:
+   mflrr0
+   std r0,16(r1)
+   stdur1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+   SAVE_GPR(2, r1)
+   SAVE_GPR(13, r1)
+   SAVE_8GPRS(14, r1)
+   SAVE_10GPRS(22, r1)
+   mfcrr10
+   std r10,8*32(r1)
+   mfmsr   r10
+   std r10,8*33(r1)
+
+   /* remove MSR_LE from msr but keep MSR_SF */
+   mfmsr   r10
+   rldicr  r10,r10,0,62
+   mtsrr1  r10
+
+   /* Load FW address, set LR to label 1, and jump to FW */
+   bl  0f
+0: mflrr10
+   addir11,r10,(1f-0b)
+   mtlrr11
+
+   ld  r10,(p_prom-0b)(r10)
+   mtsrr0  r10
+
+   rfid
+
+1: /* Return from OF */
+
+   /* Restore registers and return. */
+   rldicl  r1,r1,0,32
+
+   /* Restore the MSR (back to 64 bits) */
+   ld  r10,8*(33)(r1)
+   mtmsr   r10
+   isync
+
+   /* Restore other registers */
+   REST_GPR(2, r1)
+   REST_GPR(13, r1)
+   REST_8GPRS(14, r1)
+   REST_10GPRS(22, r1)
+   ld  r10,8*32(r1)
+   mtcrr10
+
+   addir1,r1,PROM_FRAME_SIZE
+   ld  r0,16(r1)
+   mtlrr0
+   blr
+#endif
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index cdfe762d2b2b..46c98a47d949 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -27,11 +27,17 @@ struct prom_args {
__be32 args[10];/* Input/output arguments. */
 };
 
+#ifdef __powerpc64__
+extern int prom(void *);
+#else
 static int (*prom) (void *);
+#endif
 
 void of_init(void *promptr)
 {
+#ifndef __powerpc64__
prom = (int (*)(void *))promptr;
+#endif
 }
 
 #define ADDR(x)(u32)(unsigned long)(x)
-- 
1.7.10.4

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

[PATCH v2 13/15] powerpc/boot: modify entry point for 64bit

2014-04-24 Thread Cédric Le Goater
This patch adds support a 64bit wrapper entry point. As in 32bit, the
entry point does its own relocation and can be loaded at any address
by the firmware.

Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/crt0.S |  108 --
 1 file changed, 104 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index dbd99d064828..689290561e69 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -1,17 +1,20 @@
 /*
  * Copyright (C) Paul Mackerras 1997.
  *
+ * Adapted for 64 bit LE PowerPC by Andrew Tauferner
+ *
  * 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.
  *
- * NOTE: this code runs in 32 bit mode, is position-independent,
- * and is packaged as ELF32.
  */
 
 #include "ppc_asm.h"
 
+RELA = 7
+RELACOUNT = 0x6ff9
+
.text
/* A procedure descriptor used when booting this as a COFF file.
 * When making COFF, this comes first in the link and we're
@@ -21,6 +24,20 @@
 _zimage_start_opd:
.long   0x50, 0, 0, 0
 
+#ifdef __powerpc64__
+.balign 8
+p_start:   .llong  _start
+p_etext:   .llong  _etext
+p_bss_start:   .llong  __bss_start
+p_end: .llong  _end
+
+p_toc: .llong  __toc_start + 0x8000 - p_base
+p_dyn: .llong  __dynamic_start - p_base
+p_rela:.llong  __rela_dyn_start - p_base
+p_prom:.llong  0
+   .weak   _platform_stack_top
+p_pstack:  .llong  _platform_stack_top
+#else
 p_start:   .long   _start
 p_etext:   .long   _etext
 p_bss_start:   .long   __bss_start
@@ -28,6 +45,7 @@ p_end:.long   _end
 
.weak   _platform_stack_top
 p_pstack:  .long   _platform_stack_top
+#endif
 
.weak   _zimage_start
.globl  _zimage_start
@@ -38,6 +56,7 @@ _zimage_start_lib:
   and the address where we're running. */
bl  .+4
 p_base:mflrr10 /* r10 now points to runtime addr of 
p_base */
+#ifndef __powerpc64__
/* grab the link address of the dynamic section in r11 */
addis   r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
@@ -51,8 +70,6 @@ p_base:   mflrr10 /* r10 now points to 
runtime addr of p_base */
 
/* The dynamic section contains a series of tagged entries.
 * We need the RELA and RELACOUNT entries. */
-RELA = 7
-RELACOUNT = 0x6ff9
li  r9,0
li  r0,0
 9: lwz r8,0(r12)   /* get tag */
@@ -120,7 +137,90 @@ RELACOUNT = 0x6ff9
li  r0,0
stwur0,-16(r1)  /* establish a stack frame */
 6:
+#else /* __powerpc64__ */
+   /* Save the prom pointer at p_prom. */
+   std r5,(p_prom-p_base)(r10)
+
+   /* Set r2 to the TOC. */
+   ld  r2,(p_toc-p_base)(r10)
+   add r2,r2,r10
+
+   /* Grab the link address of the dynamic section in r11. */
+   ld  r11,-32768(r2)
+   cmpwi   r11,0
+   beq 3f  /* if not linked -pie then no dynamic section */
+
+   ld  r11,(p_dyn-p_base)(r10)
+   add r11,r11,r10
+   ld  r9,(p_rela-p_base)(r10)
+   add r9,r9,r10
+
+   li  r7,0
+   li  r8,0
+9: ld  r6,0(r11)   /* get tag */
+   cmpdi   r6,0
+   beq 12f  /* end of list */
+   cmpdi   r6,RELA
+   bne 10f
+   ld  r7,8(r11)   /* get RELA pointer in r7 */
+   b   11f
+10:addis   r6,r6,(-RELACOUNT)@ha
+   cmpdi   r6,RELACOUNT@l
+   bne 11f
+   ld  r8,8(r11)   /* get RELACOUNT value in r8 */
+11:addir11,r11,16
+   b   9b
+12:
+   cmpdi   r7,0/* check we have both RELA and RELACOUNT */
+   cmpdi   cr1,r8,0
+   beq 3f
+   beq cr1,3f
+
+   /* Calcuate the runtime offset. */
+   subfr7,r7,r9
 
+   /* Run through the list of relocations and process the
+* R_PPC64_RELATIVE ones. */
+   mtctr   r8
+13:ld  r0,8(r9)/* ELF64_R_TYPE(reloc->r_info) */
+   cmpdi   r0,22   /* R_PPC64_RELATIVE */
+   bne 3f
+   ld  r6,0(r9)/* reloc->r_offset */
+   ld  r0,16(r9)   /* reloc->r_addend */
+   add r0,r0,r7
+   stdxr0,r7,r6
+   addir9,r9,24
+   bdnz13b
+
+   /* Do a cache flush for our text, in case the loader didn't */
+3: ld  r9,p_start-p_base(r10)  /* note: these are relocated now */
+   ld  r8,p_etext-p_base(r10)
+4: dcbfr0,r9
+   icbir0,r9
+   addir9,r9,0x20
+   cmpld   cr0,r9,r8
+   blt 4b
+   sync
+   isync
+
+   /* Clear the BSS */
+   ld  r9,

[PATCH v2 14/15] powerpc/boot: add a global entry point for pseries

2014-04-24 Thread Cédric Le Goater
When entering the boot wrapper in little endian, we will need to fix
the endian order using a fixup trampoline like in the kernel. This
patch overrides the _zimage_start entry point for this purpose.

Signed-off-by: Cédric Le Goater 
---

Changes since v1:

 - pseries is not the only platform generating a zImage.pseries boot 
   wrapper. Fixed Makefile for these. 

 arch/powerpc/boot/Makefile   |5 +
 arch/powerpc/boot/pseries-head.S |5 +
 arch/powerpc/boot/wrapper|2 +-
 3 files changed, 11 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/boot/pseries-head.S

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index a1f8c7f1ec60..bed660ddf48c 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -99,6 +99,11 @@ src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c 
cuboot-mpc7448hpc2.c \
 src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
 src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
 src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c
+src-plat-$(CONFIG_PPC_PSERIES) += pseries-head.S
+src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S
+src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S
+src-plat-$(CONFIG_PPC_CELLEB) += pseries-head.S
+src-plat-$(CONFIG_PPC_CELL_QPACE) += pseries-head.S
 
 src-wlib := $(sort $(src-wlib-y))
 src-plat := $(sort $(src-plat-y))
diff --git a/arch/powerpc/boot/pseries-head.S b/arch/powerpc/boot/pseries-head.S
new file mode 100644
index ..655c3d2c321b
--- /dev/null
+++ b/arch/powerpc/boot/pseries-head.S
@@ -0,0 +1,5 @@
+   .text
+
+   .globl _zimage_start
+_zimage_start:
+   b _zimage_start_lib
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index d27a25518b01..5889c440a66a 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -152,7 +152,7 @@ of)
 make_space=n
 ;;
 pseries)
-platformo="$object/of.o $object/epapr.o"
+platformo="$object/pseries-head.o $object/of.o $object/epapr.o"
 link_address='0x400'
 make_space=n
 ;;
-- 
1.7.10.4

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

[PATCH v2 15/15] powerpc/boot: add support for 64bit little endian wrapper

2014-04-24 Thread Cédric Le Goater
The code is only slightly modified : entry points now use the
FIXUP_ENDIAN trampoline to switch endian order. The 32bit wrapper
is kept for big endian kernels and 64bit is enforced for little
endian kernels with a PPC64_BOOT_WRAPPER config option.

The linker script is generated using the kernel preprocessor flags
to make use of the CONFIG_* definitions and the wrapper script is
modified to take into account the new elf64ppc format.

Finally, the zImage file is compiled as a position independent
executable (-pie) which makes it loadable at any address by the
firmware.

Signed-off-by: Cédric Le Goater 
---

Changes since v1:

 - merge last 3 patches to preserve bisectability 

 arch/powerpc/boot/Makefile |   16 +---
 arch/powerpc/boot/crt0.S   |1 +
 arch/powerpc/boot/ppc_asm.h|   12 
 arch/powerpc/boot/pseries-head.S   |3 +++
 arch/powerpc/boot/wrapper  |   15 ++-
 arch/powerpc/boot/zImage.lds.S |   25 -
 arch/powerpc/platforms/Kconfig.cputype |5 +
 7 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index bed660ddf48c..a33c23308e97 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -22,8 +22,14 @@ all: $(obj)/zImage
 BOOTCFLAGS:= -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
 -fno-strict-aliasing -Os -msoft-float -pipe \
 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
--isystem $(shell $(CROSS32CC) -print-file-name=include) \
--mbig-endian
+-isystem $(shell $(CROSS32CC) -print-file-name=include)
+ifdef CONFIG_PPC64_BOOT_WRAPPER
+BOOTCFLAGS += -m64
+endif
+ifdef CONFIG_CPU_BIG_ENDIAN
+BOOTCFLAGS += -mbig-endian
+endif
+
 BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 
 ifdef CONFIG_DEBUG_INFO
@@ -142,7 +148,11 @@ $(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: 
$(srctree)/scripts/dtc
 $(obj)/empty.c:
@touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: 
$(srctree)/$(src)/%.S
+$(obj)/zImage.lds: $(obj)/%: $(srctree)/$(src)/%.S
+   $(CROSS32CC) $(cpp_flags) -E -Wp,-MD,$(depfile) -P -Upowerpc \
+   -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+$(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 689290561e69..14de4f8778a7 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -275,6 +275,7 @@ prom:
rfid
 
 1: /* Return from OF */
+   FIXUP_ENDIAN
 
/* Restore registers and return. */
rldicl  r1,r1,0,32
diff --git a/arch/powerpc/boot/ppc_asm.h b/arch/powerpc/boot/ppc_asm.h
index eb0e98be69e0..35ea60c1f070 100644
--- a/arch/powerpc/boot/ppc_asm.h
+++ b/arch/powerpc/boot/ppc_asm.h
@@ -62,4 +62,16 @@
 #define SPRN_TBRL  268
 #define SPRN_TBRU  269
 
+#define FIXUP_ENDIAN  \
+   tdi   0, 0, 0x48; /* Reverse endian of b . + 8  */ \
+   b $+36;   /* Skip trampoline if endian is good  */ \
+   .long 0x05009f42; /* bcl 20,31,$+4  */ \
+   .long 0xa602487d; /* mflr r10   */ \
+   .long 0x1c004a39; /* addi r10,r10,28*/ \
+   .long 0xa600607d; /* mfmsr r11  */ \
+   .long 0x01006b69; /* xori r11,r11,1 */ \
+   .long 0xa6035a7d; /* mtsrr0 r10 */ \
+   .long 0xa6037b7d; /* mtsrr1 r11 */ \
+   .long 0x244c  /* rfid   */
+
 #endif /* _PPC64_PPC_ASM_H */
diff --git a/arch/powerpc/boot/pseries-head.S b/arch/powerpc/boot/pseries-head.S
index 655c3d2c321b..6ef6e02e80f9 100644
--- a/arch/powerpc/boot/pseries-head.S
+++ b/arch/powerpc/boot/pseries-head.S
@@ -1,5 +1,8 @@
+#include "ppc_asm.h"
+
.text
 
.globl _zimage_start
 _zimage_start:
+   FIXUP_ENDIAN
b _zimage_start_lib
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 5889c440a66a..1948cf8b8a40 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -40,6 +40,7 @@ cacheit=
 binary=
 gzip=.gz
 pie=
+format=
 
 # cross-compilation prefix
 CROSS=
@@ -136,6 +137,14 @@ if [ -z "$kernel" ]; then
 kernel=vmlinux
 fi
 
+elfformat="`${CROSS}objdump -p "$kernel" | grep 'file format' | awk '{print 
$4}'`"
+case "$elfformat" in
+elf64-powerpcle)   format=elf64lppc;;
+elf64-powerpc) format=elf32ppc ;;
+elf32-powerpc) format=elf32ppc ;;
+esac
+
+
 platformo=$object/"$platform".o
 lds=$object/zImage.lds
 ext=strip
@@ -154,6 +163,10 @@ of)
 pseries)
 platformo="$obje

[PATCH v2 11/15] powerpc/boot: add little endian support to elf utils

2014-04-24 Thread Cédric Le Goater
Signed-off-by: Cédric Le Goater 
---
 arch/powerpc/boot/elf_util.c |4 
 1 file changed, 4 insertions(+)

diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c
index 1567a0c0f05c..316552dea4d8 100644
--- a/arch/powerpc/boot/elf_util.c
+++ b/arch/powerpc/boot/elf_util.c
@@ -26,7 +26,11 @@ int parse_elf64(void *hdr, struct elf_info *info)
  elf64->e_ident[EI_MAG2]  == ELFMAG2   &&
  elf64->e_ident[EI_MAG3]  == ELFMAG3   &&
  elf64->e_ident[EI_CLASS] == ELFCLASS64&&
+#ifdef __LITTLE_ENDIAN__
+ elf64->e_ident[EI_DATA]  == ELFDATA2LSB   &&
+#else
  elf64->e_ident[EI_DATA]  == ELFDATA2MSB   &&
+#endif
  (elf64->e_type== ET_EXEC ||
   elf64->e_type== ET_DYN)  &&
  elf64->e_machine == EM_PPC64))
-- 
1.7.10.4

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

[PATCH 0/5] powerpc/powernv: OPAL sysparam sysfs fixes

2014-04-24 Thread Joel Stanley
These fix the issues I saw when testing the sysparam sysfs API. As some of the
parameters are not available on the machine I was using, the error paths in the
sysfs and OPAL code are tested, and were found to have some bugs.

Joel Stanley (5):
  powerpc/powernv: Fix sysparam sysfs error handling
  powerpc/powernv: Use ssize_t for sysparam return values
  powerpc/powernv: Check sysfs size before copying
  powerpc/powernv: Fix typos in sysparam code
  powerpc/powernv: Check sysparam size before creation

 arch/powerpc/platforms/powernv/opal-sysparam.c | 32 ++
 1 file changed, 23 insertions(+), 9 deletions(-)

-- 
1.9.1

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

[PATCH 1/5] powerpc/powernv: Fix sysparam sysfs error handling

2014-04-24 Thread Joel Stanley
When a sysparam query in OPAL returned a negative value (error code),
sysfs would spew out a decent chunk of memory; almost 64K more than
expected. This was traced to a sign/unsigned mix up in the OPAL sysparam
sysfs code at sys_param_show.

The return value of sys_param_show is a ssize_t, calculated using

  return ret ? ret : attr->param_size;

Alan Modra explains:

  "attr->param_size" is an unsigned int, "ret" an int, so the overall
  expression has type unsigned int.  Result is that ret is cast to
  unsigned int before being cast to ssize_t.

Instead of using the ternary operator, set ret to the param_size if an
error is not detected. The same bug exists in the sysfs write callback;
this patch fixes it in the same way.

A note on debugging this next time: on my system gcc will warn about
this if compiled with -Wsign-compare, which is not enabled by -Wall,
only -Wextra.

Signed-off-by: Joel Stanley 
---
 arch/powerpc/platforms/powernv/opal-sysparam.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c 
b/arch/powerpc/platforms/powernv/opal-sysparam.c
index 0bd249a..cdaf145 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -121,9 +121,10 @@ static ssize_t sys_param_show(struct kobject *kobj,
 
memcpy(buf, param_data_buf, attr->param_size);
 
+   ret = attr->param_size;
 out:
mutex_unlock(&opal_sysparam_mutex);
-   return ret ? ret : attr->param_size;
+   return ret;
 }
 
 static ssize_t sys_param_store(struct kobject *kobj,
@@ -138,7 +139,9 @@ static ssize_t sys_param_store(struct kobject *kobj,
ret = opal_set_sys_param(attr->param_id, attr->param_size,
param_data_buf);
mutex_unlock(&opal_sysparam_mutex);
-   return ret ? ret : count;
+   if (!ret)
+   ret = count;
+   return ret;
 }
 
 void __init opal_sys_param_init(void)
-- 
1.9.1

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

[PATCH 2/5] powerpc/powernv: Use ssize_t for sysparam return values

2014-04-24 Thread Joel Stanley
The OPAL calls are returning int64_t values, which the sysparam code
stores in an int, and the sysfs callback returns ssize_t. Make code a
easier to read by consistently using ssize_t.

Signed-off-by: Joel Stanley 
---
 arch/powerpc/platforms/powernv/opal-sysparam.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c 
b/arch/powerpc/platforms/powernv/opal-sysparam.c
index cdaf145..a363c53 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -39,10 +39,11 @@ struct param_attr {
struct kobj_attribute kobj_attr;
 };
 
-static int opal_get_sys_param(u32 param_id, u32 length, void *buffer)
+static ssize_t opal_get_sys_param(u32 param_id, u32 length, void *buffer)
 {
struct opal_msg msg;
-   int ret, token;
+   ssize_t ret;
+   int token;
 
token = opal_async_get_token_interruptible();
if (token < 0) {
@@ -59,7 +60,7 @@ static int opal_get_sys_param(u32 param_id, u32 length, void 
*buffer)
 
ret = opal_async_wait_response(token, &msg);
if (ret) {
-   pr_err("%s: Failed to wait for the async response, %d\n",
+   pr_err("%s: Failed to wait for the async response, %zd\n",
__func__, ret);
goto out_token;
}
@@ -111,7 +112,7 @@ static ssize_t sys_param_show(struct kobject *kobj,
 {
struct param_attr *attr = container_of(kobj_attr, struct param_attr,
kobj_attr);
-   int ret;
+   ssize_t ret;
 
mutex_lock(&opal_sysparam_mutex);
ret = opal_get_sys_param(attr->param_id, attr->param_size,
@@ -132,7 +133,7 @@ static ssize_t sys_param_store(struct kobject *kobj,
 {
struct param_attr *attr = container_of(kobj_attr, struct param_attr,
kobj_attr);
-   int ret;
+   ssize_t ret;
 
mutex_lock(&opal_sysparam_mutex);
memcpy(param_data_buf, buf, count);
-- 
1.9.1

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

[PATCH 3/5] powerpc/powernv: Check sysfs size before copying

2014-04-24 Thread Joel Stanley
The sysparam code currently uses the userspace supplied number of
bytes when memcpy()ing in to a local 64-byte buffer.

Limit the maximum number of bytes by the size of the buffer.
---
 arch/powerpc/platforms/powernv/opal-sysparam.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c 
b/arch/powerpc/platforms/powernv/opal-sysparam.c
index a363c53..21fdc0a 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -135,6 +135,10 @@ static ssize_t sys_param_store(struct kobject *kobj,
kobj_attr);
ssize_t ret;
 
+/* MAX_PARAM_DATA_LEN is sizeof(param_data_buf) */
+if (count > MAX_PARAM_DATA_LEN)
+count = MAX_PARAM_DATA_LEN;
+
mutex_lock(&opal_sysparam_mutex);
memcpy(param_data_buf, buf, count);
ret = opal_set_sys_param(attr->param_id, attr->param_size,
-- 
1.9.1

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

[PATCH 4/5] powerpc/powernv: Fix typos in sysparam code

2014-04-24 Thread Joel Stanley
---
 arch/powerpc/platforms/powernv/opal-sysparam.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c 
b/arch/powerpc/platforms/powernv/opal-sysparam.c
index 21fdc0a..4b3367b 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -222,13 +222,13 @@ void __init opal_sys_param_init(void)
}
 
if (of_property_read_u32_array(sysparam, "param-len", size, count)) {
-   pr_err("SYSPARAM: Missing propery param-len in the DT\n");
+   pr_err("SYSPARAM: Missing property param-len in the DT\n");
goto out_free_perm;
}
 
 
if (of_property_read_u8_array(sysparam, "param-perm", perm, count)) {
-   pr_err("SYSPARAM: Missing propery param-perm in the DT\n");
+   pr_err("SYSPARAM: Missing property param-perm in the DT\n");
goto out_free_perm;
}
 
-- 
1.9.1

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

[PATCH 5/5] powerpc/powernv: Check sysparam size before creation

2014-04-24 Thread Joel Stanley
The size of the sysparam sysfs files is determined from the device tree
at boot. However the buffer is hard coded to 64 bytes. If we encounter a
parameter that is larger than 64, or miss-parse the device tree, the
buffer will overflow when reading or writing to the parameter.

Check it at discovery time, and if the parameter is too large, do not
create a sysfs entry for it.

Signed-off-by: Joel Stanley 
---
 arch/powerpc/platforms/powernv/opal-sysparam.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c 
b/arch/powerpc/platforms/powernv/opal-sysparam.c
index 4b3367b..14231a5 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -241,6 +241,12 @@ void __init opal_sys_param_init(void)
 
/* For each of the parameters, populate the parameter attributes */
for (i = 0; i < count; i++) {
+   if (size[i] > MAX_PARAM_DATA_LEN) {
+   pr_warn("SYSPARAM: Not creating parameter %d as size "
+   "exceeds buffer length\n", i);
+   continue;
+   }
+
sysfs_attr_init(&attr[i].kobj_attr.attr);
attr[i].param_id = id[i];
attr[i].param_size = size[i];
-- 
1.9.1

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

[PATCH 03/25] powerpc/powernv: Move PNV_EEH_STATE_ENABLED around

2014-04-24 Thread Gavin Shan
The flag PNV_EEH_STATE_ENABLED is put into pnv_phb::eeh_state,
which is protected by CONFIG_EEH. We needn't that. Instead, we
can have pnv_phb::flags and maintain all flags there, which is
the purpose of the patch. The patch also renames PNV_EEH_STATE_ENABLED
to PNV_PHB_FLAG_EEH.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 2 +-
 arch/powerpc/platforms/powernv/pci.c  | 8 ++--
 arch/powerpc/platforms/powernv/pci.h  | 7 +++
 3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 5432598..9ff7b2d 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -154,7 +154,7 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
}
 #endif
 
-   phb->eeh_state |= PNV_EEH_STATE_ENABLED;
+   phb->flags |= PNV_PHB_FLAG_EEH;
 
return 0;
 }
diff --git a/arch/powerpc/platforms/powernv/pci.c 
b/arch/powerpc/platforms/powernv/pci.c
index 8518817..114e1a7 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -426,7 +426,7 @@ int pnv_pci_cfg_read(struct device_node *dn,
if (phb_pe && (phb_pe->state & EEH_PE_ISOLATED))
return PCIBIOS_SUCCESSFUL;
 
-   if (phb->eeh_state & PNV_EEH_STATE_ENABLED) {
+   if (phb->flags & PNV_PHB_FLAG_EEH) {
if (*val == EEH_IO_ERROR_VALUE(size) &&
eeh_dev_check_failure(of_node_to_eeh_dev(dn)))
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -464,12 +464,8 @@ int pnv_pci_cfg_write(struct device_node *dn,
}
 
/* Check if the PHB got frozen due to an error (no response) */
-#ifdef CONFIG_EEH
-   if (!(phb->eeh_state & PNV_EEH_STATE_ENABLED))
+   if (!(phb->flags & PNV_PHB_FLAG_EEH))
pnv_pci_config_check_eeh(phb, dn);
-#else
-   pnv_pci_config_check_eeh(phb, dn);
-#endif
 
return PCIBIOS_SUCCESSFUL;
 }
diff --git a/arch/powerpc/platforms/powernv/pci.h 
b/arch/powerpc/platforms/powernv/pci.h
index 6870f60..94e3495 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -81,24 +81,23 @@ struct pnv_eeh_ops {
int (*configure_bridge)(struct eeh_pe *pe);
int (*next_error)(struct eeh_pe **pe);
 };
-
-#define PNV_EEH_STATE_ENABLED  (1 << 0)/* EEH enabled  */
-
 #endif /* CONFIG_EEH */
 
+#define PNV_PHB_FLAG_EEH   (1 << 0)
+
 struct pnv_phb {
struct pci_controller   *hose;
enum pnv_phb_type   type;
enum pnv_phb_model  model;
u64 hub_id;
u64 opal_id;
+   int flags;
void __iomem*regs;
int initialized;
spinlock_t  lock;
 
 #ifdef CONFIG_EEH
struct pnv_eeh_ops  *eeh_ops;
-   int eeh_state;
 #endif
 
 #ifdef CONFIG_DEBUG_FS
-- 
1.8.3.2

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

[PATCH 01/25] powerpc/eeh: Remove EEH_PE_PHB_DEAD

2014-04-24 Thread Gavin Shan
The PE state (for eeh_pe instance) EEH_PE_PHB_DEAD is duplicate to
EEH_PE_ISOLATED. Originally, those PHBs (PHB PE) with EEH_PE_PHB_DEAD
would be removed from the system. However, it's safe to replace
that with EEH_PE_ISOLATED.

The patch also clear EEH_PE_RECOVERING after fenced PHB has been handled,
either failure or success. It makes the PHB PE state consistent with:

PHB functions normallyNONE
PHB has been removed  EEH_PE_ISOLATED
PHB fenced, recovery in progress  EEH_PE_ISOLATED | RECOVERING

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h   |  1 -
 arch/powerpc/kernel/eeh.c| 10 ++
 arch/powerpc/kernel/eeh_driver.c | 10 +-
 3 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index d4dd41f..a61b06f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -53,7 +53,6 @@ struct device_node;
 
 #define EEH_PE_ISOLATED(1 << 0)/* Isolated PE  
*/
 #define EEH_PE_RECOVERING  (1 << 1)/* Recovering PE*/
-#define EEH_PE_PHB_DEAD(1 << 2)/* Dead PHB 
*/
 
 #define EEH_PE_KEEP(1 << 8)/* Keep PE on hotplug   */
 
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index e7b76a6..f167676 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -232,7 +232,6 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 {
size_t loglen = 0;
struct eeh_dev *edev, *tmp;
-   bool valid_cfg_log = true;
 
/*
 * When the PHB is fenced or dead, it's pointless to collect
@@ -240,12 +239,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 * 0xFF's. For ER, we still retrieve the data from the PCI
 * config space.
 */
-   if (eeh_probe_mode_dev() &&
-   (pe->type & EEH_PE_PHB) &&
-   (pe->state & (EEH_PE_ISOLATED | EEH_PE_PHB_DEAD)))
-   valid_cfg_log = false;
-
-   if (valid_cfg_log) {
+   if (!(pe->type & EEH_PE_PHB)) {
eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
eeh_ops->configure_bridge(pe);
eeh_pe_restore_bars(pe);
@@ -309,7 +303,7 @@ static int eeh_phb_check_failure(struct eeh_pe *pe)
 
/* If the PHB has been in problematic state */
eeh_serialize_lock(&flags);
-   if (phb_pe->state & (EEH_PE_ISOLATED | EEH_PE_PHB_DEAD)) {
+   if (phb_pe->state & EEH_PE_ISOLATED) {
ret = 0;
goto out;
}
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index bb61ca5..1ddc046 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -682,8 +682,7 @@ static void eeh_handle_special_event(void)
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe) continue;
 
-   eeh_pe_state_mark(phb_pe,
-   EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+   eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED);
}
 
eeh_serialize_unlock(flags);
@@ -699,8 +698,7 @@ static void eeh_handle_special_event(void)
eeh_remove_event(pe);
 
if (rc == EEH_NEXT_ERR_DEAD_PHB)
-   eeh_pe_state_mark(pe,
-   EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+   eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
else
eeh_pe_state_mark(pe,
EEH_PE_ISOLATED | EEH_PE_RECOVERING);
@@ -724,12 +722,14 @@ static void eeh_handle_special_event(void)
if (rc == EEH_NEXT_ERR_FROZEN_PE ||
rc == EEH_NEXT_ERR_FENCED_PHB) {
eeh_handle_normal_event(pe);
+   eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
} else {
pci_lock_rescan_remove();
list_for_each_entry(hose, &hose_list, list_node) {
phb_pe = eeh_phb_pe_get(hose);
if (!phb_pe ||
-   !(phb_pe->state & EEH_PE_PHB_DEAD))
+   !(phb_pe->state & EEH_PE_ISOLATED) ||
+   (phb_pe->state & EEH_PE_RECOVERING))
continue;
 
/* Notify all devices to be down */
-- 
1.8.3.2

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

[PATCH 00/25] EEH Enhancement and bug fixes

2014-04-24 Thread Gavin Shan
The series of patches enhances EEH to block I/O and PCI-CFG access during
PE reset. Besides, it includes various bug fixes regarding EEH.

Gavin Shan (25):
  powerpc/eeh: Remove EEH_PE_PHB_DEAD
  powerpc/powernv: Remove PNV_EEH_STATE_REMOVED
  powerpc/powernv: Move PNV_EEH_STATE_ENABLED around
  powerpc/powernv: Remove fields in PHB diag-data dump
  powerpc/eeh: EEH_PE_ISOLATED not reflect HW state
  powerpc/eeh: Block PCI-CFG access during PE reset
  powerpc/powernv: Use EEH PCI config accessors
  powerpc/eeh: Avoid I/O access during PE reset
  powerpc/eeh: Cleanup eeh_gather_pci_data()
  powerpc/eeh: Use cached capability for log dump
  powerpc/eeh: Cleanup EEH subsystem variables
  powerpc/eeh: Allow to disable EEH
  powerpc/eeh: No hotplug on permanently removed dev
  powerpc/powernv: Fix endless reporting frozen PE
  powerpc/pseries: Fix overwritten PE state
  powerpc/powernv: Reset root port in firmware
  powerpc/eeh: Make the delay for PE reset unified
  powerpc/pci: Mask linkDown on resetting PCI bus
  powrpc/powernv: Reset PHB in kdump kernel
  powerpc/eeh: Can't recover from non-PE-reset case
  powerpc/powernv: Fundamental reset on PLX ports
  powerpc/powernv: Missed IOMMU table type
  powerpc/powernv: pci_domain_nr() not reliable
  PCI: Fix return value from pci_user_{read,write}_config_*()
  powerpc/prom: Stop scanning dev-tree for fdump early

 arch/powerpc/include/asm/eeh.h   |  47 +++-
 arch/powerpc/include/asm/machdep.h   |   3 +
 arch/powerpc/include/asm/ppc-pci.h   |   1 +
 arch/powerpc/kernel/eeh.c| 211 +---
 arch/powerpc/kernel/eeh_driver.c | 118 +++--
 arch/powerpc/kernel/eeh_pe.c |  47 +++-
 arch/powerpc/kernel/fadump.c |   5 +-
 arch/powerpc/kernel/pci-common.c |  20 ++
 arch/powerpc/kernel/pci_of_scan.c|   9 +
 arch/powerpc/kernel/rtas_pci.c   |  66 +++--
 arch/powerpc/platforms/powernv/eeh-ioda.c| 349 +--
 arch/powerpc/platforms/powernv/eeh-powernv.c |   4 +
 arch/powerpc/platforms/powernv/pci-ioda.c|  26 +-
 arch/powerpc/platforms/powernv/pci.c | 202 +---
 arch/powerpc/platforms/powernv/pci.h |  11 +-
 arch/powerpc/platforms/pseries/eeh_pseries.c |  43 +++-
 drivers/pci/access.c |  12 +-
 drivers/pci/pci.c|  21 +-
 include/linux/pci.h  |   6 +-
 19 files changed, 811 insertions(+), 390 deletions(-)

Thanks,
Gavin

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

[PATCH 04/25] powerpc/powernv: Remove fields in PHB diag-data dump

2014-04-24 Thread Gavin Shan
For some fields (e.g. LEM, MMIO, DMA) in PHB diag-data dump, it's
meaningless to print them if they have non-zero value in the
corresponding mask registers because we always have non-zero values
in the mask registers. The patch only prints those fieds if we
have non-zero values in the primary registers (e.g. LEM, MMIO, DMA
status) so that we can save couple of lines. The patch also removes
unnecessary spare line before "brdgCtl:" and two leading spaces as
prefix in each line as Ben suggested.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/pci.c | 91 
 1 file changed, 40 insertions(+), 51 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/pci.c 
b/arch/powerpc/platforms/powernv/pci.c
index 114e1a7..2de283d 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -131,65 +131,60 @@ static void pnv_pci_dump_p7ioc_diag_data(struct 
pci_controller *hose,
int i;
 
data = (struct OpalIoP7IOCPhbErrorData *)common;
-   pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
+   pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n",
hose->global_number, common->version);
 
if (data->brdgCtl)
-   pr_info("  brdgCtl: %08x\n",
+   pr_info("brdgCtl: %08x\n",
data->brdgCtl);
if (data->portStatusReg || data->rootCmplxStatus ||
data->busAgentStatus)
-   pr_info("  UtlSts:  %08x %08x %08x\n",
+   pr_info("UtlSts:  %08x %08x %08x\n",
data->portStatusReg, data->rootCmplxStatus,
data->busAgentStatus);
if (data->deviceStatus || data->slotStatus   ||
data->linkStatus   || data->devCmdStatus ||
data->devSecStatus)
-   pr_info("  RootSts: %08x %08x %08x %08x %08x\n",
+   pr_info("RootSts: %08x %08x %08x %08x %08x\n",
data->deviceStatus, data->slotStatus,
data->linkStatus, data->devCmdStatus,
data->devSecStatus);
if (data->rootErrorStatus   || data->uncorrErrorStatus ||
data->corrErrorStatus)
-   pr_info("  RootErrSts:  %08x %08x %08x\n",
+   pr_info("RootErrSts:  %08x %08x %08x\n",
data->rootErrorStatus, data->uncorrErrorStatus,
data->corrErrorStatus);
if (data->tlpHdr1 || data->tlpHdr2 ||
data->tlpHdr3 || data->tlpHdr4)
-   pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+   pr_info("RootErrLog:  %08x %08x %08x %08x\n",
data->tlpHdr1, data->tlpHdr2,
data->tlpHdr3, data->tlpHdr4);
if (data->sourceId || data->errorClass ||
data->correlator)
-   pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+   pr_info("RootErrLog1: %08x %016llx %016llx\n",
data->sourceId, data->errorClass,
data->correlator);
if (data->p7iocPlssr || data->p7iocCsr)
-   pr_info("  PhbSts:  %016llx %016llx\n",
+   pr_info("PhbSts:  %016llx %016llx\n",
data->p7iocPlssr, data->p7iocCsr);
-   if (data->lemFir || data->lemErrorMask ||
-   data->lemWOF)
-   pr_info("  Lem: %016llx %016llx %016llx\n",
+   if (data->lemFir)
+   pr_info("Lem: %016llx %016llx %016llx\n",
data->lemFir, data->lemErrorMask,
data->lemWOF);
-   if (data->phbErrorStatus || data->phbFirstErrorStatus ||
-   data->phbErrorLog0   || data->phbErrorLog1)
-   pr_info("  PhbErr:  %016llx %016llx %016llx %016llx\n",
+   if (data->phbErrorStatus)
+   pr_info("PhbErr:  %016llx %016llx %016llx %016llx\n",
data->phbErrorStatus, data->phbFirstErrorStatus,
data->phbErrorLog0, data->phbErrorLog1);
-   if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
-   data->mmioErrorLog0   || data->mmioErrorLog1)
-   pr_info("  OutErr:  %016llx %016llx %016llx %016llx\n",
+   if (data->mmioErrorStatus)
+   pr_info("OutErr:  %016llx %016llx %016llx %016llx\n",
data->mmioErrorStatus, data->mmioFirstErrorStatus,
data->mmioErrorLog0, data->mmioErrorLog1);
-   if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
-   data->dma0ErrorLog0   || data->dma0ErrorLog1)
-   pr_info("  InAErr:  %016llx %016llx %016llx %016llx\n",
+   if (data->dma0ErrorStatus)
+   pr_info("InAErr:  %016llx %016llx %016llx %016llx\n",
data->dma0ErrorStatus, data->dma0FirstErrorStatus,
data->dma0ErrorLog0

[PATCH 09/25] powerpc/eeh: Cleanup eeh_gather_pci_data()

2014-04-24 Thread Gavin Shan
The patch replaces printk(KERN_WARNING ...) with pr_warn() in the
function eeh_gather_pci_data().

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/eeh.c | 27 +--
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 25f3753..c6d8f7e 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -151,18 +151,18 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
int n = 0;
 
n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
-   printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name);
+   pr_warn("EEH: of node=%s\n", dn->full_name);
 
eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg);
n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
-   printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);
+   pr_warn("EEH: PCI device/vendor: %08x\n", cfg);
 
eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg);
n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
-   printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);
+   pr_warn("EEH: PCI cmd/status register: %08x\n", cfg);
 
if (!dev) {
-   printk(KERN_WARNING "EEH: no PCI device for this of node\n");
+   pr_warn("EEH: no PCI device for this of node\n");
return n;
}
 
@@ -170,11 +170,11 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);
n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
-   printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", 
cfg);
+   pr_warn("EEH: Bridge secondary status: %04x\n", cfg);
 
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg);
n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
-   printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg);
+   pr_warn("EEH: Bridge control: %04x\n", cfg);
}
 
/* Dump out the PCI-X command and status regs */
@@ -182,35 +182,34 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
if (cap) {
eeh_ops->read_config(dn, cap, 4, &cfg);
n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
-   printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);
+   pr_warn("EEH: PCI-X cmd: %08x\n", cfg);
 
eeh_ops->read_config(dn, cap+4, 4, &cfg);
n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
-   printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);
+   pr_warn("EEH: PCI-X status: %08x\n", cfg);
}
 
/* If PCI-E capable, dump PCI-E cap 10, and the AER */
if (pci_is_pcie(dev)) {
n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
-   printk(KERN_WARNING
-  "EEH: PCI-E capabilities and status follow:\n");
+   pr_warn("EEH: PCI-E capabilities and status follow:\n");
 
for (i=0; i<=8; i++) {
eeh_ops->read_config(dn, dev->pcie_cap+4*i, 4, &cfg);
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
-   printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
+   pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg);
}
 
cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (cap) {
n += scnprintf(buf+n, len-n, "pci-e AER:\n");
-   printk(KERN_WARNING
-  "EEH: PCI-E AER capability register set 
follows:\n");
+   pr_warn("EEH: PCI-E AER capability register "
+   "set follows:\n");
 
for (i=0; i<14; i++) {
eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, 
cfg);
-   printk(KERN_WARNING "EEH: PCI-E AER %02x: 
%08x\n", i, cfg);
+   pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg);
}
}
}
-- 
1.8.3.2

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

[PATCH 07/25] powerpc/powernv: Use EEH PCI config accessors

2014-04-24 Thread Gavin Shan
For EEH PowerNV backends, they need use their own PCI config
accesors as the normal one could be blocked during PE reset.
The patch also removes necessary parameter "hose" for the
function ioda_eeh_bridge_reset().

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 9ff7b2d..ed6c686 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -478,26 +478,27 @@ out:
return 0;
 }
 
-static int ioda_eeh_bridge_reset(struct pci_controller *hose,
-   struct pci_dev *dev, int option)
+static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
+
 {
-   u16 ctrl;
+   struct device_node *dn = pci_device_to_OF_node(dev);
+   u32 ctrl;
 
-   pr_debug("%s: Reset device %04x:%02x:%02x.%01x with option %d\n",
-__func__, hose->global_number, dev->bus->number,
-PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), option);
+   pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
+__func__, pci_domain_nr(dev->bus),
+dev->bus->number, option);
 
switch (option) {
case EEH_RESET_FUNDAMENTAL:
case EEH_RESET_HOT:
-   pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
+   eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
-   pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+   eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
break;
case EEH_RESET_DEACTIVATE:
-   pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
+   eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
-   pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+   eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
break;
}
 
@@ -552,7 +553,7 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
if (pci_is_root_bus(bus))
ret = ioda_eeh_root_reset(hose, option);
else
-   ret = ioda_eeh_bridge_reset(hose, bus->self, option);
+   ret = ioda_eeh_bridge_reset(bus->self, option);
}
 
return ret;
-- 
1.8.3.2

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

[PATCH 02/25] powerpc/powernv: Remove PNV_EEH_STATE_REMOVED

2014-04-24 Thread Gavin Shan
The PHB state PNV_EEH_STATE_REMOVED maintained in pnv_phb isn't
so useful any more and it's duplicated to EEH_PE_ISOLATED. The
patch replaces PNV_EEH_STATE_REMOVED with EEH_PE_ISOLATED.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 56 +--
 arch/powerpc/platforms/powernv/pci.h  |  1 -
 2 files changed, 15 insertions(+), 42 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 253fefe..5432598 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -639,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
}
 }
 
-static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
-  struct eeh_pe **pe)
-{
-   struct eeh_pe *phb_pe;
-
-   phb_pe = eeh_phb_pe_get(hose);
-   if (!phb_pe) {
-   pr_warning("%s Can't find PE for PHB#%d\n",
-  __func__, hose->global_number);
-   return -EEXIST;
-   }
-
-   *pe = phb_pe;
-   return 0;
-}
-
 static int ioda_eeh_get_pe(struct pci_controller *hose,
   u16 pe_no, struct eeh_pe **pe)
 {
@@ -662,7 +646,8 @@ static int ioda_eeh_get_pe(struct pci_controller *hose,
struct eeh_dev dev;
 
/* Find the PHB PE */
-   if (ioda_eeh_get_phb_pe(hose, &phb_pe))
+   phb_pe = eeh_phb_pe_get(hose);
+   if (!phb_pe)
return -EEXIST;
 
/* Find the PE according to PE# */
@@ -690,6 +675,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 {
struct pci_controller *hose;
struct pnv_phb *phb;
+   struct eeh_pe *phb_pe;
u64 frozen_pe_no;
u16 err_type, severity;
long rc;
@@ -706,10 +692,12 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
list_for_each_entry(hose, &hose_list, list_node) {
/*
 * If the subordinate PCI buses of the PHB has been
-* removed, we needn't take care of it any more.
+* removed or is exactly under error recovery, we
+* needn't take care of it any more.
 */
phb = hose->private_data;
-   if (phb->eeh_state & PNV_EEH_STATE_REMOVED)
+   phb_pe = eeh_phb_pe_get(hose);
+   if (!phb_pe || (phb_pe->state & EEH_PE_ISOLATED))
continue;
 
rc = opal_pci_next_error(phb->opal_id,
@@ -742,12 +730,6 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
switch (err_type) {
case OPAL_EEH_IOC_ERROR:
if (severity == OPAL_EEH_SEV_IOC_DEAD) {
-   list_for_each_entry(hose, &hose_list,
-   list_node) {
-   phb = hose->private_data;
-   phb->eeh_state |= PNV_EEH_STATE_REMOVED;
-   }
-
pr_err("EEH: dead IOC detected\n");
ret = EEH_NEXT_ERR_DEAD_IOC;
} else if (severity == OPAL_EEH_SEV_INF) {
@@ -760,17 +742,12 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
break;
case OPAL_EEH_PHB_ERROR:
if (severity == OPAL_EEH_SEV_PHB_DEAD) {
-   if (ioda_eeh_get_phb_pe(hose, pe))
-   break;
-
+   *pe = phb_pe;
pr_err("EEH: dead PHB#%x detected\n",
hose->global_number);
-   phb->eeh_state |= PNV_EEH_STATE_REMOVED;
ret = EEH_NEXT_ERR_DEAD_PHB;
} else if (severity == OPAL_EEH_SEV_PHB_FENCED) {
-   if (ioda_eeh_get_phb_pe(hose, pe))
-   break;
-
+   *pe = phb_pe;
pr_err("EEH: fenced PHB#%x detected\n",
hose->global_number);
ret = EEH_NEXT_ERR_FENCED_PHB;
@@ -790,15 +767,12 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 * fenced PHB so that it can be recovered.
 */
if (ioda_eeh_get_pe(hose, frozen_pe_no, pe)) {
-   if (!ioda_eeh_get_phb_pe(hose, pe)) {
-   pr_err("EEH: Escalated fenced PHB#%x "
-  "detected for PE#%llx\n",
-   hose->global_number,
-   frozen_pe_no);
-   ret = EEH_NEX

[PATCH 05/25] powerpc/eeh: EEH_PE_ISOLATED not reflect HW state

2014-04-24 Thread Gavin Shan
When doing PE reset, EEH_PE_ISOLATED is cleared unconditionally.
However, We should remove that if the PE reset has cleared the
frozen state successfully. Otherwise, the flag should be kept.
The patch fixes the issue.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/eeh.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index f167676..cc728e8 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -612,12 +612,6 @@ static void eeh_reset_pe_once(struct eeh_pe *pe)
 #define PCI_BUS_RST_HOLD_TIME_MSEC 250
msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
 
-   /* We might get hit with another EEH freeze as soon as the
-* pci slot reset line is dropped. Make sure we don't miss
-* these, and clear the flag now.
-*/
-   eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
-
eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
 
/* After a PCI slot has been reset, the PCI Express spec requires
@@ -646,8 +640,10 @@ int eeh_reset_pe(struct eeh_pe *pe)
eeh_reset_pe_once(pe);
 
rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-   if ((rc & flags) == flags)
+   if ((rc & flags) == flags) {
+   eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
return 0;
+   }
 
if (rc < 0) {
pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
-- 
1.8.3.2

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

[PATCH 06/25] powerpc/eeh: Block PCI-CFG access during PE reset

2014-04-24 Thread Gavin Shan
We've observed multiple PE reset failures because of PCI-CFG
access during that period. Potentially, some device drivers
can't support EEH very well and they can't put the device to
motionless state before PE reset. So those device drivers might
produce PCI-CFG accesses during PE reset. Also, we could have
PCI-CFG access from user space (e.g. "lspci"). Since access to
frozen PE should return 0xFF's, we can block PCI-CFG access
during the period of PE reset so that we won't get recrusive EEH
errors.

The patch adds flag EEH_PE_RESET, which is kept during PE reset.
The PowerNV/pSeries PCI-CFG accessors reuse the flag to block
PCI-CFG accordingly.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h   |   1 +
 arch/powerpc/kernel/eeh_driver.c |  13 -
 arch/powerpc/kernel/rtas_pci.c   |  66 +--
 arch/powerpc/platforms/powernv/pci.c | 100 ++-
 4 files changed, 126 insertions(+), 54 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index a61b06f..fa32d8d 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -53,6 +53,7 @@ struct device_node;
 
 #define EEH_PE_ISOLATED(1 << 0)/* Isolated PE  
*/
 #define EEH_PE_RECOVERING  (1 << 1)/* Recovering PE*/
+#define EEH_PE_RESET   (1 << 2)/* PE reset in progress */
 
 #define EEH_PE_KEEP(1 << 8)/* Keep PE on hotplug   */
 
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 1ddc046..6d91b51 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -451,19 +451,28 @@ static int eeh_reset_device(struct eeh_pe *pe, struct 
pci_bus *bus)
eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed);
}
 
-   /* Reset the pci controller. (Asserts RST#; resets config space).
+   /*
+* Reset the pci controller. (Asserts RST#; resets config space).
 * Reconfigure bridges and devices. Don't try to bring the system
 * up if the reset failed for some reason.
+*
+* During the reset, it's very dangerous to have uncontrolled PCI
+* config accesses. So we prefer to block them. However, controlled
+* PCI config accesses initiated from EEH itself are allowed.
 */
+   eeh_pe_state_mark(pe, EEH_PE_RESET);
rc = eeh_reset_pe(pe);
-   if (rc)
+   if (rc) {
+   eeh_pe_state_clear(pe, EEH_PE_RESET);
return rc;
+   }
 
pci_lock_rescan_remove();
 
/* Restore PE */
eeh_ops->configure_bridge(pe);
eeh_pe_restore_bars(pe);
+   eeh_pe_state_clear(pe, EEH_PE_RESET);
 
/* Give the system 5 seconds to finish running the user-space
 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 7d4c717..c168337 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -80,10 +80,6 @@ int rtas_read_config(struct pci_dn *pdn, int where, int 
size, u32 *val)
if (ret)
return PCIBIOS_DEVICE_NOT_FOUND;
 
-   if (returnval == EEH_IO_ERROR_VALUE(size) &&
-   eeh_dev_check_failure(of_node_to_eeh_dev(pdn->node)))
-   return PCIBIOS_DEVICE_NOT_FOUND;
-
return PCIBIOS_SUCCESSFUL;
 }
 
@@ -92,18 +88,39 @@ static int rtas_pci_read_config(struct pci_bus *bus,
int where, int size, u32 *val)
 {
struct device_node *busdn, *dn;
-
-   busdn = pci_bus_to_OF_node(bus);
+   struct pci_dn *pdn;
+   bool found = false;
+#ifdef CONFIG_EEH
+   struct eeh_dev *edev;
+#endif
+   int ret;
 
/* Search only direct children of the bus */
+   *val = 0x;
+   busdn = pci_bus_to_OF_node(bus);
for (dn = busdn->child; dn; dn = dn->sibling) {
-   struct pci_dn *pdn = PCI_DN(dn);
+   pdn = PCI_DN(dn);
if (pdn && pdn->devfn == devfn
-   && of_device_is_available(dn))
-   return rtas_read_config(pdn, where, size, val);
+   && of_device_is_available(dn)) {
+   found = true;
+   break;
+   }
}
 
-   return PCIBIOS_DEVICE_NOT_FOUND;
+   if (!found)
+   return PCIBIOS_DEVICE_NOT_FOUND;
+#ifdef CONFIG_EEH
+   edev = of_node_to_eeh_dev(dn);
+   if (edev && edev->pe && edev->pe->state & EEH_PE_RESET)
+   return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+
+   ret = rtas_read_config(pdn, where, size, val);
+   if (*val == EEH_IO_ERROR_VALUE(size) &&
+   eeh_dev_check_failure(of_node_to_eeh_dev(dn)))
+   return PCIBIOS_DEVICE_NOT_FOUND;
+
+   return ret;
 }
 
 int rtas_write_config(struct pci_dn *pdn, int where, int

[PATCH 10/25] powerpc/eeh: Use cached capability for log dump

2014-04-24 Thread Gavin Shan
When calling into eeh_gather_pci_data() on pSeries platform, we
possiblly don't have pci_dev instance yet, but eeh_dev is always
ready. So we use cached capability from eeh_dev instead of pci_dev
for log dump there. In order to keep things unified, we also cache
PCI capability positions to eeh_dev for PowerNV as well.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h   |  4 ++-
 arch/powerpc/kernel/eeh.c| 39 
 arch/powerpc/platforms/powernv/eeh-powernv.c |  4 +++
 arch/powerpc/platforms/pseries/eeh_pseries.c | 32 +++
 4 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index fa32d8d..f0183e3 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -99,7 +99,9 @@ struct eeh_dev {
int config_addr;/* Config address   */
int pe_config_addr; /* PE config address*/
u32 config_space[16];   /* Saved PCI config space   */
-   u8 pcie_cap;/* Saved PCIe capability*/
+   int pcix_cap;   /* Saved PCIx capability*/
+   int pcie_cap;   /* Saved PCIe capability*/
+   int aer_cap;/* Saved AER capability */
struct eeh_pe *pe;  /* Associated PE*/
struct list_head list;  /* Form link list in the PE */
struct pci_controller *phb; /* Associated PHB   */
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index c6d8f7e..69df898 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -145,7 +145,6 @@ static struct eeh_stats eeh_stats;
 static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
 {
struct device_node *dn = eeh_dev_to_of_node(edev);
-   struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
u32 cfg;
int cap, i;
int n = 0;
@@ -161,13 +160,8 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
pr_warn("EEH: PCI cmd/status register: %08x\n", cfg);
 
-   if (!dev) {
-   pr_warn("EEH: no PCI device for this of node\n");
-   return n;
-   }
-
/* Gather bridge-specific registers */
-   if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
+   if (edev->mode & EEH_DEV_BRIDGE) {
eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);
n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
pr_warn("EEH: Bridge secondary status: %04x\n", cfg);
@@ -178,7 +172,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
}
 
/* Dump out the PCI-X command and status regs */
-   cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+   cap = edev->pcix_cap;
if (cap) {
eeh_ops->read_config(dn, cap, 4, &cfg);
n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
@@ -189,28 +183,29 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, 
char * buf, size_t len)
pr_warn("EEH: PCI-X status: %08x\n", cfg);
}
 
-   /* If PCI-E capable, dump PCI-E cap 10, and the AER */
-   if (pci_is_pcie(dev)) {
+   /* If PCI-E capable, dump PCI-E cap 10 */
+   cap = edev->pcie_cap;
+   if (cap) {
n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
pr_warn("EEH: PCI-E capabilities and status follow:\n");
 
for (i=0; i<=8; i++) {
-   eeh_ops->read_config(dn, dev->pcie_cap+4*i, 4, &cfg);
+   eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg);
}
+   }
 
-   cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-   if (cap) {
-   n += scnprintf(buf+n, len-n, "pci-e AER:\n");
-   pr_warn("EEH: PCI-E AER capability register "
-   "set follows:\n");
-
-   for (i=0; i<14; i++) {
-   eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
-   n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, 
cfg);
-   pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg);
-   }
+   /* If AER capable, dump it */
+   cap = edev->aer_cap;
+   if (cap) {
+   n += scnprintf(buf+n, len-n, "pci-e AER:\n");
+   pr_warn("EEH: PCI-E AER capability register set follows:\n");
+
+   for (i=0; i<14; i++) {
+   eeh_ops->read_config(dn, 

[PATCH 08/25] powerpc/eeh: Avoid I/O access during PE reset

2014-04-24 Thread Gavin Shan
We have suffered recrusive frozen PE a lot, which was caused
by IO accesses during the PE reset. Ben came up with the good
idea to keep frozen PE until recovery (BAR restore) gets done.
With that, IO accesses during PE reset are dropped by hardware
and wouldn't incur the recrusive frozen PE any more.

The patch implements the idea. We don't clear the frozen state
until PE reset is done completely. During the period, the EEH
core expects unfrozen state from backend to keep going. So we
have to reuse EEH_PE_RESET flag, which has been set during PE
reset, to return normal state from backend. The side effect is
we have to clear frozen state for towice (PE reset and clear it
explicitly), but that's harmless.

We have some limitations on pHyp. pHyp doesn't allow to enable
IO or DMA for unfrozen PE. So we don't enable them on unfrozen PE
in eeh_pci_enable(). We have to enable IO before grabbing logs on
pHyp. Otherwise, 0xFF's is always returned from PCI config space.
Also, we had wrong return value from eeh_pci_enable() for
EEH_OPT_THAW_DMA case. The patch fixes it too.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/eeh.c | 50 ++
 arch/powerpc/kernel/eeh_driver.c  | 35 +
 arch/powerpc/platforms/powernv/eeh-ioda.c | 84 +--
 3 files changed, 99 insertions(+), 70 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index cc728e8..25f3753 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -238,9 +238,13 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 * the data from PCI config space because it should return
 * 0xFF's. For ER, we still retrieve the data from the PCI
 * config space.
+*
+* For pHyp, we have to enable IO for log retrieval. Otherwise,
+* 0xFF's is always returned from PCI config space.
 */
if (!(pe->type & EEH_PE_PHB)) {
-   eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
+   if (eeh_probe_mode_devtree())
+   eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
eeh_ops->configure_bridge(pe);
eeh_pe_restore_bars(pe);
 
@@ -509,16 +513,42 @@ EXPORT_SYMBOL(eeh_check_failure);
  */
 int eeh_pci_enable(struct eeh_pe *pe, int function)
 {
-   int rc;
+   int rc, flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
+
+   /*
+* pHyp doesn't allow to enable IO or DMA on unfrozen PE.
+* Also, it's pointless to enable them on unfrozen PE. So
+* we have the check here.
+*/
+   if (function == EEH_OPT_THAW_MMIO ||
+   function == EEH_OPT_THAW_DMA) {
+   rc = eeh_ops->get_state(pe, NULL);
+   if (rc < 0)
+   return rc;
+
+   /* Needn't to enable or already enabled */
+   if ((rc == EEH_STATE_NOT_SUPPORT) ||
+   ((rc & flags) == flags))
+   return 0;
+   }
 
rc = eeh_ops->set_option(pe, function);
if (rc)
-   pr_warning("%s: Unexpected state change %d on PHB#%d-PE#%x, 
err=%d\n",
-   __func__, function, pe->phb->global_number, pe->addr, 
rc);
+   pr_warn("%s: Unexpected state change %d on "
+   "PHB#%d-PE#%x, err=%d\n",
+   __func__, function, pe->phb->global_number,
+   pe->addr, rc);
 
rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-   if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
-  (function == EEH_OPT_THAW_MMIO))
+   if (rc <= 0)
+   return rc;
+
+   if ((function == EEH_OPT_THAW_MMIO) &&
+   (rc & EEH_STATE_MMIO_ENABLED))
+   return 0;
+
+   if ((function == EEH_OPT_THAW_DMA) &&
+   (rc & EEH_STATE_DMA_ENABLED))
return 0;
 
return rc;
@@ -639,11 +669,13 @@ int eeh_reset_pe(struct eeh_pe *pe)
for (i=0; i<3; i++) {
eeh_reset_pe_once(pe);
 
+   /*
+* EEH_PE_ISOLATED is expected to be removed after
+* BAR restore.
+*/
rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-   if ((rc & flags) == flags) {
-   eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
+   if ((rc & flags) == flags)
return 0;
-   }
 
if (rc < 0) {
pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 6d91b51..1f1e2cc 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -417,6 +417,36 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
return NULL;
 }
 
+/*
+ * Explicitly clear PE's frozen state for PowerNV where
+ * we have frozen PE until BAR resto

[PATCH 13/25] powerpc/eeh: No hotplug on permanently removed dev

2014-04-24 Thread Gavin Shan
The issue was detected in a bit complicated test case where
we have multiple hierarchical PEs shown as following figure:

+-+
| PE#3 p2p#0  |
|  p2p#1  |
+-+
|
+-+
| PE#4 pdev#0 |
|  pdev#1 |
+-+

PE#4 (have 2 PCI devices) is the child of PE#3, which has 2 p2p
bridges. We accidentally had less-known scenario: PE#4 was removed
permanently from the system because of permanent failure (e.g.
exceeding the max allowd failure times in last hour), then we detects
EEH errors on PE#3 and tried to recover it. However, eeh_dev instances
for pdev#0/1 were not detached from PE#4, which was still connected to
PE#3. All of that was because of the fact that we rely on count-based
pcibios_release_device(), which isn't reliable enough. When doing
recovery for PE#3, we still apply hotplug on PE#4 and pdev#0/1, which
are not valid any more. Eventually, we run into kernel crash.

The patch fixes above issue from two aspects. For unplug, we simply
skip those permanently removed PE, whose state is (EEH_PE_STATE_ISOLATED
&& !EEH_PE_STATE_RECOVERING) and its frozen count should be greater
than EEH_MAX_ALLOWED_FREEZES. For plug, we marked all permanently
removed EEH devices with EEH_DEV_REMOVED and return 0xFF's on read
its PCI config so that PCI core will omit them.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h   |  1 +
 arch/powerpc/include/asm/ppc-pci.h   |  1 +
 arch/powerpc/kernel/eeh_driver.c | 48 ++--
 arch/powerpc/kernel/eeh_pe.c | 47 +--
 arch/powerpc/kernel/pci_of_scan.c|  9 +++
 arch/powerpc/platforms/powernv/pci.c | 13 +++---
 6 files changed, 100 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index f4a9321..2841eca 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -98,6 +98,7 @@ struct eeh_pe {
 
 #define EEH_DEV_NO_HANDLER (1 << 8)/* No error handler */
 #define EEH_DEV_SYSFS  (1 << 9)/* Sysfs created*/
+#define EEH_DEV_REMOVED(1 << 10)   /* Removed permanently  
*/
 
 struct eeh_dev {
int mode;   /* EEH mode */
diff --git a/arch/powerpc/include/asm/ppc-pci.h 
b/arch/powerpc/include/asm/ppc-pci.h
index ed57fa7..db1e2b8 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -58,6 +58,7 @@ int rtas_write_config(struct pci_dn *, int where, int size, 
u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 void eeh_pe_state_mark(struct eeh_pe *pe, int state);
 void eeh_pe_state_clear(struct eeh_pe *pe, int state);
+void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode);
 
 void eeh_sysfs_add_device(struct pci_dev *pdev);
 void eeh_sysfs_remove_device(struct pci_dev *pdev);
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 1f1e2cc..f99ba9b 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -171,6 +171,15 @@ static void eeh_enable_irq(struct pci_dev *dev)
}
 }
 
+static bool eeh_dev_removed(struct eeh_dev *edev)
+{
+   /* EEH device removed ? */
+   if (!edev || (edev->mode & EEH_DEV_REMOVED))
+   return true;
+
+   return false;
+}
+
 /**
  * eeh_report_error - Report pci error to each device driver
  * @data: eeh device
@@ -187,10 +196,8 @@ static void *eeh_report_error(void *data, void *userdata)
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver;
 
-   /* We might not have the associated PCI device,
-* then we should continue for next one.
-*/
-   if (!dev) return NULL;
+   if (!dev || eeh_dev_removed(edev))
+   return NULL;
dev->error_state = pci_channel_io_frozen;
 
driver = eeh_pcid_get(dev);
@@ -230,6 +237,9 @@ static void *eeh_report_mmio_enabled(void *data, void 
*userdata)
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver;
 
+   if (!dev || eeh_dev_removed(edev))
+   return NULL;
+
driver = eeh_pcid_get(dev);
if (!driver) return NULL;
 
@@ -267,7 +277,8 @@ static void *eeh_report_reset(void *data, void *userdata)
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver;
 
-   if (!dev) return NULL;
+   if (!dev || eeh_dev_removed(edev))
+   return NULL;
dev->error_state = pci_channel_io_normal;
 
driver = eeh_pcid_get(dev);
@@ -307,7 +318,8 @@ static void *eeh_report_resume(void *data, void *userdata)
struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
struct pci_driver *driver;
 

[PATCH 14/25] powerpc/powernv: Fix endless reporting frozen PE

2014-04-24 Thread Gavin Shan
Once one specific PE has been marked as EEH_PE_ISOLATED, it's in
the middile of recovery or removed permenently. We needn't report
the frozen PE again. Otherwise, we will have endless reporting
same frozen PE.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 35ec394..3a755b5 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -745,6 +745,11 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 * If we can't find the corresponding PE, the
 * PEEV / PEST would be messy. So we force an
 * fenced PHB so that it can be recovered.
+*
+* If the PE has been marked as isolated, that
+* should have been removed permanently or in
+* progress with recovery. We needn't report
+* it again.
 */
if (ioda_eeh_get_pe(hose, frozen_pe_no, pe)) {
*pe = phb_pe;
@@ -753,6 +758,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
hose->global_number,
frozen_pe_no);
ret = EEH_NEXT_ERR_FENCED_PHB;
+   } else if ((*pe)->state & EEH_PE_ISOLATED) {
+   ret = EEH_NEXT_ERR_NONE;
} else {
pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
(*pe)->addr, (*pe)->phb->global_number);
-- 
1.8.3.2

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

[PATCH 15/25] powerpc/pseries: Fix overwritten PE state

2014-04-24 Thread Gavin Shan
In pseries_eeh_get_state(), EEH_STATE_UNAVAILABLE is always
overwritten by EEH_STATE_NOT_SUPPORT because of the missed
"break" there. The patch fixes the issue.

Reported-by: Joe Perches 
Cc: linux-stable 
Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/pseries/eeh_pseries.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c 
b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 9d58a53..2f1ba64 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -496,6 +496,7 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int 
*state)
} else {
result = EEH_STATE_NOT_SUPPORT;
}
+   break;
default:
result = EEH_STATE_NOT_SUPPORT;
}
-- 
1.8.3.2

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

[PATCH 11/25] powerpc/eeh: Cleanup EEH subsystem variables

2014-04-24 Thread Gavin Shan
There're 2 EEH subsystem variables: eeh_subsystem_enabled and
eeh_probe_mode. We needn't maintain 2 variables and we can just
have one variable and introduce different flags. The patch also
introduces additional flag EEH_FORCE_DISABLE, which will be used
to disable EEH subsystem via boot parameter ("eeh=off") in future.
Besides, the patch also introduces flag EEH_ENABLED, which is
changed to disable or enable EEH functionality on the fly through
debugfs entry in future.

With the patch applied, the creteria to check the enabled EEH
functionality is changed to:

!EEH_FORCE_DISABLED && EEH_ENABLED : Enabled
   Other cases : Disabled

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h | 29 +++--
 arch/powerpc/kernel/eeh.c  | 31 +++
 2 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index f0183e3..f4a9321 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -32,6 +32,12 @@ struct device_node;
 
 #ifdef CONFIG_EEH
 
+/* EEH subsystem flags */
+#define EEH_ENABLED0x1 /* EEH enabled  */
+#define EEH_FORCE_DISABLED 0x2 /* EEH disabled */
+#define EEH_PROBE_MODE_DEV 0x4 /* From PCI device  */
+#define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */
+
 /*
  * The struct is used to trace PE related EEH functionality.
  * In theory, there will have one instance of the struct to
@@ -173,37 +179,40 @@ struct eeh_ops {
int (*restore_config)(struct device_node *dn);
 };
 
+extern int eeh_subsystem_flags;
 extern struct eeh_ops *eeh_ops;
-extern bool eeh_subsystem_enabled;
 extern raw_spinlock_t confirm_error_lock;
-extern int eeh_probe_mode;
 
 static inline bool eeh_enabled(void)
 {
-   return eeh_subsystem_enabled;
+   if ((eeh_subsystem_flags & EEH_FORCE_DISABLED) ||
+   !(eeh_subsystem_flags & EEH_ENABLED))
+   return false;
+
+   return true;
 }
 
 static inline void eeh_set_enable(bool mode)
 {
-   eeh_subsystem_enabled = mode;
+   if (mode)
+   eeh_subsystem_flags |= EEH_ENABLED;
+   else
+   eeh_subsystem_flags &= ~EEH_ENABLED;
 }
 
-#define EEH_PROBE_MODE_DEV (1<<0)  /* From PCI device  */
-#define EEH_PROBE_MODE_DEVTREE (1<<1)  /* From device tree */
-
 static inline void eeh_probe_mode_set(int flag)
 {
-   eeh_probe_mode = flag;
+   eeh_subsystem_flags |= flag;
 }
 
 static inline int eeh_probe_mode_devtree(void)
 {
-   return (eeh_probe_mode == EEH_PROBE_MODE_DEVTREE);
+   return (eeh_subsystem_flags & EEH_PROBE_MODE_DEVTREE);
 }
 
 static inline int eeh_probe_mode_dev(void)
 {
-   return (eeh_probe_mode == EEH_PROBE_MODE_DEV);
+   return (eeh_subsystem_flags & EEH_PROBE_MODE_DEV);
 }
 
 static inline void eeh_serialize_lock(unsigned long *flags)
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 69df898..06d2b7c 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -87,22 +87,21 @@
 /* Time to wait for a PCI slot to report status, in milliseconds */
 #define PCI_BUS_RESET_WAIT_MSEC (5*60*1000)
 
-/* Platform dependent EEH operations */
-struct eeh_ops *eeh_ops = NULL;
-
-bool eeh_subsystem_enabled = false;
-EXPORT_SYMBOL(eeh_subsystem_enabled);
-
 /*
- * EEH probe mode support. The intention is to support multiple
- * platforms for EEH. Some platforms like pSeries do PCI emunation
- * based on device tree. However, other platforms like powernv probe
- * PCI devices from hardware. The flag is used to distinguish that.
- * In addition, struct eeh_ops::probe would be invoked for particular
- * OF node or PCI device so that the corresponding PE would be created
- * there.
+ * EEH probe mode support, which is part of the flags,
+ * is to support multiple platforms for EEH. Some platforms
+ * like pSeries do PCI emunation based on device tree.
+ * However, other platforms like powernv probe PCI devices
+ * from hardware. The flag is used to distinguish that.
+ * In addition, struct eeh_ops::probe would be invoked for
+ * particular OF node or PCI device so that the corresponding
+ * PE would be created there.
  */
-int eeh_probe_mode;
+int eeh_subsystem_flags;
+EXPORT_SYMBOL(eeh_subsystem_flags);
+
+/* Platform dependent EEH operations */
+struct eeh_ops *eeh_ops = NULL;
 
 /* Lock to avoid races due to multiple reports of an error */
 DEFINE_RAW_SPINLOCK(confirm_error_lock);
@@ -842,8 +841,8 @@ int eeh_init(void)
&hose_list, list_node)
pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL);
} else {
-   pr_warning("%s: Invalid probe mode %d\n",
-  __func__, eeh_probe_mode);
+   pr_warn("%s: Invalid probe mode %x",
+   __func__, eeh_subsystem_flags);
return -EINVAL;
}

[PATCH 12/25] powerpc/eeh: Allow to disable EEH

2014-04-24 Thread Gavin Shan
The patch introduces bootarg "eeh=off" to disable EEH functinality.
Also, it creates /sys/kerenl/debug/powerpc/eeh_enable to disable
or enable EEH functionality. By default, we have the functionality
enabled.

For PowerNV platform, we will restore to have the conventional
mechanism of clearing frozen PE during PCI config access if we're
going to disable EEH functionality. Conversely, we will rely on
EEH for error recovery.

The patch also fixes the issue that we missed to cover the case
of disabled EEH functionality in function ioda_eeh_event(). Those
events driven by interrupt should be cleared to avoid endless
reporting.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/eeh.c | 47 ++-
 arch/powerpc/platforms/powernv/eeh-ioda.c | 29 +++
 arch/powerpc/platforms/powernv/pci.h  |  1 +
 3 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 06d2b7c..1e409a2 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -22,6 +22,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -132,6 +133,15 @@ static struct eeh_stats eeh_stats;
 
 #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
 
+static int __init eeh_setup(char *str)
+{
+   if (!strcmp(str, "off"))
+   eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+
+   return 1;
+}
+__setup("eeh=", eeh_setup);
+
 /**
  * eeh_gather_pci_data - Copy assorted PCI config space registers to buff
  * @edev: device to report data for
@@ -1117,10 +1127,45 @@ static const struct file_operations proc_eeh_operations 
= {
.release   = single_release,
 };
 
+#ifdef CONFIG_DEBUG_FS
+static int eeh_enable_dbgfs_set(void *data, u64 val)
+{
+   if (val)
+   eeh_subsystem_flags &= ~EEH_FORCE_DISABLED;
+   else
+   eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+
+   /* Notify the backend */
+   if (eeh_ops->post_init)
+   eeh_ops->post_init();
+
+   return 0;
+}
+
+static int eeh_enable_dbgfs_get(void *data, u64 *val)
+{
+   if (eeh_enabled())
+   *val = 0x1ul;
+   else
+   *val = 0x0ul;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(eeh_enable_dbgfs_ops, eeh_enable_dbgfs_get,
+   eeh_enable_dbgfs_set, "0x%llx\n");
+#endif
+
 static int __init eeh_init_proc(void)
 {
-   if (machine_is(pseries) || machine_is(powernv))
+   if (machine_is(pseries) || machine_is(powernv)) {
proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
+#ifdef CONFIG_DEBUG_FS
+   debugfs_create_file("eeh_enable", 0600,
+powerpc_debugfs_root, NULL,
+&eeh_enable_dbgfs_ops);
+#endif
+   }
+
return 0;
 }
 __initcall(eeh_init_proc);
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 6bdae8d..35ec394 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -42,11 +42,19 @@ static int ioda_eeh_event(struct notifier_block *nb,
 {
uint64_t changed_evts = (uint64_t)change;
 
-   /* We simply send special EEH event */
-   if ((changed_evts & OPAL_EVENT_PCI_ERROR) &&
-   (events & OPAL_EVENT_PCI_ERROR) &&
-   eeh_enabled())
+   /*
+* We simply send special EEH event if EEH has
+* been enabled, or clear pending events in
+* case that we enable EEH soon
+*/
+   if (!(changed_evts & OPAL_EVENT_PCI_ERROR) ||
+   !(events & OPAL_EVENT_PCI_ERROR))
+   return 0;
+
+   if (eeh_enabled())
eeh_send_failure_event(NULL);
+   else
+   opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
 
return 0;
 }
@@ -141,7 +149,9 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
}
 
 #ifdef CONFIG_DEBUG_FS
-   if (phb->dbgfs) {
+   if (!phb->has_dbgfs && phb->dbgfs) {
+   phb->has_dbgfs = 1;
+
debugfs_create_file("err_injct_outbound", 0600,
phb->dbgfs, hose,
&ioda_eeh_outb_dbgfs_ops);
@@ -154,7 +164,14 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
}
 #endif
 
-   phb->flags |= PNV_PHB_FLAG_EEH;
+   /* If EEH is enabled, we're going to rely on that.
+* Otherwise, we restore to conventional mechanism
+* to clear frozen PE during PCI config access.
+*/
+   if (eeh_enabled())
+   phb->flags |= PNV_PHB_FLAG_EEH;
+   else
+   phb->flags &= ~PNV_PHB_FLAG_EEH;
 
return 0;
 }
diff --git a/arch/powerpc/platforms/powernv/pci.h 
b/arch/powerpc/platforms/powernv/pci.h
index 94e3495..39ec697 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/

[PATCH 18/25] powerpc/pci: Mask linkDown on resetting PCI bus

2014-04-24 Thread Gavin Shan
The problem was initially reported by Wendy who tried pass through
IPR adapter, which was connected to PHB root port directly, to KVM
based guest. When doing that, pci_reset_bridge_secondary_bus() was
called by VFIO driver and linkDown was detected by the root port.
That caused all PEs to be frozen.

The patch fixes the issue by routing the reset for the secondary bus
of root port to underly firmware. For that, one more weak function
pci_reset_secondary_bus() is introduced so that the individual platforms
can override that and do specific reset for bridge's secondary bus.

Reported-by: Wendy Xiong 
Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/machdep.h|  3 +++
 arch/powerpc/kernel/pci-common.c  | 20 
 arch/powerpc/platforms/powernv/eeh-ioda.c | 38 +--
 arch/powerpc/platforms/powernv/pci-ioda.c |  1 +
 arch/powerpc/platforms/powernv/pci.h  |  1 +
 drivers/pci/pci.c | 21 ++---
 6 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h 
b/arch/powerpc/include/asm/machdep.h
index 5b6c03f..240b137 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -241,6 +241,9 @@ struct machdep_calls {
/* Called during PCI resource reassignment */
resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned 
long type);
 
+   /* Reset the secondary bus of bridge */
+   void  (*pcibios_reset_secondary_bus)(struct pci_dev *dev);
+
/* Called to shutdown machine specific hardware not already controlled
 * by other drivers.
 */
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index d9476c1..f9ca509 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -120,6 +121,25 @@ resource_size_t pcibios_window_alignment(struct pci_bus 
*bus,
return 1;
 }
 
+void pcibios_reset_secondary_bus(struct pci_dev *dev)
+{
+   u16 ctrl;
+
+   if (ppc_md.pcibios_reset_secondary_bus) {
+   ppc_md.pcibios_reset_secondary_bus(dev);
+   return;
+   }
+
+   pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
+   ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
+   pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+   msleep(2);
+
+   ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+   pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+   ssleep(1);
+}
+
 static resource_size_t pcibios_io_size(const struct pci_controller *hose)
 {
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 268cd46..58ef809 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -474,6 +474,8 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int 
option)
 
 {
struct device_node *dn = pci_device_to_OF_node(dev);
+   struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+   int aer = edev ? edev->aer_cap : 0;
u32 ctrl;
 
pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
@@ -483,24 +485,56 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int 
option)
switch (option) {
case EEH_RESET_FUNDAMENTAL:
case EEH_RESET_HOT:
+   /* Don't report linkDown event */
+   if (aer) {
+   eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
+4, &ctrl);
+   ctrl |= PCI_ERR_UNC_SURPDN;
+eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
+ 4, ctrl);
+}
+
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
-
msleep(EEH_PE_RST_HOLD_TIME);
+
break;
case EEH_RESET_DEACTIVATE:
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
-
msleep(EEH_PE_RST_SETTLE_TIME);
+
+   /* Continue reporting linkDown event */
+   if (aer) {
+   eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
+4, &ctrl);
+   ctrl &= ~PCI_ERR_UNC_SURPDN;
+   eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
+ 4, ctrl);
+   }
+
break;
}
 
return 0;
 }
 
+void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
+{
+   struct pci_controller *hose;
+
+   if (pc

[PATCH 21/25] powerpc/powernv: Fundamental reset on PLX ports

2014-04-24 Thread Gavin Shan
The patch intends to support fundamental reset on PLX downstream
ports. If the PCI device matches any one of the internal table,
which includes PLX vendor ID, bridge device ID, register offset
for fundamental reset and bit, fundamental reset will be done
accordingly. Otherwise, it will fail back to hot reset.

Additional flag (EEH_DEV_FRESET) is introduced to record the last
reset type on the PCI bridge.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h|   1 +
 arch/powerpc/platforms/powernv/eeh-ioda.c | 110 +-
 2 files changed, 95 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index b76f58c..d12529f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -109,6 +109,7 @@ struct eeh_pe {
 #define EEH_DEV_NO_HANDLER (1 << 8)/* No error handler */
 #define EEH_DEV_SYSFS  (1 << 9)/* Sysfs created*/
 #define EEH_DEV_REMOVED(1 << 10)   /* Removed permanently  
*/
+#define EEH_DEV_FRESET (1 << 11)   /* Fundamental reset*/
 
 struct eeh_dev {
int mode;   /* EEH mode */
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 753f08e..79d0cdf 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -477,49 +477,127 @@ out:
return 0;
 }
 
+static bool ioda_eeh_is_plx_dnport(struct pci_dev *dev, int *reg,
+  int *mask, int *len)
+{
+   unsigned short *pid;
+   unsigned short ids[] = {
+   0x10b5, 0x8748, 0x0080, 0x0400, /* PLX#8748 */
+   0x, 0x, 0x, 0x, /* End flag */
+   };
+
+   if (!pci_is_pcie(dev))
+   return false;
+   if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
+   return false;
+
+   pid = &ids[0];
+   while (!reg) {
+   if (pid[0] == 0x0)
+   break;
+
+   if (dev->vendor == pid[0] &&
+   dev->device == pid[1]) {
+*reg  = pid[2];
+*mask = pid[3];
+*len  = 2;
+return true;
+}
+}
+
+   *reg  = PCI_BRIDGE_CONTROL;
+   *mask = PCI_BRIDGE_CTL_BUS_RESET;
+   *len  = 2;
+   return false;
+}
+
 static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
 
 {
struct device_node *dn = pci_device_to_OF_node(dev);
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
int aer = edev ? edev->aer_cap : 0;
-   u32 ctrl;
+   int reg, mask, val, len;
+   bool is_plx_dnport;
 
pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
 __func__, pci_domain_nr(dev->bus),
 dev->bus->number, option);
 
+
+   is_plx_dnport = ioda_eeh_is_plx_dnport(dev, ®, &mask, &len);
+   if (option == EEH_RESET_FUNDAMENTAL)
+   if (!is_plx_dnport || !edev)
+   option = EEH_RESET_HOT;
+
+   if (option == EEH_RESET_HOT) {
+   reg  = PCI_BRIDGE_CONTROL;
+   mask = PCI_BRIDGE_CTL_BUS_RESET;
+   len  = 2;
+   }
+
+   if (option == EEH_RESET_DEACTIVATE) {
+   if (!is_plx_dnport || !edev ||
+   !(edev->mode & EEH_DEV_FRESET)) {
+   reg  = PCI_BRIDGE_CONTROL;
+   mask = PCI_BRIDGE_CTL_BUS_RESET;
+   len  = 2;
+   }
+   }
+
switch (option) {
case EEH_RESET_FUNDAMENTAL:
+   edev->mode |= EEH_DEV_FRESET;
+   /* Fall through */
case EEH_RESET_HOT:
-   /* Don't report linkDown event */
if (aer) {
+   /* Mask receiver error */
+   eeh_ops->read_config(dn, aer + PCI_ERR_COR_MASK,
+4, &val);
+   val |= PCI_ERR_COR_RCVR;
+   eeh_ops->write_config(dn, aer + PCI_ERR_COR_MASK,
+ 4, val);
+
+   /* Mask linkDown */
eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
-4, &ctrl);
-   ctrl |= PCI_ERR_UNC_SURPDN;
+4, &val);
+   val |= PCI_ERR_UNC_SURPDN;
 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
- 4, ctrl);
-}
+ 4, val);
+   }
 
-   eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
-   ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
-  

[PATCH 19/25] powrpc/powernv: Reset PHB in kdump kernel

2014-04-24 Thread Gavin Shan
In the kdump scenario, the first kerenl doesn't shutdown PCI devices
and the kdump kerenl clean PHB IODA table at the early probe time.
That means the kdump kerenl can't support PCI transactions piled
by the first kerenl. Otherwise, lots of EEH errors and frozen PEs
will be detected.

In order to avoid the EEH errors, the PHB is resetted to drop all
PCI transaction from the first kerenl.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 15 +++
 arch/powerpc/platforms/powernv/pci-ioda.c | 12 
 arch/powerpc/platforms/powernv/pci.h  |  1 +
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 58ef809..753f08e 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -388,13 +388,16 @@ static s64 ioda_eeh_phb_poll(struct pnv_phb *phb)
if (rc <= 0)
break;
 
-   msleep(rc);
+   if (system_state < SYSTEM_RUNNING)
+   udelay(1000 * rc);
+   else
+   msleep(rc);
}
 
return rc;
 }
 
-static int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
+int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
 {
struct pnv_phb *phb = hose->private_data;
s64 rc = OPAL_HARDWARE;
@@ -422,8 +425,12 @@ static int ioda_eeh_phb_reset(struct pci_controller *hose, 
int option)
 * need the PCI bus settlement delay.
 */
rc = ioda_eeh_phb_poll(phb);
-   if (option == EEH_RESET_DEACTIVATE)
-   msleep(EEH_PE_RST_SETTLE_TIME);
+   if (option == EEH_RESET_DEACTIVATE) {
+   if (system_state < SYSTEM_RUNNING)
+   udelay(1000 * EEH_PE_RST_SETTLE_TIME);
+   else
+   msleep(EEH_PE_RST_SETTLE_TIME);
+   }
 out:
if (rc != OPAL_SUCCESS)
return -EIO;
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 0bfc4d1..6a2cb37 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1394,6 +1395,17 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, 
OPAL_ASSERT_RESET);
if (rc)
pr_warning("  OPAL Error %ld performing IODA table reset !\n", 
rc);
+
+   /* If we're running in kdump kerenl, the previous kerenl never
+* shutdown PCI devices correctly. We already got IODA table
+* cleaned out. So we have to issue PHB reset to stop all PCI
+* transactions from previous kerenl.
+*/
+   if (is_kdump_kernel()) {
+   pr_info("  Issue PHB reset ...\n");
+   ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
+   ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
+   }
 }
 
 void __init pnv_pci_init_ioda2_phb(struct device_node *np)
diff --git a/arch/powerpc/platforms/powernv/pci.h 
b/arch/powerpc/platforms/powernv/pci.h
index 34a0974..676232c 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -205,5 +205,6 @@ extern void pnv_pci_init_ioda2_phb(struct device_node *np);
 extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
__be64 *startp, __be64 *endp, bool rm);
 extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
+extern int ioda_eeh_phb_reset(struct pci_controller *hose, int option);
 
 #endif /* __POWERNV_PCI_H */
-- 
1.8.3.2

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

[PATCH 17/25] powerpc/eeh: Make the delay for PE reset unified

2014-04-24 Thread Gavin Shan
Basically, we have 3 types of resets to fulfil PE reset: fundamental,
hot and PHB reset. For the later 2 cases, we need PCI bus reset hold
and settlement delay as specified by PCI spec. PowerNV and pSeries
platforms are running on top of different firmware and some of the
delays have been covered by underly firmware (PowerNV).

The patch makes the delays unified to be done in backend, instead of
EEH core.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/include/asm/eeh.h   | 10 ++
 arch/powerpc/kernel/eeh.c| 13 -
 arch/powerpc/platforms/powernv/eeh-ioda.c| 12 +++-
 arch/powerpc/platforms/pseries/eeh_pseries.c | 10 +-
 4 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 2841eca..b76f58c 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -39,6 +39,16 @@ struct device_node;
 #define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */
 
 /*
+ * Delay for PE reset, all in ms
+ *
+ * PCI specification has reset hold time of 100 milliseconds.
+ * We have 250 milliseconds here. The PCI bus settlement time
+ * is specified as 1.5 seconds and we have 1.8 seconds.
+ */
+#define EEH_PE_RST_HOLD_TIME   250
+#define EEH_PE_RST_SETTLE_TIME 1800
+
+/*
  * The struct is used to trace PE related EEH functionality.
  * In theory, there will have one instance of the struct to
  * be created against particular PE. In nature, PEs corelate
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 1e409a2..3764fb7 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -639,20 +639,7 @@ static void eeh_reset_pe_once(struct eeh_pe *pe)
else
eeh_ops->reset(pe, EEH_RESET_HOT);
 
-   /* The PCI bus requires that the reset be held high for at least
-* a 100 milliseconds. We wait a bit longer 'just in case'.
-*/
-#define PCI_BUS_RST_HOLD_TIME_MSEC 250
-   msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
-
eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-
-   /* After a PCI slot has been reset, the PCI Express spec requires
-* a 1.5 second idle time for the bus to stabilize, before starting
-* up traffic.
-*/
-#define PCI_BUS_SETTLE_TIME_MSEC 1800
-   msleep(PCI_BUS_SETTLE_TIME_MSEC);
 }
 
 /**
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 0844e00..268cd46 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -417,9 +417,13 @@ static int ioda_eeh_phb_reset(struct pci_controller *hose, 
int option)
 
/*
 * Poll state of the PHB until the request is done
-* successfully.
+* successfully. The PHB reset is usually PHB complete
+* reset followed by hot reset on root bus. So we also
+* need the PCI bus settlement delay.
 */
rc = ioda_eeh_phb_poll(phb);
+   if (option == EEH_RESET_DEACTIVATE)
+   msleep(EEH_PE_RST_SETTLE_TIME);
 out:
if (rc != OPAL_SUCCESS)
return -EIO;
@@ -457,6 +461,8 @@ static int ioda_eeh_root_reset(struct pci_controller *hose, 
int option)
 
/* Poll state of the PHB until the request is done */
rc = ioda_eeh_phb_poll(phb);
+   if (option == EEH_RESET_DEACTIVATE)
+   msleep(EEH_PE_RST_SETTLE_TIME);
 out:
if (rc != OPAL_SUCCESS)
return -EIO;
@@ -480,11 +486,15 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int 
option)
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
+
+   msleep(EEH_PE_RST_HOLD_TIME);
break;
case EEH_RESET_DEACTIVATE:
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
+
+   msleep(EEH_PE_RST_SETTLE_TIME);
break;
}
 
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c 
b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 2f1ba64..0bec0c0 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -532,11 +532,19 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int 
option)
/* If fundamental-reset not supported, try hot-reset */
if (option == EEH_RESET_FUNDAMENTAL &&
ret == -8) {
+   option = EEH_RESET_HOT;
ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
config_addr, BUID_HI(pe->phb->buid),
-   BUID_LO(pe->phb->buid), EEH_RESET_HOT);
+   BUID_LO(pe->phb->buid), option);

[PATCH 20/25] powerpc/eeh: Can't recover from non-PE-reset case

2014-04-24 Thread Gavin Shan
When PCI_ERS_RESULT_CAN_RECOVER returned from device drivers, the
EEH core should enable I/O and DMA for the affected PE. However,
it was missed to have DMA enabled in eeh_handle_normal_event().
Besides, the frozen state of the affected PE should be cleared
after successful recovery, but we didn't.

The patch fixes both of the issues as above.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/eeh_driver.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index f99ba9b..7100a5b 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -640,7 +640,6 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
result = PCI_ERS_RESULT_NEED_RESET;
} else {
pr_info("EEH: Notify device drivers to resume I/O\n");
-   result = PCI_ERS_RESULT_NONE;
eeh_pe_dev_traverse(pe, eeh_report_mmio_enabled, 
&result);
}
}
@@ -652,10 +651,17 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
 
if (rc < 0)
goto hard_fail;
-   if (rc)
+   if (rc) {
result = PCI_ERS_RESULT_NEED_RESET;
-   else
+   } else {
+   /*
+* We didn't do PE reset for the case. The PE
+* is still in frozen state. Clear it before
+* resuming the PE.
+*/
+   eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
result = PCI_ERS_RESULT_RECOVERED;
+   }
}
 
/* If any device has a hard failure, then shut off everything. */
-- 
1.8.3.2

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

[PATCH 16/25] powerpc/powernv: Reset root port in firmware

2014-04-24 Thread Gavin Shan
Resetting root port has more stuff to do than that for PCIe switch
ports and we should have resetting root port done in firmware instead
of the kernel itself. The problem was introduced by commit 5b2e198e
("powerpc/powernv: Rework EEH reset").

Cc: linux-stable 
Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 3a755b5..0844e00 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -510,12 +510,10 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
int ret;
 
/*
-* The rules applied to reset, either fundamental or hot reset:
-*
-* We always reset the direct upstream bridge of the PE. If the
-* direct upstream bridge isn't root bridge, we always take hot
-* reset no matter what option (fundamental or hot) is. Otherwise,
-* we should do the reset according to the required option.
+* For PHB reset, we always have complete reset. For those PEs whose
+* primary bus derived from root complex (root bus) or root port
+* (usually bus#1), we apply hot or fundamental reset on the root port.
+* For other PEs, we always have hot reset on the PE primary bus.
 *
 * Here, we have different design to pHyp, which always clear the
 * frozen state during PE reset. However, the good idea here from
@@ -529,7 +527,8 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
ret = ioda_eeh_phb_reset(hose, option);
} else {
bus = eeh_pe_bus_get(pe);
-   if (pci_is_root_bus(bus))
+   if (pci_is_root_bus(bus) ||
+   pci_is_root_bus(bus->parent))
ret = ioda_eeh_root_reset(hose, option);
else
ret = ioda_eeh_bridge_reset(bus->self, option);
-- 
1.8.3.2

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

[PATCH 22/25] powerpc/powernv: Missed IOMMU table type

2014-04-24 Thread Gavin Shan
In function pnv_pci_ioda2_setup_dma_pe(), the IOMMU table type is
set to (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE) unconditionally.
It was just set to TCE_PCI by pnv_pci_setup_iommu_table(). So the
primary IOMMU table type (TCE_PCI) is lost. The patch fixes it.

Also, pnv_pci_setup_iommu_table() already set "tbl->it_busno" to
zero and we needn't do it again. The patch removes the redundant
assignment.

The patch also fixes similar issues in pnv_pci_ioda_setup_dma_pe().

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 6a2cb37..1934327 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -665,12 +665,12 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
 * errors, and on the first pass the data will be a relative
 * bus number, print that out instead.
 */
-   tbl->it_busno = 0;
pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
8);
-   tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE |
-  TCE_PCI_SWINV_PAIR;
+   tbl->it_type |= (TCE_PCI_SWINV_CREATE |
+TCE_PCI_SWINV_FREE   |
+TCE_PCI_SWINV_PAIR);
}
iommu_init_table(tbl, phb->hose->node);
iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
@@ -795,11 +795,10 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb 
*phb,
 * errors, and on the first pass the data will be a relative
 * bus number, print that out instead.
 */
-   tbl->it_busno = 0;
pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
8);
-   tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
+   tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE);
}
iommu_init_table(tbl, phb->hose->node);
iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
-- 
1.8.3.2

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

[PATCH 25/25] powerpc/prom: Stop scanning dev-tree for fdump early

2014-04-24 Thread Gavin Shan
Function early_init_dt_scan_fw_dump() is called to scan the device
tree for fdump properties under node "rtas". Any one of them is
invalid, we can stop scanning the device tree early by returning
"1". It would save a bit time during boot.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/kernel/fadump.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 2230fd0..0266774 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -69,7 +69,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
 */
token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL);
if (!token)
-   return 0;
+   return 1;
 
fw_dump.fadump_supported = 1;
fw_dump.ibm_configure_kernel_dump = *token;
@@ -92,7 +92,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
&size);
 
if (!sections)
-   return 0;
+   return 1;
 
num_sections = size / (3 * sizeof(u32));
 
@@ -110,6 +110,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
break;
}
}
+
return 1;
 }
 
-- 
1.8.3.2

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

[PATCH 23/25] powerpc/powernv: pci_domain_nr() not reliable

2014-04-24 Thread Gavin Shan
If the PE contains single PCI function, "pe->pbus" would be NULL.
It's not reliable to be used by pci_domain_nr().  We just grab the
PCI domain number from the PCI host controller (struct pci_controller)
instance.

Signed-off-by: Gavin Shan 
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 1934327..9807341 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -673,7 +673,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
 TCE_PCI_SWINV_PAIR);
}
iommu_init_table(tbl, phb->hose->node);
-   iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
+   iommu_register_group(tbl, phb->hose->global_number, pe->pe_number);
 
if (pe->pdev)
set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
@@ -801,7 +801,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE);
}
iommu_init_table(tbl, phb->hose->node);
-   iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
+   iommu_register_group(tbl, phb->hose->global_number, pe->pe_number);
 
if (pe->pdev)
set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
-- 
1.8.3.2

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

[PATCH 24/25] PCI: Fix return value from pci_user_{read, write}_config_*()

2014-04-24 Thread Gavin Shan
PCI accessors from user space pci_user_{read,write}_config_*()
return negative error number, which was introduced by commit
34e32072 ("PCI: handle positive error codes"). That patch coverts
all positive error numbers from platform specific PCI config
accessors to -EINVAL. The upper layer calling to those PCI config
accessors hardly know the specific cause from the return value
when hitting failures.

The patch fixes the issue by doing the conversion (from positive
to negative) using existing function pcibios_err_to_errno().

Signed-off-by: Gavin Shan 
---
 drivers/pci/access.c | 12 
 include/linux/pci.h  |  6 --
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 7f8b78c..8c148f3 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -148,7 +148,7 @@ static noinline void pci_wait_cfg(struct pci_dev *dev)
 int pci_user_read_config_##size
\
(struct pci_dev *dev, int pos, type *val)   \
 {  \
-   int ret = 0;\
+   int ret = PCIBIOS_SUCCESSFUL;   \
u32 data = -1;  \
if (PCI_##size##_BAD)   \
return -EINVAL; \
@@ -159,9 +159,7 @@ int pci_user_read_config_##size 
\
pos, sizeof(type), &data);  \
raw_spin_unlock_irq(&pci_lock); \
*val = (type)data;  \
-   if (ret > 0)\
-   ret = -EINVAL;  \
-   return ret; \
+   return pcibios_err_to_errno(ret);   \
 }  \
 EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
 
@@ -170,7 +168,7 @@ EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
 int pci_user_write_config_##size   \
(struct pci_dev *dev, int pos, type val)\
 {  \
-   int ret = -EIO; \
+   int ret = PCIBIOS_SUCCESSFUL;   \
if (PCI_##size##_BAD)   \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock);   \
@@ -179,9 +177,7 @@ int pci_user_write_config_##size
\
ret = dev->bus->ops->write(dev->bus, dev->devfn,\
pos, sizeof(type), val);\
raw_spin_unlock_irq(&pci_lock); \
-   if (ret > 0)\
-   ret = -EINVAL;  \
-   return ret; \
+   return pcibios_err_to_errno(ret);   \
 }  \
 EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index aab57b4..1682cb1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -518,7 +518,7 @@ static inline int pcibios_err_to_errno(int err)
case PCIBIOS_FUNC_NOT_SUPPORTED:
return -ENOENT;
case PCIBIOS_BAD_VENDOR_ID:
-   return -EINVAL;
+   return -ENOTTY;
case PCIBIOS_DEVICE_NOT_FOUND:
return -ENODEV;
case PCIBIOS_BAD_REGISTER_NUMBER:
@@ -527,9 +527,11 @@ static inline int pcibios_err_to_errno(int err)
return -EIO;
case PCIBIOS_BUFFER_TOO_SMALL:
return -ENOSPC;
+   default:
+   return -err;
}
 
-   return -ENOTTY;
+   return -ERANGE;
 }
 
 /* Low-level architecture-dependent routines */
-- 
1.8.3.2

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

Re: [PATCH 00/38] MMC updates, plus CuBox-i WiFi support

2014-04-24 Thread Ulf Hansson
On 23 April 2014 20:55, Russell King - ARM Linux  wrote:
> All,
>
> This is where I'm at with trying to clean up the SDHCI mess, and sort out
> issues I've noticed when trying to get UHS support working on CuBoxes.
> This is my full patch set, but I recommend not applying patch 37 as there
> appears to be a hardware issue preventing it working reliably.
>
> In any case, patches 0-33 inclusive are the SDHCI clean up, based against
> v3.15-rc1.  Patches 34 and 35 are Olof's Wifi support, 36 is my fix against
> those, and 38 adds the Broadcom Wifi and BT support for CuBox.
>
> The questions over how to handle these devices were never properly settled,
> so I recommend against merging patch 34 onwards.  As for the rest, I'm not
> planning on any further work, so it may be a good idea for people to
> consider testing them with a view to getting them merged.
>

I have looked though the patches up until patch 33 and this is clearly
a nice piece of clean-up /fixes work for sdhci. Besides my minor
comments per patch, I don't have any objections code-review wise to
proceed merging them.

I have also tried to applied them on Chris' mmc-next branch,
unfortunate it fails at patch 23, so it would be nice to get a
re-based patchset for the mmc-next branch.

Kind regards
Ulf Hansson

>  Documentation/devicetree/bindings/mmc/mmc.txt |  11 +
>  arch/arm/boot/dts/imx6qdl-cubox-i.dtsi|  34 +-
>  arch/arm/boot/dts/imx6qdl-microsom.dtsi   |  98 
>  drivers/mmc/core/core.c   |  42 ++
>  drivers/mmc/core/host.c   |  68 +++
>  drivers/mmc/core/sdio_irq.c   |  41 +-
>  drivers/mmc/host/Kconfig  |  63 +--
>  drivers/mmc/host/dw_mmc.c |   2 +
>  drivers/mmc/host/sdhci-acpi.c |   8 +
>  drivers/mmc/host/sdhci-bcm-kona.c |   4 +
>  drivers/mmc/host/sdhci-bcm2835.c  |   4 +
>  drivers/mmc/host/sdhci-cns3xxx.c  |  13 +-
>  drivers/mmc/host/sdhci-dove.c |   4 +
>  drivers/mmc/host/sdhci-esdhc-imx.c|  82 +--
>  drivers/mmc/host/sdhci-esdhc.h|   4 +-
>  drivers/mmc/host/sdhci-of-arasan.c|   4 +
>  drivers/mmc/host/sdhci-of-esdhc.c |  70 ++-
>  drivers/mmc/host/sdhci-of-hlwd.c  |   4 +
>  drivers/mmc/host/sdhci-pci.c  |   9 +-
>  drivers/mmc/host/sdhci-pltfm.c|   4 +
>  drivers/mmc/host/sdhci-pxav2.c|  14 +-
>  drivers/mmc/host/sdhci-pxav3.c|  13 +-
>  drivers/mmc/host/sdhci-s3c.c  |  36 +-
>  drivers/mmc/host/sdhci-sirf.c |   4 +
>  drivers/mmc/host/sdhci-spear.c|   5 +-
>  drivers/mmc/host/sdhci-tegra.c|  27 +-
>  drivers/mmc/host/sdhci.c  | 728 
> +-
>  drivers/mmc/host/sdhci.h  |  20 +-
>  include/linux/mmc/host.h  |   8 +
>  include/linux/mmc/sdhci.h |  15 +-
>  30 files changed, 885 insertions(+), 554 deletions(-)
>
>
> --
> FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
> improving, and getting towards what was expected from it.
> --
> 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 3/3] of: Handle memory@0 node on PPC32 only

2014-04-24 Thread Leif Lindholm
On Wed, Apr 23, 2014 at 02:10:58PM +0100, Grant Likely wrote:
> > Does anyone have a LongTrail DT to hand, and if so does the root have a
> > compatible string? From grepping through the kernel I could only find a
> > model string ("IBM,LongTrail").
> 
> Actually, on LongTrail this can be removed from the common code
> entirely. It has real open firmware and PowerPC already has the
> infrastructure for fixing up the device tree.
> 
> Here's a draft patch that I've compile tested, but nothing else.

I would certainly be happy with that.

Consider my 3/3 withdrawn.

And if the kernel proper will stop honoring nodes with no type,
there is no need for the stub to treat those specially either.

/
Leif

> g.
> 
> ---
> 
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 078145acf7fb..18b2c3fee98f 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -2587,9 +2587,18 @@ static void __init fixup_device_tree_chrp(void)
>   phandle ph;
>   u32 prop[6];
>   u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
> - char *name;
> + char *name, strprop[16];
>   int rc;
>  
> + /* Deal with missing device_type in LongTrail memory node */
> + name = "/memory@0";
> + ph = call_prom("finddevice", 1, 1, ADDR(name));
> + rc = prom_getprop(ph, "device_type", strprop, sizeof(strprop));
> + if (rc == PROM_ERROR || strcmp(strprop, "memory") != 0) {
> + prom_printf("Fixing up missing device_type on /memory@0 
> node...\n");
> + prom_setprop(ph, name, "device_type", "memory", 
> sizeof("memory"));
> + }
> +
>   name = "/pci@8000/isa@c";
>   ph = call_prom("finddevice", 1, 1, ADDR(name));
>   if (!PHANDLE_VALID(ph)) {
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 7a2ef7bb8022..7cda0d279cbe 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -886,14 +886,7 @@ int __init early_init_dt_scan_memory(unsigned long node, 
> const char *uname,
>   unsigned long l;
>  
>   /* We are scanning "memory" nodes only */
> - if (type == NULL) {
> - /*
> -  * The longtrail doesn't have a device_type on the
> -  * /memory node, so look for the node called /memory@0.
> -  */
> - if (depth != 1 || strcmp(uname, "memory@0") != 0)
> - return 0;
> - } else if (strcmp(type, "memory") != 0)
> + if (!type || strcmp(type, "memory") != 0)
>   return 0;
>  
>   reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
> 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 00/38] MMC updates, plus CuBox-i WiFi support

2014-04-24 Thread Russell King - ARM Linux
On Thu, Apr 24, 2014 at 10:25:42AM +0200, Ulf Hansson wrote:
> I have looked though the patches up until patch 33 and this is clearly
> a nice piece of clean-up /fixes work for sdhci. Besides my minor
> comments per patch, I don't have any objections code-review wise to
> proceed merging them.
> 
> I have also tried to applied them on Chris' mmc-next branch,
> unfortunate it fails at patch 23, so it would be nice to get a
> re-based patchset for the mmc-next branch.

I /could/ rebase it but then I wouldn't be able to produce the patch
sets/patches for others [*] (such as the Novena project) to derive
their kernel tree from my iMX6 patch set.

What I'd prefer is to keep the patch set intact, and provide Chris
with a pull request for it up to patch 33, which would need a
conflict fixed - and this would mean that I can be sure that what
I'm testing, and what I'm distributing is what Chris will also be
submitting.

* - this currently stands at 230 patches in all - mmc + l2c + fec +
imx-drm + other iMX6 changes.

-- 
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 00/38] MMC updates, plus CuBox-i WiFi support

2014-04-24 Thread Ulf Hansson
On 24 April 2014 12:17, Russell King - ARM Linux  wrote:
> On Thu, Apr 24, 2014 at 10:25:42AM +0200, Ulf Hansson wrote:
>> I have looked though the patches up until patch 33 and this is clearly
>> a nice piece of clean-up /fixes work for sdhci. Besides my minor
>> comments per patch, I don't have any objections code-review wise to
>> proceed merging them.
>>
>> I have also tried to applied them on Chris' mmc-next branch,
>> unfortunate it fails at patch 23, so it would be nice to get a
>> re-based patchset for the mmc-next branch.
>
> I /could/ rebase it but then I wouldn't be able to produce the patch
> sets/patches for others [*] (such as the Novena project) to derive
> their kernel tree from my iMX6 patch set.
>
> What I'd prefer is to keep the patch set intact, and provide Chris
> with a pull request for it up to patch 33, which would need a
> conflict fixed - and this would mean that I can be sure that what
> I'm testing, and what I'm distributing is what Chris will also be
> submitting.

Whether there are more than one conflict, I don't know. I just stopped
at patch 23.

Moreover, there are other patches for sdhci that have been posted and
being discussed. In principle, we then need to put all these on hold
to prevent further conflicts. I guess that doable, as long as we don't
to that for too long. Maybe Chris have some more thoughts how to
handle this!?

Kind regards
Ulf Hansson

>
> * - this currently stands at 230 patches in all - mmc + l2c + fec +
> imx-drm + other iMX6 changes.
>
> --
> FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
> improving, and getting towards what was expected from it.
> --
> 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 00/38] MMC updates, plus CuBox-i WiFi support

2014-04-24 Thread Russell King - ARM Linux
On Thu, Apr 24, 2014 at 12:52:11PM +0200, Ulf Hansson wrote:
> On 24 April 2014 12:17, Russell King - ARM Linux  
> wrote:
> > On Thu, Apr 24, 2014 at 10:25:42AM +0200, Ulf Hansson wrote:
> >> I have looked though the patches up until patch 33 and this is clearly
> >> a nice piece of clean-up /fixes work for sdhci. Besides my minor
> >> comments per patch, I don't have any objections code-review wise to
> >> proceed merging them.
> >>
> >> I have also tried to applied them on Chris' mmc-next branch,
> >> unfortunate it fails at patch 23, so it would be nice to get a
> >> re-based patchset for the mmc-next branch.
> >
> > I /could/ rebase it but then I wouldn't be able to produce the patch
> > sets/patches for others [*] (such as the Novena project) to derive
> > their kernel tree from my iMX6 patch set.
> >
> > What I'd prefer is to keep the patch set intact, and provide Chris
> > with a pull request for it up to patch 33, which would need a
> > conflict fixed - and this would mean that I can be sure that what
> > I'm testing, and what I'm distributing is what Chris will also be
> > submitting.
> 
> Whether there are more than one conflict, I don't know. I just stopped
> at patch 23.
> 
> Moreover, there are other patches for sdhci that have been posted and
> being discussed. In principle, we then need to put all these on hold
> to prevent further conflicts. I guess that doable, as long as we don't
> to that for too long. Maybe Chris have some more thoughts how to
> handle this!?

This is nothing new or unexpected - it was last posted back in February,
and I elected that it should be held off until after the last merge
window.

Unfortunately, I didn't have time to post it immediately after the merge
window closed, partly because it needed to be rebased on top of tglx's
IRQ changes on which it depends.  I was carrying those as separate commits
to the ones Thomas was carrying in his tree - and in the event, Thomas had
modified his patches slightly between sending me copies of them and the
versions he sent during the merge window.

-- 
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 00/38] MMC updates, plus CuBox-i WiFi support

2014-04-24 Thread Ulf Hansson
On 24 April 2014 12:57, Russell King - ARM Linux  wrote:
> On Thu, Apr 24, 2014 at 12:52:11PM +0200, Ulf Hansson wrote:
>> On 24 April 2014 12:17, Russell King - ARM Linux  
>> wrote:
>> > On Thu, Apr 24, 2014 at 10:25:42AM +0200, Ulf Hansson wrote:
>> >> I have looked though the patches up until patch 33 and this is clearly
>> >> a nice piece of clean-up /fixes work for sdhci. Besides my minor
>> >> comments per patch, I don't have any objections code-review wise to
>> >> proceed merging them.
>> >>
>> >> I have also tried to applied them on Chris' mmc-next branch,
>> >> unfortunate it fails at patch 23, so it would be nice to get a
>> >> re-based patchset for the mmc-next branch.
>> >
>> > I /could/ rebase it but then I wouldn't be able to produce the patch
>> > sets/patches for others [*] (such as the Novena project) to derive
>> > their kernel tree from my iMX6 patch set.
>> >
>> > What I'd prefer is to keep the patch set intact, and provide Chris
>> > with a pull request for it up to patch 33, which would need a
>> > conflict fixed - and this would mean that I can be sure that what
>> > I'm testing, and what I'm distributing is what Chris will also be
>> > submitting.
>>
>> Whether there are more than one conflict, I don't know. I just stopped
>> at patch 23.
>>
>> Moreover, there are other patches for sdhci that have been posted and
>> being discussed. In principle, we then need to put all these on hold
>> to prevent further conflicts. I guess that doable, as long as we don't
>> to that for too long. Maybe Chris have some more thoughts how to
>> handle this!?
>
> This is nothing new or unexpected - it was last posted back in February,
> and I elected that it should be held off until after the last merge
> window.
>
> Unfortunately, I didn't have time to post it immediately after the merge
> window closed, partly because it needed to be rebased on top of tglx's
> IRQ changes on which it depends.  I was carrying those as separate commits
> to the ones Thomas was carrying in his tree - and in the event, Thomas had
> modified his patches slightly between sending me copies of them and the
> versions he sent during the merge window.

Okay, so let's keep up the frequency here then. I only had some minor
comments, please fix them and send a v2.

How about if I resolve the conflicts and send the pull request to
Chris? I suppose it makes life a bit easier for Chris.

Kind regards
Ulf Hansson

>
> --
> FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
> improving, and getting towards what was expected from it.
> --
> 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 v2 1/2] fsl/corenet_generic: add a particular initialization for platform

2014-04-24 Thread Scott Wood
On Thu, 2014-04-24 at 01:43 -0500, Wang Dongsheng-B40534 wrote:
> 
> > -Original Message-
> > From: Wood Scott-B07421
> > Sent: Thursday, April 17, 2014 3:36 AM
> > To: Wang Dongsheng-B40534
> > Cc: Jin Zhengxiong-R64188; haoke...@gmail.com; Kushwaha Prabhakar-B32579;
> > linuxppc-dev@lists.ozlabs.org
> > Subject: Re: [PATCH v2 1/2] fsl/corenet_generic: add a particular 
> > initialization
> > for platform
> > 
> > On Tue, 2014-04-15 at 21:58 -0500, Wang Dongsheng-B40534 wrote:
> > >
> > > > -Original Message-
> > > > From: Wood Scott-B07421
> > > > Sent: Wednesday, April 16, 2014 3:39 AM
> > > > To: Wang Dongsheng-B40534
> > > > Cc: Jin Zhengxiong-R64188; haoke...@gmail.com; Kushwaha
> > > > Prabhakar-B32579; linuxppc-dev@lists.ozlabs.org
> > > > Subject: Re: [PATCH v2 1/2] fsl/corenet_generic: add a particular
> > > > initialization for platform
> > > >
> > > > On Tue, 2014-04-15 at 13:53 +0800, Dongsheng Wang wrote:
> > > > > From: Wang Dongsheng 
> > > > >
> > > > > Corenet_generic is a generic platform initialization. Those based
> > > > > on the corenet_generic board maybe need a particular initialize to
> > > > > enable/set some IP-Blocks. So add "Fix Generic Initialization" to
> > > > > solve this kind of special cases.
> > > >
> > > > I still don't understand what you mean by "fix".  What are you
> > > > fixing, or what is fixed?
> > > >
> > > > There is no need for adding an infrastructure layer here.  Just add
> > > > a new piece of code for t104x diu, and have it be called by an
> > > > appropriate initfunc.
> > > >
> > >
> > > "fix" is means to handle some boards those based on corenet_generic
> > > config file, But those boards may need some special handle. Perhaps
> > > these used to handle special feature codes not have an appropriate
> > > initfunc we cannot *just find* an appropriate place,
> > 
> > I'm not asking you to "just find" anything.  I'm asking you to add an 
> > initfunc
> > in a standalone file.
> > 
> > > if more and more boards need to do this, at that time maybe *initfunc*
> > > looks very complicated.
> > 
> > They would each have their own initfunc.  There is no reason to tie this in 
> > with
> > anything else.
> > 
> 
> Sorry, if those platforms are using corenet_generic, I don’t see any 
> standalone file
> for initfunc of platform. That's why I'm adding "fix" layer.

It's totally unnecessary.

Just do this:

t104x_diu_init(void)
{
if (t104x diu not in the device tree)
return;

...
}

early_initcall(t104x_diu_init);

> > > > > +config FIX_GENERIC_PLATFORM_INIT
> > > > > + bool "Fix Generic Initialization"
> > > > > + depends on CORENET_GENERIC
> > > >
> > > > Why does this depend on CORENET_GENERIC?
> > > >
> > >
> > > Because CORENET_GENERIC is a multiboards file, This is designed to handle 
> > > this
> > situation.
> > 
> > This DIU code is going to be just as applicable to a custom T104x board 
> > which
> > may or may not use CORENET_GENERIC.
> > 
> 
> "fix" is a middle layer, it's not only for T104xrdb-DIU.

My point is a custom t104x board might not use CORENET_GENERIC.

> > > > > + default y
> > > >
> > > > No.
> > > >
> > >
> > > Why not? This will not increase any redundant operations if there is not 
> > > any
> > boards need fix.
> > > You can see my fix.c code.
> > 
> > default y should not be used for hardware specific code.
> > 
> 
> fix.c and hardware no relationship at all. :), It's just a software layer.

No relationship to hardware, yet it depends on CORENET_GENERIC, reads a
Freescale-specific SPR, and lives in arch/powerpc/platforms/85xx. :-)

-Scott


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

Re: [PATCH v2 1/2] fsl/corenet_generic: add a particular initialization for platform

2014-04-24 Thread Scott Wood
On Thu, 2014-04-24 at 13:46 -0500, Scott Wood wrote:
> On Thu, 2014-04-24 at 01:43 -0500, Wang Dongsheng-B40534 wrote:
> > 
> > > -Original Message-
> > > From: Wood Scott-B07421
> > > Sent: Thursday, April 17, 2014 3:36 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Jin Zhengxiong-R64188; haoke...@gmail.com; Kushwaha Prabhakar-B32579;
> > > linuxppc-dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v2 1/2] fsl/corenet_generic: add a particular 
> > > initialization
> > > for platform
> > > 
> > > On Tue, 2014-04-15 at 21:58 -0500, Wang Dongsheng-B40534 wrote:
> > > >
> > > > > -Original Message-
> > > > > From: Wood Scott-B07421
> > > > > Sent: Wednesday, April 16, 2014 3:39 AM
> > > > > To: Wang Dongsheng-B40534
> > > > > Cc: Jin Zhengxiong-R64188; haoke...@gmail.com; Kushwaha
> > > > > Prabhakar-B32579; linuxppc-dev@lists.ozlabs.org
> > > > > Subject: Re: [PATCH v2 1/2] fsl/corenet_generic: add a particular
> > > > > initialization for platform
> > > > >
> > > > > On Tue, 2014-04-15 at 13:53 +0800, Dongsheng Wang wrote:
> > > > > > From: Wang Dongsheng 
> > > > > >
> > > > > > Corenet_generic is a generic platform initialization. Those based
> > > > > > on the corenet_generic board maybe need a particular initialize to
> > > > > > enable/set some IP-Blocks. So add "Fix Generic Initialization" to
> > > > > > solve this kind of special cases.
> > > > >
> > > > > I still don't understand what you mean by "fix".  What are you
> > > > > fixing, or what is fixed?
> > > > >
> > > > > There is no need for adding an infrastructure layer here.  Just add
> > > > > a new piece of code for t104x diu, and have it be called by an
> > > > > appropriate initfunc.
> > > > >
> > > >
> > > > "fix" is means to handle some boards those based on corenet_generic
> > > > config file, But those boards may need some special handle. Perhaps
> > > > these used to handle special feature codes not have an appropriate
> > > > initfunc we cannot *just find* an appropriate place,
> > > 
> > > I'm not asking you to "just find" anything.  I'm asking you to add an 
> > > initfunc
> > > in a standalone file.
> > > 
> > > > if more and more boards need to do this, at that time maybe *initfunc*
> > > > looks very complicated.
> > > 
> > > They would each have their own initfunc.  There is no reason to tie this 
> > > in with
> > > anything else.
> > > 
> > 
> > Sorry, if those platforms are using corenet_generic, I don’t see any 
> > standalone file
> > for initfunc of platform. That's why I'm adding "fix" layer.
> 
> It's totally unnecessary.
> 
> Just do this:
> 
> t104x_diu_init(void)
> {

s/t104x_diu_init/static void t104x_diu_init/ of course.

-Scott


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