[PATCH v2 00/15] powerpc/boot: 64bit little endian wrapper (rebased on v3.15-rc2)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
--- 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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_*()
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
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
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
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
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
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
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
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
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