Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On Fri, Aug 16, 2013 at 12:43:31PM +0800, Nicolin Chen wrote: Hi Tomasz, Thank you for the comments. I'll revise them in v6. And below is my reply for you comments. On Thu, Aug 15, 2013 at 02:18:22PM +0200, Tomasz Figa wrote: + - clock-names : Includes the following entries: + nametypecomments + core RequiredThe core clock of spdif controller + + rxOptionalRx clock source for spdif record. + If absent, will use core clock. + + txOptionalTx clock source for spdif playback. + If absent, will use core clock. + + tx-32000 OptionalTx clock source for 32000Hz sample rate + playback. If absent, will use tx clock. + + tx-44100 OptionalTx clock source for 44100Hz sample rate + playback. If absent, will use tx clock. + + tx-48000 OptionalTx clock source for 48000Hz sample rate + playback. If absent, will use tx clock. + + src0-7 OptionalClock source list for tx and rx clock + to look up their clock source indexes. + This clock list should be identical to + the list of TxClk_Source bit value of + register SPDIF_STC. If absent or failed + to look up, tx and rx clock would then + ignore the rx, tx tx-32000, + tx-44100, tx-48000 clock phandles + and select the core clock as default + tx and rx clock. I suspect a little abuse of clocks property here. From the description of core and src0-7 clocks I assume that the IP can have up to 9 clock inputs - core clock and up to 8 extra source clocks. Is it correct? If yes, this makes the tx, rx and tx-* clocks describe configuration, not hardware. IMHO it should be up to the driver which source clocks to use for tx and rx channels and for each sampling rate. First, you are right that all the properties you just commented are software configurations. And I got the point that device tree now can't allow any software configuration even if the actual hardware connection will depend on it. If so, I would like to remove those abused clocks and also drop the unused clocks in src0-7, then just remain those needed clocks src. I think that can be plausible because there'll be no more clock abuse and the driver will be able to get the source index from the name 'srcnum'. And you are right about the 9 clock inputs, just there're not only 9 inputs but also an extra external clock from S/PDIF transmitter via coaxial cable or optical fiber -- RxCLK. Please check the following list: if (DPLL Locked) SPDIF_RxClk else extal 0001 if (DPLL Locked) SPDIF_RxClk else spdif_clk 0010 if (DPLL Locked) SPDIF_RxClk else asrc_clk 0011 if (DPLL Locked) SPDIF_RxClk else spdif_extclk 0100 if (DPLL Locked) SPDIF_Rxclk else esai_hckt 0101 extal_clk 0110 spdif_clk 0111 asrc_clk 1000 spdif_extclk 1001 esai_hckt 1010 if (DPLL Locked) SPDIF_RxClk else mlb_clk 1011 if (DPLL Locked) SPDIF_RxClk else mlb_phy_clk 1100 mkb_clk 1101 mlb_phy_clk When (DPLL Locked) condition matches, the rx clock can ignore the 8 input clocks from clock mux then use the external one from a S/PDIF transmitter. So extal, spdif_clk, asrc_clk, spdif_extclk, esai_hckt, mlb_clk and mlb_phy_clk are clocks provided to the S/PDIF core and thus should be described in the devicetree. Which of them the driver should use is configuration and thus normally should *not* be described in the devicetree. However, there may be no good way for the driver to know which clock to use in which case. There may be additional board requirements which are unknown to the driver. So in this case it might be valid to put the information which clock to use into the devicetree. But be aware that from the moment you put this information into the devicetree the driver is no longer free to chose the best clock, even if in future we find a good way to automatically guess the best clock. Do you have some insights in which case I would use which input clock? Is this only about which clock has the best suitable input frequency or is this also about synchronization of the audio signal with some other unit? Likewise with the rx-clksrc-lock property. what are the reasons to enable/disable this property? Is this an option you want to change during runtime? Is it an option you always want to use when it's available? If you don't know the answer then it might be a good option to just let the driver pick a sane default. If someone feels the need
[RFC PATCH v2 00/10] Machine check handling in linux host.
Hi, Please find the patch set that performs the machine check handling inside linux host. The design is to be able to handle re-entrancy so that we do not clobber the machine check information during nested machine check interrupt. The patch 2 introduces separate emergency stack in paca structure exclusively for machine check exception handling. Patch 3 implements the logic to save the raw MCE info onto the emergency stack and prepares to take another exception. Patch 4 and 5 adds CPU-side hooks for early machine check handler and TLB flush. The patch 6 and 7 is responsible to detect SLB/TLB errors and flush them off in the real mode. The patch 9 implements the logic to decode and save high level MCE information to per cpu buffer without clobbering. The patch 10 adds the basic error handling to the high level C code with MMU on. I have tested SLB multihit scenario on powernv. Please review and let me know your comments. Changes in v2: - Moved early machine check handling code under CPU_FTR_HVMODE section. This makes sure that the early machine check handler will get executed only in hypervisor kernel. - Add dedicated emergency stack for machine check so that we don't end up disturbing others who use same emergency stack. - Fixed the machine check early handle where it used to assume that r1 always contains the valid stack pointer. - Fixed an issue where per-cpu mce_nest_count variable underflows when kvm fails to handle MC error and exit the guest. - Fixed the code to restore r13 before exiting early handler. Thanks, -Mahesh. --- Mahesh Salgaonkar (10): powerpc/book3s: Split the common exception prolog logic into two section. powerpc/book3s: Introduce exclusive emergency stack for machine check exception. powerpc/book3s: handle machine check in Linux host. powerpc/book3s: Introduce a early machine check hook in cpu_spec. powerpc/book3s: Add flush_tlb operation in cpu_spec. powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors on power7. powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors on power8. powerpc/book3s: Decode and save machine check event. powerpc/powernv: Remove machine check handling in OPAL. powerpc/powernv: Machine check exception handling. arch/powerpc/include/asm/bitops.h|5 + arch/powerpc/include/asm/cputable.h | 12 + arch/powerpc/include/asm/exception-64s.h | 67 --- arch/powerpc/include/asm/mce.h | 195 arch/powerpc/include/asm/paca.h |9 + arch/powerpc/kernel/Makefile |1 arch/powerpc/kernel/asm-offsets.c|4 arch/powerpc/kernel/cpu_setup_power.S| 38 +++- arch/powerpc/kernel/cputable.c | 16 ++ arch/powerpc/kernel/exceptions-64s.S | 108 +++ arch/powerpc/kernel/mce.c| 191 arch/powerpc/kernel/mce_power.c | 287 ++ arch/powerpc/kernel/setup_64.c |8 + arch/powerpc/kernel/traps.c | 15 ++ arch/powerpc/kvm/book3s_hv_ras.c | 50 +++-- arch/powerpc/platforms/powernv/opal.c| 84 ++--- arch/powerpc/xmon/xmon.c |2 17 files changed, 998 insertions(+), 94 deletions(-) create mode 100644 arch/powerpc/include/asm/mce.h create mode 100644 arch/powerpc/kernel/mce.c create mode 100644 arch/powerpc/kernel/mce_power.c -- -Mahesh ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
Hi Sascha, Thank you for the detailed comments. On Fri, Aug 16, 2013 at 09:08:18AM +0200, Sascha Hauer wrote: Which of them the driver should use is configuration and thus normally should *not* be described in the devicetree. However, there may be no good way for the driver to know which clock to use in which case. There may be additional board requirements which are unknown to the driver. So in this case it might be valid to put the information which clock to use into the devicetree. But be aware that from the moment you put this information into the devicetree the driver is no longer free to chose the best clock, even if in future we find a good way to automatically guess the best clock. Do you have some insights in which case I would use which input clock? Is this only about which clock has the best suitable input frequency or is this also about synchronization of the audio signal with some other unit? I understand. What I'm thinking now is to let the driver find the best clock source for tx clock and a correspond divisor like this: tx0-8 OptionalTx clock source for spdif playback. If absent, will use core clock. The index from 0 to 8 is identical to the clock source list described in TxClk_Source bit of register STC. Multiple clock source are allowed for this tx clock source. The driver will select one source from them for each supported sample rate according to the clock rates of these provided clock sources. Please review this idea. And likewise for rx: rx0-16 OptionalRx clock source for spdif record. If absent, will use core clock. The index from 0 to 16 is identical to the clock source list described in ClkSrc_Sel bit of register SRPC. If the index provided contains an if (DPLL Locked) condition in its source, the correspond clock phandle should be the one in else path. Only one rx clock source should be defined here. Likewise with the rx-clksrc-lock property. what are the reasons to enable/disable this property? Is this an option you want to change during runtime? Is it an option you always want to use when it's available? If you don't know the answer then it might be a good option to just let the driver pick a sane default. If someone feels the need to change the default he probably comes up with a good reason why this is necessary. And then we can discuss again whether we want to have the option in the devicetree or some sysfs entry or whatever else. The answer is, SPDIF controller actually doesn't care about which rx clock source being chosen or even whether it has the if (DPLL Locked) condition or not. It can measure its input clock sample rate by measuring the signal source, from a spdif transmitter via coaxial cable or optical line. However, the rxclk will be sent to other IP, ASRC on i.MX6Q for example. Quoting from the i.MX6Q reference manual that Both the Rx clock and Tx clock are sent to the ASRC. Therefore, if 'rx-clksrc-lock' is present, that means ASRC will get a clock source indirectly from coaxial cable that contains the sample rate information. So it can know what input sample rate is and do his own procedure accordingly. Thank you, Nicolin Chen ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 01/10] powerpc/book3s: Split the common exception prolog logic into two section.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch splits the common exception prolog logic into two parts to facilitate reuse of existing code in the next patch. The second part will be reused in the machine check exception routine in the next patch. Please note that this patch does not introduce or change existing code logic. Instead it is just a code movement. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/exception-64s.h | 67 -- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 07ca627..2386d40 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -248,6 +248,40 @@ do_kvm_##n: \ #define NOTEST(n) +#define EXCEPTION_PROLOG_COMMON_2(n, area)\ + std r2,GPR2(r1);/* save r2 in stackframe*/ \ + SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ + SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe*/ \ + ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ + ld r10,area+EX_R10(r13); \ + std r9,GPR9(r1); \ + std r10,GPR10(r1); \ + ld r9,area+EX_R11(r13);/* move r11 - r13 to stackframe */ \ + ld r10,area+EX_R12(r13); \ + ld r11,area+EX_R13(r13); \ + std r9,GPR11(r1); \ + std r10,GPR12(r1); \ + std r11,GPR13(r1); \ + BEGIN_FTR_SECTION_NESTED(66); \ + ld r10,area+EX_CFAR(r13); \ + std r10,ORIG_GPR3(r1); \ + END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);\ + GET_LR(r9,area);/* Get LR, later save to stack */ \ + ld r2,PACATOC(r13);/* get kernel TOC into r2 */ \ + std r9,_LINK(r1); \ + mfctr r10;/* save CTR in stackframe */ \ + std r10,_CTR(r1); \ + lbz r10,PACASOFTIRQEN(r13);\ + mfspr r11,SPRN_XER; /* save XER in stackframe */ \ + std r10,SOFTE(r1); \ + std r11,_XER(r1); \ + li r9,(n)+1; \ + std r9,_TRAP(r1); /* set trap number */ \ + li r10,0; \ + ld r11,exception_marker@toc(r2); \ + std r10,RESULT(r1); /* clear regs-result */ \ + std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ + /* * The common exception prolog is used for all except a few exceptions * such as a segment miss on a kernel address. We have to be prepared @@ -281,38 +315,7 @@ do_kvm_##n: \ beq 4f; /* if from kernel mode */ \ ACCOUNT_CPU_USER_ENTRY(r9, r10); \ SAVE_PPR(area, r9, r10); \ -4: std r2,GPR2(r1);/* save r2 in stackframe*/ \ - SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ - SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe*/ \ - ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ - ld r10,area+EX_R10(r13); \ - std r9,GPR9(r1); \ - std r10,GPR10(r1); \ - ld r9,area+EX_R11(r13);/* move r11 - r13 to stackframe */ \ - ld r10,area+EX_R12(r13); \ - ld r11,area+EX_R13(r13); \ - std r9,GPR11(r1); \ - std r10,GPR12(r1); \ - std r11,GPR13(r1); \ - BEGIN_FTR_SECTION_NESTED(66);
[RFC PATCH v2 02/10] powerpc/book3s: Introduce exclusive emergency stack for machine check exception.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch introduces exclusive emergency stack for machine check exception. We use emergency stack to handle machine check exception so that we can save MCE information (srr1, srr0, dar and dsisr) before turning on ME bit and be ready for re-entrancy. This helps us to prevent clobbering of MCE information in case of nested machine checks. The reason for using emergency stack over normal kernel stack is that the machine check might occur in the middle of setting up a stack frame which may result into improper use of kernel stack. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/paca.h |9 + arch/powerpc/kernel/setup_64.c |8 +++- arch/powerpc/xmon/xmon.c|2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 77c91e7..b4ca4e9 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -147,6 +147,15 @@ struct paca_struct { */ struct opal_machine_check_event *opal_mc_evt; #endif +#ifdef CONFIG_PPC_BOOK3S_64 + /* Exclusive emergency stack pointer for machine check exception. */ + void *mc_emergency_sp; + /* +* Flag to check whether we are in machine check early handler +* and already using emergency stack. +*/ + u16 in_mce; +#endif /* Stuff for accurate time accounting */ u64 user_time; /* accumulated usermode TB ticks */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 389fb807..3fdbdb0 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -529,7 +529,8 @@ static void __init exc_lvl_early_init(void) /* * Stack space used when we detect a bad kernel stack pointer, and - * early in SMP boots before relocation is enabled. + * early in SMP boots before relocation is enabled. Exclusive emergency + * stack for machine checks. */ static void __init emergency_stack_init(void) { @@ -552,6 +553,11 @@ static void __init emergency_stack_init(void) sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); sp += THREAD_SIZE; paca[i].emergency_sp = __va(sp); + + /* emergency stack for machine check exception handling. */ + sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); + sp += THREAD_SIZE; + paca[i].mc_emergency_sp = __va(sp); } } diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 96bf5bd..147a5e98 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2044,6 +2044,8 @@ static void dump_one_paca(int cpu) DUMP(p, stab_addr, lx); #endif DUMP(p, emergency_sp, p); + DUMP(p, mc_emergency_sp, p); + DUMP(p, in_mce, x); DUMP(p, data_offset, lx); DUMP(p, hw_cpu_id, x); DUMP(p, cpu_start, x); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 03/10] powerpc/book3s: handle machine check in Linux host.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com Move machine check entry point into Linux. So far we were dependent on firmware to decode MCE error details and handover the high level info to OS. This patch introduces early machine check routine that saves the MCE information (srr1, srr0, dar and dsisr) to the emergency stack. We allocate stack frame on emergency stack and set the r1 accordingly. This allows us to be prepared to take another exception without loosing context. One thing to note here that, if we get another machine check while ME bit is off then we risk a checkstop. Hence we restrict ourselves to save only MCE information and turn the ME bit on. We use paca-in_mce flag to differentiate between first entry and nested machine check entry which helps proper use of emergency stack. We increment paca-in_mce every time we enter in early machine check handler and decrement it while leaving. When we enter machine check early handler first time (paca-in_mce == 0), we are sure nobody is using MC emergency stack and allocate a stack frame at the start of the emergency stack. During subsequent entry (paca-in_mce 0), we know that r1 points inside emergency stack and we allocate separate stack frame accordingly. This prevents us from clobbering MCE information during nested machine checks. The early machine check handler changes are placed under CPU_FTR_HVMODE section. This makes sure that the early machine check handler will get executed only in hypervisor kernel. This is the code flow: Machine Check Interrupt | V 0x200 vector ME=0, IR=0, DR=0 | V +---+ |machine_check_pSeries_early: | ME=0, IR=0, DR=0 | Alloc frame on emergency stack | | Save srr1, srr0, dar and dsisr on stack | +---+ | (ME=1, IR=0, DR=0, RFID) | V machine_check_handle_earlyME=1, IR=0, DR=0 | V +---+ | machine_check_early (r3=pt_regs)| ME=1, IR=0, DR=0 | Things to do: (in next patches) | | Flush SLB for SLB errors| | Flush TLB for TLB errors| | Decode and save MCE info| +---+ | (Fall through existing exception handler routine.) | V machine_check_pSerie ME=1, IR=0, DR=0 | (ME=1, IR=1, DR=1, RFID) | V machine_check_common ME=1, IR=1, DR=1 . . . Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/kernel/asm-offsets.c|4 + arch/powerpc/kernel/exceptions-64s.S | 108 ++ arch/powerpc/kernel/traps.c | 12 3 files changed, 124 insertions(+) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index c7e8afc..151b49d 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -235,6 +235,10 @@ int main(void) DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx)); #endif /* CONFIG_PPC_STD_MMU_64 */ DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); +#ifdef CONFIG_PPC_BOOK3S_64 + DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp)); + DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce)); +#endif DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 4e00d22..369518b 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -156,7 +156,11 @@ machine_check_pSeries_1: HMT_MEDIUM_PPR_DISCARD SET_SCRATCH0(r13) /* save r13 */ EXCEPTION_PROLOG_0(PACA_EXMC) +BEGIN_FTR_SECTION + b machine_check_pSeries_early +FTR_SECTION_ELSE b machine_check_pSeries_0 +ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) . = 0x300 .globl data_access_pSeries @@ -404,6 +408,61 @@ denorm_exception_hv: .align 7 /* moved from 0x200 */
[RFC PATCH v2 04/10] powerpc/book3s: Introduce a early machine check hook in cpu_spec.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch adds the early machine check function pointer in cputable for CPU specific early machine check handling. The early machine handle routine will be called in real mode to handle SLB and TLB errors. This patch just sets up a mechanism invoke CPU specific handler. The subsequent patches will populate the function pointer. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/cputable.h |7 +++ arch/powerpc/kernel/traps.c |7 +-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 6f3887d..d8c098e 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -90,6 +90,13 @@ struct cpu_spec { * if the error is fatal, 1 if it was fully recovered and 0 to * pass up (not CPU originated) */ int (*machine_check)(struct pt_regs *regs); + + /* +* Processor specific early machine check handler which is +* called in real mode to handle SLB and TLB errors. +*/ + long(*machine_check_early)(struct pt_regs *regs); + }; extern struct cpu_spec *cur_cpu_spec; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 1720e08..07331b7 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -294,8 +294,11 @@ void system_reset_exception(struct pt_regs *regs) */ long machine_check_early(struct pt_regs *regs) { - /* TODO: handle/decode machine check reason */ - return 0; + long handled = 0; + + if (cur_cpu_spec cur_cpu_spec-machine_check_early) + handled = cur_cpu_spec-machine_check_early(regs); + return handled; } #endif ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 05/10] powerpc/book3s: Add flush_tlb operation in cpu_spec.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch introduces flush_tlb operation in cpu_spec structure. This will help us to invoke appropriate CPU-side flush tlb routine. This patch adds the foundation to invoke CPU specific flush routine for respective architectures. Currently this patch introduce flush_tlb for p7 and p8. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/cputable.h |5 arch/powerpc/kernel/cpu_setup_power.S | 38 +++-- arch/powerpc/kernel/cputable.c|8 +++ arch/powerpc/kvm/book3s_hv_ras.c | 18 +++- 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index d8c098e..d76e47b 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -97,6 +97,11 @@ struct cpu_spec { */ long(*machine_check_early)(struct pt_regs *regs); + /* +* Processor specific routine to flush tlbs. +*/ + void(*flush_tlb)(unsigned long inval_selector); + }; extern struct cpu_spec *cur_cpu_spec; diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index 18b5b9c..37d1bb0 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7) mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR bl __init_LPCR - bl __init_TLB + bl __init_tlb_power7 mtlrr11 blr @@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7) mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR bl __init_LPCR - bl __init_TLB + bl __init_tlb_power7 mtlrr11 blr @@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8) orisr3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR - bl __init_TLB + bl __init_tlb_power8 bl __init_PMU_HV mtlrr11 blr @@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8) orisr3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR - bl __init_TLB + bl __init_tlb_power8 bl __init_PMU_HV mtlrr11 blr @@ -134,15 +134,31 @@ __init_HFSCR: mtspr SPRN_HFSCR,r3 blr -__init_TLB: - /* -* Clear the TLB using the IS 3 form of tlbiel instruction -* (invalidate by congruence class). P7 has 128 CCs, P8 has 512 -* so we just always do 512 -*/ +/* + * Clear the TLB using the specified IS form of tlbiel instruction + * (invalidate by congruence class). P7 has 128 CCs., P8 has 512. + * + * r3 = IS field + */ +__init_tlb_power7: + li r3,0xc00/* IS field = 0b11 */ +_GLOBAL(__flush_tlb_power7) + li r6,128 + mtctr r6 + mr r7,r3 /* IS field */ + ptesync +2: tlbiel r7 + addir7,r7,0x1000 + bdnz2b + ptesync +1: blr + +__init_tlb_power8: + li r3,0xc00/* IS field = 0b11 */ +_GLOBAL(__flush_tlb_power8) li r6,512 mtctr r6 - li r7,0xc00/* IS field = 0b11 */ + mr r7,r3 /* IS field */ ptesync 2: tlbiel r7 addir7,r7,0x1000 diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 22973a7..cdbe115 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -71,6 +71,8 @@ extern void __restore_cpu_power7(void); extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec); extern void __restore_cpu_power8(void); extern void __restore_cpu_a2(void); +extern void __flush_tlb_power7(unsigned long inval_selector); +extern void __flush_tlb_power8(unsigned long inval_selector); #endif /* CONFIG_PPC64 */ #if defined(CONFIG_E500) extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); @@ -440,6 +442,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_cpu_type = ppc64/ibm-compat-v1, .cpu_setup = __setup_cpu_power7, .cpu_restore= __restore_cpu_power7, + .flush_tlb = __flush_tlb_power7, .platform = power7, }, { /* 2.07-compliant processor, i.e. Power8 architected mode */ @@ -456,6 +459,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_cpu_type = ppc64/ibm-compat-v1, .cpu_setup = __setup_cpu_power8, .cpu_restore= __restore_cpu_power8, + .flush_tlb = __flush_tlb_power8, .platform = power8, }, {
[RFC PATCH v2 06/10] powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors on power7.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com If we get a machine check exception due to SLB or TLB errors, then flush SLBs/TLBs and reload SLBs to recover. We do this in real mode before turning on MMU. Otherwise we would run into nested machine checks. If we get a machine check when we are in guest, then just flush the SLBs and continue. This patch handles errors for power7. The next patch will handle errors for power8 Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/bitops.h |5 + arch/powerpc/include/asm/mce.h| 67 arch/powerpc/kernel/Makefile |1 arch/powerpc/kernel/cputable.c|4 + arch/powerpc/kernel/mce_power.c | 153 + 5 files changed, 230 insertions(+) create mode 100644 arch/powerpc/include/asm/mce.h create mode 100644 arch/powerpc/kernel/mce_power.c diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 910194e..a57f4bc 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -46,6 +46,11 @@ #include asm/asm-compat.h #include asm/synch.h +/* PPC bit number conversion */ +#define PPC_BIT(bit) (0x8000UL (bit)) +#define PPC_BITLSHIFT(be) (63 - (be)) +#define PPC_BITMASK(bs, be)((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs)) + /* * clear_bit doesn't imply a memory barrier */ diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h new file mode 100644 index 000..ba19073 --- /dev/null +++ b/arch/powerpc/include/asm/mce.h @@ -0,0 +1,67 @@ +/* + * Machine check exception header file. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright 2013 IBM Corporation + * Author: Mahesh Salgaonkar mah...@linux.vnet.ibm.com + */ + +#ifndef __ASM_PPC64_MCE_H__ +#define __ASM_PPC64_MCE_H__ + +#include linux/bitops.h + +/* + * Machine Check bits on power7 and power8 + */ +#define P7_SRR1_MC_LOADSTORE(srr1) ((srr1) PPC_BIT(42)) /* P8 too */ + +/* SRR1 bits for machine check (On Power7 and Power8) */ +#define P7_SRR1_MC_IFETCH(srr1)((srr1) PPC_BITMASK(43, 45)) /* P8 too */ + +#define P7_SRR1_MC_IFETCH_UE (0x1 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_SLB_PARITY (0x2 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_SLB_MULTIHIT (0x3 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_SLB_BOTH (0x4 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_TLB_MULTIHIT (0x5 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_UE_TLB_RELOAD(0x6 PPC_BITLSHIFT(45)) /* P8 too */ +#define P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL (0x7 PPC_BITLSHIFT(45)) + +/* SRR1 bits for machine check (On Power8) */ +#define P8_SRR1_MC_IFETCH_ERAT_MULTIHIT(0x4 PPC_BITLSHIFT(45)) + +/* DSISR bits for machine check (On Power7 and Power8) */ +#define P7_DSISR_MC_UE (PPC_BIT(48)) /* P8 too */ +#define P7_DSISR_MC_UE_TABLEWALK (PPC_BIT(49)) /* P8 too */ +#define P7_DSISR_MC_ERAT_MULTIHIT (PPC_BIT(52)) /* P8 too */ +#define P7_DSISR_MC_TLB_MULTIHIT_MFTLB (PPC_BIT(53)) /* P8 too */ +#define P7_DSISR_MC_SLB_PARITY_MFSLB (PPC_BIT(55)) /* P8 too */ +#define P7_DSISR_MC_SLB_MULTIHIT (PPC_BIT(56)) /* P8 too */ +#define P7_DSISR_MC_SLB_MULTIHIT_PARITY(PPC_BIT(57)) /* P8 too */ + +/* + * DSISR bits for machine check (Power8) in addition to above. + * Secondary DERAT Multihit + */ +#define P8_DSISR_MC_ERAT_MULTIHIT_SEC (PPC_BIT(54)) + +/* SLB error bits */ +#define P7_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_ERAT_MULTIHIT | \ +P7_DSISR_MC_SLB_PARITY_MFSLB | \ +P7_DSISR_MC_SLB_MULTIHIT | \ +P7_DSISR_MC_SLB_MULTIHIT_PARITY) + +#endif /* __ASM_PPC64_MCE_H__ */ diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index a8619bf..a1aba53 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_PPC_BOOK3S_64)+= cpu_setup_ppc970.o cpu_setup_pa6t.o
[RFC PATCH v2 07/10] powerpc/book3s: Flush SLB/TLBs if we get SLB/TLB machine check errors on power8.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch handles the memory errors on power8. If we get a machine check exception due to SLB or TLB errors, then flush SLBs/TLBs and reload SLBs to recover. I do not have access to power8 box, hence this patch haven't been tested yet. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/mce.h |3 +++ arch/powerpc/kernel/cputable.c |4 arch/powerpc/kernel/mce_power.c | 34 ++ 3 files changed, 41 insertions(+) diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index ba19073..6866062 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -64,4 +64,7 @@ P7_DSISR_MC_SLB_MULTIHIT | \ P7_DSISR_MC_SLB_MULTIHIT_PARITY) +#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \ +P8_DSISR_MC_ERAT_MULTIHIT_SEC) + #endif /* __ASM_PPC64_MCE_H__ */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index c28cc2c..0195358 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -74,6 +74,7 @@ extern void __restore_cpu_a2(void); extern void __flush_tlb_power7(unsigned long inval_selector); extern void __flush_tlb_power8(unsigned long inval_selector); extern long __machine_check_early_realmode_p7(struct pt_regs *regs); +extern long __machine_check_early_realmode_p8(struct pt_regs *regs); #endif /* CONFIG_PPC64 */ #if defined(CONFIG_E500) extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); @@ -462,6 +463,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_power8, .cpu_restore= __restore_cpu_power8, .flush_tlb = __flush_tlb_power8, + .machine_check_early= __machine_check_early_realmode_p8, .platform = power8, }, { /* Power7 */ @@ -521,6 +523,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_power8, .cpu_restore= __restore_cpu_power8, .flush_tlb = __flush_tlb_power8, + .machine_check_early= __machine_check_early_realmode_p8, .platform = power8, }, { /* Power8 */ @@ -540,6 +543,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_power8, .cpu_restore= __restore_cpu_power8, .flush_tlb = __flush_tlb_power8, + .machine_check_early= __machine_check_early_realmode_p8, .platform = power8, }, { /* Cell Broadband Engine */ diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 645d722..949d102 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -151,3 +151,37 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs) /* TODO: Decode machine check reason. */ return handled; } + +static long mce_handle_ierror_p8(uint64_t srr1) +{ + long handled = 0; + + handled = mce_handle_common_ierror(srr1); + + if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) { + flush_and_reload_slb(); + handled = 1; + } + return handled; +} + +static long mce_handle_derror_p8(uint64_t dsisr) +{ + return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS); +} + +long __machine_check_early_realmode_p8(struct pt_regs *regs) +{ + uint64_t srr1; + long handled = 1; + + srr1 = regs-msr; + + if (P7_SRR1_MC_LOADSTORE(srr1)) + handled = mce_handle_derror_p8(regs-dsisr); + else + handled = mce_handle_ierror_p8(srr1); + + /* TODO: Decode machine check reason. */ + return handled; +} ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 08/10] powerpc/book3s: Decode and save machine check event.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com Now that we handle machine check in linux, the MCE decoding should also take place in linux host. This info is crucial to log before we go down in case we can not handle the machine check errors. This patch decodes and populates a machine check event which contain high level meaning full MCE information. We do this in real mode C code with ME bit on. The MCE information is still available on emergency stack (in pt_regs structure format). Even if we take another exception at this point the MCE early handler will allocate a new stack frame on top of current one. So when we return back here we still have our MCE information safe on current stack. We use per cpu buffer to save high level MCE information. Each per cpu buffer is an array of machine check event structure indexed by per cpu counter mce_nest_count. The mce_nest_count is incremented every time we enter machine check early handler in real mode to get the current free slot (index = mce_nest_count - 1). The mce_nest_count is decremented once the MCE info is consumed by virtual mode machine exception handler. This patch provides save_mce_event(), get_mce_event() and release_mce_event() generic routines that can be used by machine check handlers to populate and retrieve the event. The routine release_mce_event() will free the event slot so that it can be reused. Caller can invoke get_mce_event() with a release flag either to release the event slot immediately OR keep it so that it can be fetched again. The event slot can be also released anytime by invoking release_mce_event(). This patch also updates kvm code to invoke get_mce_event to retrieve generic mce event rather than paca-opal_mce_evt. The KVM code always calls get_mce_event() with release flags set to false so that event is available for linus host machine If machine check occurs while we are in guest, KVM tries to handle the error. If KVM is able to handle MC error successfully, it enters the guest and delivers the machine check to guest. If KVM is not able to handle MC error, it exists the guest and passes the control to linux host machine check handler which then logs MC event and decides how to handle it in linux host. In failure case, KVM needs to make sure that the MC event is available for linux host to consume. Hence KVM always calls get_mce_event() with release flags set to false and later it invokes release_mce_event() only if it succeeds to handle error. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/mce.h| 124 + arch/powerpc/kernel/Makefile |2 arch/powerpc/kernel/mce.c | 164 + arch/powerpc/kernel/mce_power.c | 116 ++- arch/powerpc/kvm/book3s_hv_ras.c | 32 -- arch/powerpc/platforms/powernv/opal.c | 35 +++ 6 files changed, 434 insertions(+), 39 deletions(-) create mode 100644 arch/powerpc/kernel/mce.c diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index 6866062..d319161 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -66,5 +66,129 @@ #define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \ P8_DSISR_MC_ERAT_MULTIHIT_SEC) +enum MCE_Version { + MCE_V1 = 1, +}; + +enum MCE_Severity { + MCE_SEV_NO_ERROR = 0, + MCE_SEV_WARNING = 1, + MCE_SEV_ERROR_SYNC = 2, + MCE_SEV_FATAL = 3, +}; + +enum MCE_Disposition { + MCE_DISPOSITION_RECOVERED = 0, + MCE_DISPOSITION_NOT_RECOVERED = 1, +}; + +enum MCE_Initiator { + MCE_INITIATOR_UNKNOWN = 0, + MCE_INITIATOR_CPU = 1, +}; + +enum MCE_ErrorType { + MCE_ERROR_TYPE_UNKNOWN = 0, + MCE_ERROR_TYPE_UE = 1, + MCE_ERROR_TYPE_SLB = 2, + MCE_ERROR_TYPE_ERAT = 3, + MCE_ERROR_TYPE_TLB = 4, +}; + +enum MCE_UeErrorType { + MCE_UE_ERROR_INDETERMINATE = 0, + MCE_UE_ERROR_IFETCH = 1, + MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2, + MCE_UE_ERROR_LOAD_STORE = 3, + MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4, +}; + +enum MCE_SlbErrorType { + MCE_SLB_ERROR_INDETERMINATE = 0, + MCE_SLB_ERROR_PARITY = 1, + MCE_SLB_ERROR_MULTIHIT = 2, +}; + +enum MCE_EratErrorType { + MCE_ERAT_ERROR_INDETERMINATE = 0, + MCE_ERAT_ERROR_PARITY = 1, + MCE_ERAT_ERROR_MULTIHIT = 2, +}; + +enum MCE_TlbErrorType { + MCE_TLB_ERROR_INDETERMINATE = 0, + MCE_TLB_ERROR_PARITY = 1, + MCE_TLB_ERROR_MULTIHIT = 2, +}; + +struct machine_check_event { + enum MCE_Versionversion:8; /* 0x00 */ + uint8_t in_use; /* 0x01 */ + enum MCE_Severity severity:8; /* 0x02 */ + enum MCE_Initiator initiator:8;/* 0x03 */ + enum MCE_ErrorType error_type:8; /* 0x04 */ + enum MCE_Dispositiondisposition:8; /*
[RFC PATCH v2 09/10] powerpc/powernv: Remove machine check handling in OPAL.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com Now that we are ready to handle machine check directly in linux, do not register with firmware to handle machine check exception. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/opal.c |8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index bcbbcdc..8545b33 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -83,14 +83,10 @@ static int __init opal_register_exception_handlers(void) if (!(powerpc_firmware_features FW_FEATURE_OPAL)) return -ENODEV; - /* Hookup some exception handlers. We use the fwnmi area at 0x7000 -* to provide the glue space to OPAL + /* Hookup some exception handlers except machine check. We use the +* fwnmi area at 0x7000 to provide the glue space to OPAL */ glue = 0x7000; - opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER, - __pa(opal_mc_secondary_handler[0]), - glue); - glue += 128; opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER, 0, glue); glue += 128; ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 10/10] powerpc/powernv: Machine check exception handling.
From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com Add basic error handling in machine check exception handler. - If MSR_RI isn't set, we can not recover. - Check if disposition set to OpalMCE_DISPOSITION_RECOVERED. - Check if address at fault is inside kernel address space, if not then send SIGBUS to process if we hit exception when in userspace. - If address at fault is not provided then and if we get a synchronous machine check while in userspace then kill the task. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/mce.h|1 + arch/powerpc/kernel/mce.c | 27 + arch/powerpc/platforms/powernv/opal.c | 43 - 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index d319161..3ff1208 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -190,5 +190,6 @@ extern void save_mce_event(struct pt_regs *regs, long handled, struct mce_error_info *mce_err, uint64_t addr); extern int get_mce_event(struct machine_check_event *mce, bool release); extern void release_mce_event(void); +extern uint64_t get_mce_fault_addr(struct machine_check_event *evt); #endif /* __ASM_PPC64_MCE_H__ */ diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index aeecdf1..659778e 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -162,3 +162,30 @@ void release_mce_event(void) { get_mce_event(NULL, true); } + +uint64_t get_mce_fault_addr(struct machine_check_event *evt) +{ + switch (evt-error_type) { + case MCE_ERROR_TYPE_UE: + if (evt-u.ue_error.effective_address_provided) + return evt-u.ue_error.effective_address; + break; + case MCE_ERROR_TYPE_SLB: + if (evt-u.slb_error.effective_address_provided) + return evt-u.slb_error.effective_address; + break; + case MCE_ERROR_TYPE_ERAT: + if (evt-u.erat_error.effective_address_provided) + return evt-u.erat_error.effective_address; + break; + case MCE_ERROR_TYPE_TLB: + if (evt-u.tlb_error.effective_address_provided) + return evt-u.tlb_error.effective_address; + break; + default: + case MCE_ERROR_TYPE_UNKNOWN: + break; + } + return 0; +} +EXPORT_SYMBOL(get_mce_fault_addr); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 8545b33..7af3b12 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -17,6 +17,7 @@ #include linux/interrupt.h #include linux/notifier.h #include linux/slab.h +#include linux/sched.h #include asm/opal.h #include asm/firmware.h #include asm/mce.h @@ -240,6 +241,44 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) return written; } +static int opal_recover_mce(struct pt_regs *regs, + struct machine_check_event *evt) +{ + int recovered = 0; + uint64_t ea = get_mce_fault_addr(evt); + + if (!(regs-msr MSR_RI)) { + /* If MSR_RI isn't set, we cannot recover */ + recovered = 0; + } else if (evt-disposition == MCE_DISPOSITION_RECOVERED) { + /* Platform corrected itself */ + recovered = 1; + } else if (ea !is_kernel_addr(ea)) { + /* +* Faulting address is not in kernel text. We should be fine. +* We need to find which process uses this address. +* For now, kill the task if we have received exception when +* in userspace. +* +* TODO: Queue up this address for hwpoisioning later. +*/ + if (user_mode(regs) !is_global_init(current)) { + _exception(SIGBUS, regs, BUS_MCEERR_AR, regs-nip); + recovered = 1; + } else + recovered = 0; + } else if (user_mode(regs) !is_global_init(current) + evt-severity == MCE_SEV_ERROR_SYNC) { + /* +* If we have received a synchronous error when in userspace +* kill the task. +*/ + _exception(SIGBUS, regs, BUS_MCEERR_AR, regs-nip); + recovered = 1; + } + return recovered; +} + int opal_machine_check(struct pt_regs *regs) { struct machine_check_event evt; @@ -350,7 +389,9 @@ int opal_machine_check(struct pt_regs *regs) printk(%s Error type: Unknown\n, level); break; } - return evt.severity == MCE_SEV_FATAL ? 0 : 1; + if (opal_recover_mce(regs, evt))
[PATCH 1/2] powerpc/85xx: add hardware automatically enter altivec idle state
From: Wang Dongsheng dongsheng.w...@freescale.com Each core's AltiVec unit may be placed into a power savings mode by turning off power to the unit. Core hardware will automatically power down the AltiVec unit after no AltiVec instructions have executed in N cycles. The AltiVec power-control is triggered by hardware. Signed-off-by: Wang Dongsheng dongsheng.w...@freescale.com diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 5d7d9c2..5c7a7ba 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1053,6 +1053,8 @@ #define PVR_8560 0x8020 #define PVR_VER_E500V1 0x8020 #define PVR_VER_E500V2 0x8021 +#define PVR_VER_E6500 0x8040 + /* * For the 8xx processors, all of them report the same PVR family for * the PowerPC core. The various versions of these processors must be diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index b417de3..c047e08 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -170,6 +170,7 @@ #define SPRN_L2CSR10x3FA /* L2 Data Cache Control and Status Register 1 */ #define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */ #define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */ +#define SPRN_PWRMGTCR0 0x3FB /* Power management control register 0 */ #define SPRN_SVR 0x3FF /* System Version Register */ /* @@ -216,6 +217,9 @@ #defineCCR1_DPC0x0100 /* Disable L1 I-Cache/D-Cache parity checking */ #defineCCR1_TCS0x0080 /* Timer Clock Select */ +/* Bit definitions for PWRMGTCR0. */ +#define PWRMGTCR0_ALTIVEC_IDLE (1 22) /* Altivec idle enable */ + /* Bit definitions for the MCSR. */ #define MCSR_MCS 0x8000 /* Machine Check Summary */ #define MCSR_IB0x4000 /* Instruction PLB Error */ diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c index d0861a0..dbbbc24 100644 --- a/arch/powerpc/platforms/85xx/common.c +++ b/arch/powerpc/platforms/85xx/common.c @@ -7,10 +7,22 @@ */ #include linux/of_platform.h +#include asm/time.h + #include sysdev/cpm2_pic.h #include mpc85xx.h +#define MAX_BIT64 + +#define ALTIVEC_COUNT_OFFSET 16 +#define ALTIVEC_IDLE_COUNT_MASK0x003f + +/* + * FIXME - We don't know the AltiVec application scenarios. + */ +#define ALTIVEC_IDLE_TIME 1000 /* 1ms */ + static struct of_device_id __initdata mpc85xx_common_ids[] = { { .type = soc, }, { .compatible = soc, }, @@ -80,3 +92,63 @@ void __init mpc85xx_cpm2_pic_init(void) irq_set_chained_handler(irq, cpm2_cascade); } #endif + +static bool has_pw20_altivec_idle(void) +{ + u32 pvr; + + pvr = mfspr(SPRN_PVR); + + /* PW20 AltiVec idle feature only exists for E6500 */ + if (PVR_VER(pvr) != PVR_VER_E6500) + return false; + + /* Fix erratum, e6500 rev1 does not support PW20 AltiVec idle */ + if (PVR_REV(pvr) 0x20) + return false; + + return true; +} + +static unsigned int get_idle_ticks_bit(unsigned int us) +{ + unsigned int cycle; + + /* +* The time control by TB turn over bit, so we need +* to be divided by 2. +*/ + cycle = (us / 2) * tb_ticks_per_usec; + + return ilog2(cycle) + 1; +} + +static void setup_altivec_idle(void *unused) +{ + u32 altivec_idle, bit; + + if (!has_pw20_altivec_idle()) + return; + + /* Enable Altivec Idle */ + altivec_idle = mfspr(SPRN_PWRMGTCR0); + altivec_idle |= PWRMGTCR0_ALTIVEC_IDLE; + + /* Set Automatic AltiVec Idle Count */ + /* clear count */ + altivec_idle = ~ALTIVEC_IDLE_COUNT_MASK; + + /* set count */ + bit = get_idle_ticks_bit(ALTIVEC_IDLE_TIME); + altivec_idle |= ((MAX_BIT - bit) ALTIVEC_COUNT_OFFSET); + + mtspr(SPRN_PWRMGTCR0, altivec_idle); +} + +static int __init setup_idle_hw_governor(void) +{ + on_each_cpu(setup_altivec_idle, NULL, 1); + + return 0; +} +late_initcall(setup_idle_hw_governor); -- 1.8.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/2] powerpc/85xx: add hardware automatically enter pw20 state
From: Wang Dongsheng dongsheng.w...@freescale.com Using hardware features make core automatically enter PW20 state. Set a TB count to hardware, the effective count begins when PW10 is entered. When the effective period has expired, the core will proceed from PW10 to PW20 if no exit conditions have occurred during the period. Signed-off-by: Wang Dongsheng dongsheng.w...@freescale.com diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index c047e08..3c81a88 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -219,6 +219,7 @@ /* Bit definitions for PWRMGTCR0. */ #define PWRMGTCR0_ALTIVEC_IDLE (1 22) /* Altivec idle enable */ +#define PWRMGTCR0_PW20_WAIT(1 14) /* PW20 state enable bit */ /* Bit definitions for the MCSR. */ #define MCSR_MCS 0x8000 /* Machine Check Summary */ diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c index dbbbc24..a208d52 100644 --- a/arch/powerpc/platforms/85xx/common.c +++ b/arch/powerpc/platforms/85xx/common.c @@ -17,12 +17,22 @@ #define ALTIVEC_COUNT_OFFSET 16 #define ALTIVEC_IDLE_COUNT_MASK0x003f +#define PW20_COUNT_OFFSET 8 +#define PW20_IDLE_COUNT_MASK 0x3f00 /* * FIXME - We don't know the AltiVec application scenarios. */ #define ALTIVEC_IDLE_TIME 1000 /* 1ms */ +/* + * FIXME - We don't know, what time should we let the core into PW20 state. + * because we don't know the current state of the cpu load. And threads are + * independent, so we can not know the state of different thread has been + * idle. + */ +#definePW20_IDLE_TIME 1000 /* 1ms */ + static struct of_device_id __initdata mpc85xx_common_ids[] = { { .type = soc, }, { .compatible = soc, }, @@ -145,9 +155,33 @@ static void setup_altivec_idle(void *unused) mtspr(SPRN_PWRMGTCR0, altivec_idle); } +static void setup_pw20_idle(void *unused) +{ + u32 pw20_idle, bit; + + if (!has_pw20_altivec_idle()) + return; + + pw20_idle = mfspr(SPRN_PWRMGTCR0); + + /* set PW20_WAIT bit, enable pw20 */ + pw20_idle |= PWRMGTCR0_PW20_WAIT; + + /* Set Automatic PW20 Core Idle Count */ + /* clear count */ + pw20_idle = ~PW20_IDLE_COUNT_MASK; + + /* set count */ + bit = get_idle_ticks_bit(PW20_IDLE_TIME); + pw20_idle |= ((MAX_BIT - bit) PW20_COUNT_OFFSET); + + mtspr(SPRN_PWRMGTCR0, pw20_idle); +} + static int __init setup_idle_hw_governor(void) { on_each_cpu(setup_altivec_idle, NULL, 1); + on_each_cpu(setup_pw20_idle, NULL, 1); return 0; } -- 1.8.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
On 16/08/13 05:50, Benjamin Herrenschmidt wrote: On Thu, 2013-08-15 at 18:09 +0100, Sudeep KarkadaNagesha wrote: /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist * fallback to reg property and assume no threads */ - Oh and I forgot ... that comment is now wrong, since your code handles threads in the reg case... I have fixed it in the next patch while adding the documentation to these function. I wanted changes in this patch minimal. I can fix it here too if you insist on it. Regards, Sudeep ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
On 16/08/13 05:49, Benjamin Herrenschmidt wrote: On Thu, 2013-08-15 at 18:09 +0100, Sudeep KarkadaNagesha wrote: From: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com Currently different drivers requiring to access cpu device node are parsing the device tree themselves. Since the ordering in the DT need not match the logical cpu ordering, the parsing logic needs to consider that. However, this has resulted in lots of code duplication and in some cases even incorrect logic. .../... +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ +return (int)phys_id == get_hard_smp_processor_id(cpu); +} Naming is a bit gross. You might want to make it clearer that we are talking about CPU IDs in the device-tree here. Any particular preference to the name or just a note is sufficient. Also unlike PPC, in ARM we don't set hard processor id value based values read from device tree. DT must contain the values matching to the hardware ID registers. +static bool __of_find_n_match_cpu_property(struct device_node *cpun, +const char *prop_name, int cpu, unsigned int *thread) +{ +const __be32 *cell; +int ac, prop_len, tid; +u64 hwid; + +ac = of_n_addr_cells(cpun); +cell = of_get_property(cpun, prop_name, prop_len); +if (!cell) +return false; +prop_len /= sizeof(*cell); +for (tid = 0; tid prop_len; tid++) { +hwid = of_read_number(cell, ac); +if (arch_match_cpu_phys_id(cpu, hwid)) { +if (thread) +*thread = tid; +return true; +} Missing: cell += ac; Ah, missed it while refactoring, will fix it. Thanks Regards, Sudeep ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On Fri, Aug 16, 2013 at 04:01:25PM +0800, Nicolin Chen wrote: Hi Sascha, Thank you for the detailed comments. On Fri, Aug 16, 2013 at 09:08:18AM +0200, Sascha Hauer wrote: Which of them the driver should use is configuration and thus normally should *not* be described in the devicetree. However, there may be no good way for the driver to know which clock to use in which case. There may be additional board requirements which are unknown to the driver. So in this case it might be valid to put the information which clock to use into the devicetree. But be aware that from the moment you put this information into the devicetree the driver is no longer free to chose the best clock, even if in future we find a good way to automatically guess the best clock. Do you have some insights in which case I would use which input clock? Is this only about which clock has the best suitable input frequency or is this also about synchronization of the audio signal with some other unit? I understand. What I'm thinking now is to let the driver find the best clock source for tx clock and a correspond divisor like this: tx0-8 OptionalTx clock source for spdif playback. If absent, will use core clock. The index from 0 to 8 is identical to the clock source list described in TxClk_Source bit of register STC. Multiple clock source are allowed for this tx clock source. The driver will select one source from them for each supported sample rate according to the clock rates of these provided clock sources. You mean tx0-7. Also I would make this option required. Use a dummy clock for mux inputs that are grounded for a specific SoC. Please review this idea. And likewise for rx: rx0-16OptionalRx clock source for spdif record. If absent, will use core clock. The index from 0 to 16 is identical to the clock source list described in ClkSrc_Sel bit of register SRPC. If the index provided contains an if (DPLL Locked) condition in its source, the correspond clock phandle should be the one in else path. Only one rx clock source should be defined here. Again, describe the input clocks *to* *the* *S/PDIF* *core* in the devicetree. Nothing more, nothing less. We've already been at the point where we realized that half of the above clocks only describe the 'PDLL locked' condition. Also the tx clocks are from what I see identical to the rx clocks. The following are the clocks: clock-names: core, rxtx0-7 Required. The S/PDIF core has a core clock and 8 clocks which are muxed internally to provide input/output sample clocks. This is all binding that is needed for now. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH v2 02/10] powerpc/book3s: Introduce exclusive emergency stack for machine check exception.
On Friday 16 August 2013 01:34 PM, Mahesh J Salgaonkar wrote: From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch introduces exclusive emergency stack for machine check exception. We use emergency stack to handle machine check exception so that we can save MCE information (srr1, srr0, dar and dsisr) before turning on ME bit and be ready for re-entrancy. This helps us to prevent clobbering of MCE information in case of nested machine checks. The reason for using emergency stack over normal kernel stack is that the machine check might occur in the middle of setting up a stack frame which may result into improper use of kernel stack. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/paca.h |9 + arch/powerpc/kernel/setup_64.c |8 +++- arch/powerpc/xmon/xmon.c|2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 77c91e7..b4ca4e9 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -147,6 +147,15 @@ struct paca_struct { */ struct opal_machine_check_event *opal_mc_evt; #endif +#ifdef CONFIG_PPC_BOOK3S_64 + /* Exclusive emergency stack pointer for machine check exception. */ + void *mc_emergency_sp; + /* + * Flag to check whether we are in machine check early handler + * and already using emergency stack. + */ + u16 in_mce; +#endif /* Stuff for accurate time accounting */ u64 user_time; /* accumulated usermode TB ticks */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 389fb807..3fdbdb0 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -529,7 +529,8 @@ static void __init exc_lvl_early_init(void) /* * Stack space used when we detect a bad kernel stack pointer, and - * early in SMP boots before relocation is enabled. + * early in SMP boots before relocation is enabled. Exclusive emergency + * stack for machine checks. */ static void __init emergency_stack_init(void) { @@ -552,6 +553,11 @@ static void __init emergency_stack_init(void) sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); sp += THREAD_SIZE; paca[i].emergency_sp = __va(sp); + + /* emergency stack for machine check exception handling. */ + sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); + sp += THREAD_SIZE; + paca[i].mc_emergency_sp = __va(sp); } } Just a concern, kindly ignore it if it is irrelevant. you have defined mc_emergency_sp under CONFIG_PPC_BOOK3S_64, but assigning memory in a common code. This may break build for other configs such as like ppc64e_defconfig. diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 96bf5bd..147a5e98 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2044,6 +2044,8 @@ static void dump_one_paca(int cpu) DUMP(p, stab_addr, lx); #endif DUMP(p, emergency_sp, p); + DUMP(p, mc_emergency_sp, p); + DUMP(p, in_mce, x); DUMP(p, data_offset, lx); DUMP(p, hw_cpu_id, x); DUMP(p, cpu_start, x); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH v2 02/10] powerpc/book3s: Introduce exclusive emergency stack for machine check exception.
On 08/16/2013 02:29 PM, Madhavan Srinivasan wrote: On Friday 16 August 2013 01:34 PM, Mahesh J Salgaonkar wrote: From: Mahesh Salgaonkar mah...@linux.vnet.ibm.com This patch introduces exclusive emergency stack for machine check exception. We use emergency stack to handle machine check exception so that we can save MCE information (srr1, srr0, dar and dsisr) before turning on ME bit and be ready for re-entrancy. This helps us to prevent clobbering of MCE information in case of nested machine checks. The reason for using emergency stack over normal kernel stack is that the machine check might occur in the middle of setting up a stack frame which may result into improper use of kernel stack. Signed-off-by: Mahesh Salgaonkar mah...@linux.vnet.ibm.com --- arch/powerpc/include/asm/paca.h |9 + arch/powerpc/kernel/setup_64.c |8 +++- arch/powerpc/xmon/xmon.c|2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 77c91e7..b4ca4e9 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -147,6 +147,15 @@ struct paca_struct { */ struct opal_machine_check_event *opal_mc_evt; #endif +#ifdef CONFIG_PPC_BOOK3S_64 +/* Exclusive emergency stack pointer for machine check exception. */ +void *mc_emergency_sp; +/* + * Flag to check whether we are in machine check early handler + * and already using emergency stack. + */ +u16 in_mce; +#endif /* Stuff for accurate time accounting */ u64 user_time; /* accumulated usermode TB ticks */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 389fb807..3fdbdb0 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -529,7 +529,8 @@ static void __init exc_lvl_early_init(void) /* * Stack space used when we detect a bad kernel stack pointer, and - * early in SMP boots before relocation is enabled. + * early in SMP boots before relocation is enabled. Exclusive emergency + * stack for machine checks. */ static void __init emergency_stack_init(void) { @@ -552,6 +553,11 @@ static void __init emergency_stack_init(void) sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); sp += THREAD_SIZE; paca[i].emergency_sp = __va(sp); + +/* emergency stack for machine check exception handling. */ +sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); +sp += THREAD_SIZE; +paca[i].mc_emergency_sp = __va(sp); } } Just a concern, kindly ignore it if it is irrelevant. you have defined mc_emergency_sp under CONFIG_PPC_BOOK3S_64, but assigning memory in a common code. This may break build for other configs such as like ppc64e_defconfig. Nice catch. Will fix it in next spin. Thanks, -Mahesh. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH 2/4] openrisc: remove undefined of_get_cpu_node declaration
On 15/08/13 18:09, Sudeep KarkadaNagesha wrote: From: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com This patch removes the declaration of the function 'of_get_cpu_node' which is not defined for openrisc. This is in preparation to move it's definition from PPC to DT common code. Again it could be there as it was originally copied from powerpc. Signed-off-by: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com Cc: Jonas Bonn jo...@southpole.se Hi Jonas, Since both microblaze and openrisc have moderated lists which I am not member of, these patches were blocked. Michal Simek agreed to remove this for microblaze. Do you see any concern with this patch for openrisc ? Can I have you ACK if it looks fine ? Regards, Sudeep --- arch/openrisc/include/asm/prom.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h index bbb34e5..eb59bfe 100644 --- a/arch/openrisc/include/asm/prom.h +++ b/arch/openrisc/include/asm/prom.h @@ -44,9 +44,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, extern void kdump_move_device_tree(void); -/* CPU OF node matching */ -struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); - /* Get the MAC address */ extern const void *of_get_mac_address(struct device_node *np); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On Fri, Aug 16, 2013 at 10:56:32AM +0200, Sascha Hauer wrote: tx0-8 OptionalTx clock source for spdif playback. If absent, will use core clock. The index from 0 to 8 is identical to the clock source list described in TxClk_Source bit of register STC. Multiple clock source are allowed for this tx clock source. The driver will select one source from them for each supported sample rate according to the clock rates of these provided clock sources. You mean tx0-7 Yes. Thank you. Also I would make this option required. Use a dummy clock for mux inputs that are grounded for a specific SoC. Some clocks are not from CCM and we haven't defined in imx6q-clk.txt, so in most cases we can't provide a phandle for them, eg: spdif_ext. I think it's a bit hard to force it to be 'required'. An 'optional' looks more flexible to me and a default one is ensured even if it's missing. rx0-16 OptionalRx clock source for spdif record. If absent, will use core clock. The index from 0 to 16 is identical to the clock source list described in ClkSrc_Sel bit of register SRPC. If the index provided contains an if (DPLL Locked) condition in its source, the correspond clock phandle should be the one in else path. Only one rx clock source should be defined here. Again, describe the input clocks *to* *the* *S/PDIF* *core* in the devicetree. Nothing more, nothing less. We've already been at the point where we realized that half of the above clocks only describe the 'PDLL locked' condition. Also the tx clocks are from what I see identical to the rx clocks. The following are the clocks: clock-names: core, rxtx0-7 Required. The S/PDIF core has a core clock and 8 clocks which are muxed internally to provide input/output sample clocks. I know the reason why you suggest to combine two into 'rxtx0-7' is because the clock mux is defined so. And the previous suggestion 'the option required' is also because of it. But actually the rxclk itself, can be not only routed from the clock mux but also derived from DPLL of SPDIF Rx BLOCK as well. So, IMHO, it's more likely to be a fact that rxclk actually has 9 clock source, 8 from mux and 1 from DPLL. But why we here have to exclude it? WELL anyway, I know my opinion might not be concerned so much. So I would like to follow the suggestion as an expediency because I still wish this patch could be finally applied and merged into mainline :( But I still don't get why we need to be so obsessed to make this impenetrable rule of devicetree that we here have to sacrifice something we could have reasonably done. And thank you for the comments again, Sascha. Nicolin Chen ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/2] powerpc/iommu: check dev-iommu_group before remove a device from iommu_group
--- arch/powerpc/kernel/iommu.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b20ff17..5abf7c3 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1149,7 +1149,8 @@ static int iommu_bus_notifier(struct notifier_block *nb, case BUS_NOTIFY_ADD_DEVICE: return iommu_add_device(dev); case BUS_NOTIFY_DEL_DEVICE: - iommu_del_device(dev); + if (dev-iommu_group) + iommu_del_device(dev); return 0; default: return 0; -- 1.7.5.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2] iommu: Don't remove device when no iommu_group associated
In some cases, one device may not associated with any iommu_group. For example, not enough DMA address space. For those devices, kernel will crash when try to remove it from an iommu_group. This patch do the check before remove it. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com --- drivers/iommu/iommu.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index fbe9ca7..fe41946 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -379,6 +379,9 @@ void iommu_group_remove_device(struct device *dev) struct iommu_group *group = dev-iommu_group; struct iommu_device *tmp_device, *device = NULL; + if (!group) + return; + /* Pre-notify listeners that a device is being removed. */ blocking_notifier_call_chain(group-notifier, IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev); -- 1.7.5.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 0/2] powerpc/iommu: check dev-iommu_group before remove it
Had a talk with Alexey, who suggest me to send this for comments. On powernv platform, the P7IOC provide limited range of DMA space. For example, there are only 8 DMA segments on each PHB. When there are more than 8 PEs, some of PE's tce32_table is not initialized. In the normal case, 8 PE is enough. If VF is enabled, 8 is not enough. This lead to some pci_dev's iommu_table_base is NULL. Which results this device couldn't be added to any iommu_group, and finally dev-iommu_group is left NULL. When this VF is removed from the system, this will case kernel crash. These two patches add the check to guard the kernel. Comments are welcome for which place is better. One more comment from Alexey is where we allow these non-DMA capable device exist in the system. Maybe we should not allow to create a pci_dev for those who can't get proper DMA space. Your comments are welcome :-) Thanks in advance. Wei Yang (2): iommu: Don't remove device when no iommu_group associated powerpc/iommu: check dev-iommu_group before remove a device from iommu_group arch/powerpc/kernel/iommu.c |3 ++- drivers/iommu/iommu.c |3 +++ 2 files changed, 5 insertions(+), 1 deletions(-) -- 1.7.5.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On Fri, Aug 16, 2013 at 05:53:58PM +0800, Nicolin Chen wrote: On Fri, Aug 16, 2013 at 10:56:32AM +0200, Sascha Hauer wrote: tx0-8 OptionalTx clock source for spdif playback. If absent, will use core clock. The index from 0 to 8 is identical to the clock source list described in TxClk_Source bit of register STC. Multiple clock source are allowed for this tx clock source. The driver will select one source from them for each supported sample rate according to the clock rates of these provided clock sources. You mean tx0-7 Yes. Thank you. Also I would make this option required. Use a dummy clock for mux inputs that are grounded for a specific SoC. Some clocks are not from CCM and we haven't defined in imx6q-clk.txt, so in most cases we can't provide a phandle for them, eg: spdif_ext. I think it's a bit hard to force it to be 'required'. An 'optional' looks more flexible to me and a default one is ensured even if it's missing. clks 0 is the dummy clock. This can be used for all input clocks not defined by the SoC. spdif_ext would be a fixed clock on boards which provide it, but wiring this up would be the job of the board maintainer. Again, describe the input clocks *to* *the* *S/PDIF* *core* in the devicetree. Nothing more, nothing less. We've already been at the point where we realized that half of the above clocks only describe the 'PDLL locked' condition. Also the tx clocks are from what I see identical to the rx clocks. The following are the clocks: clock-names: core, rxtx0-7 Required. The S/PDIF core has a core clock and 8 clocks which are muxed internally to provide input/output sample clocks. I know the reason why you suggest to combine two into 'rxtx0-7' is because the clock mux is defined so. And the previous suggestion 'the option required' is also because of it. But actually the rxclk itself, can be not only routed from the clock mux but also derived from DPLL of SPDIF Rx BLOCK as well. So, IMHO, it's more likely to be a fact that rxclk actually has 9 clock source, 8 from mux and 1 from DPLL. But why we here have to exclude it? Because this is configuration, not hardware description. WELL anyway, I know my opinion might not be concerned so much. So I would like to follow the suggestion as an expediency because I still wish this patch could be finally applied and merged into mainline :( But I still don't get why we need to be so obsessed to make this impenetrable rule of devicetree that we here have to sacrifice something we could have reasonably done. Look, it's really simple. Define the binding in a way that describes the hardware. Then use some sensible default in the driver for which clock to use. This doesn't have to cover all possible usecases, it only has to work. This is all that is necessary to get this driver mainline and will make most users happy. Then, later, someone might come along who needs more fine grained control over the clocks, but this guy is then able to justify *why* more control is needed. This is not about getting a full featured driver into mainline. Get a basic driver into mainline and improve it later. You'll make it easier for us all. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/2] powerpc/iommu: check dev-iommu_group before remove a device from iommu_group
On 08/16/2013 08:08 PM, Wei Yang wrote: --- arch/powerpc/kernel/iommu.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b20ff17..5abf7c3 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1149,7 +1149,8 @@ static int iommu_bus_notifier(struct notifier_block *nb, case BUS_NOTIFY_ADD_DEVICE: return iommu_add_device(dev); case BUS_NOTIFY_DEL_DEVICE: - iommu_del_device(dev); + if (dev-iommu_group) + iommu_del_device(dev); return 0; default: return 0; This one seems redundant, no? -- Alexey ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On Fri, Aug 16, 2013 at 12:11:51PM +0200, Sascha Hauer wrote: Some clocks are not from CCM and we haven't defined in imx6q-clk.txt, so in most cases we can't provide a phandle for them, eg: spdif_ext. I think it's a bit hard to force it to be 'required'. An 'optional' looks more flexible to me and a default one is ensured even if it's missing. clks 0 is the dummy clock. This can be used for all input clocks not defined by the SoC. That's feasible, thank you. spdif_ext would be a fixed clock on boards which provide it, but wiring this up would be the job of the board maintainer. Understood. Look, it's really simple. Define the binding in a way that describes the hardware. Then use some sensible default in the driver for which clock to use. This doesn't have to cover all possible usecases, it only has to work. This is all that is necessary to get this driver mainline and will make most users happy. Then, later, someone might come along who needs more fine grained control over the clocks, but this guy is then able to justify *why* more control is needed. This is not about getting a full featured driver into mainline. Get a basic driver into mainline and improve it later. You'll make it easier for us all. Thank you for explain all these to the despicable me. I'll try to make myself more comfortable with rules here. Best regards, Nicolin Chen ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/2] powerpc/85xx: add hardware automatically enter altivec idle state
On Aug 16, 2013, at 2:23 AM, Dongsheng Wang wrote: From: Wang Dongsheng dongsheng.w...@freescale.com Each core's AltiVec unit may be placed into a power savings mode by turning off power to the unit. Core hardware will automatically power down the AltiVec unit after no AltiVec instructions have executed in N cycles. The AltiVec power-control is triggered by hardware. Signed-off-by: Wang Dongsheng dongsheng.w...@freescale.com Why treat this as a idle HW governor vs just some one time setup at boot of the time delay? - k ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: Critical Interrupt Input
On Aug 15, 2013, at 11:57 PM, Henry Bausley wrote: Is there any reason that a Critical Input Interrupt will not work reliably on a 44x powerpc? I am using an AMCC now Applied Micro AMCC460EX and changed CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception) to CRITICAL_EXCEPTION(0x0100, CriticalInput, do_MyCritIntr) The code for the handler is trivial ie. int crintrcount; void do_MyCritIntr(void) { crintrcount++; } The code runs for a while but eventually I get panic messages and the system hangs. Is there something I must alter in the kernel to do this reliably? The 44x low level code needs to handle exception stacks properly for this to work. Since its possible to have a critical exception occur while in a normal exception level, you have to have proper saving of additional register state and a stack frame for the critical exception, etc. I'm not sure if that was ever done for 44x. - k ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
On Fri, 2013-08-16 at 09:48 +0100, Sudeep KarkadaNagesha wrote: Naming is a bit gross. You might want to make it clearer that we are talking about CPU IDs in the device-tree here. Any particular preference to the name or just a note is sufficient. Also unlike PPC, in ARM we don't set hard processor id value based values read from device tree. DT must contain the values matching to the hardware ID registers. This is exactly the same on ppc. We don't set HW values. The device-tree content matches the HW internals. Some processors have a PIR register as well which contains the HW value, in this case the device-tree must contain the same value as the PIR on that processor. +static bool __of_find_n_match_cpu_property(struct device_node *cpun, + const char *prop_name, int cpu, unsigned int *thread) +{ + const __be32 *cell; + int ac, prop_len, tid; + u64 hwid; + + ac = of_n_addr_cells(cpun); + cell = of_get_property(cpun, prop_name, prop_len); + if (!cell) + return false; + prop_len /= sizeof(*cell); + for (tid = 0; tid prop_len; tid++) { + hwid = of_read_number(cell, ac); + if (arch_match_cpu_phys_id(cpu, hwid)) { + if (thread) + *thread = tid; + return true; + } Missing: cell += ac; Ah, missed it while refactoring, will fix it. Thanks Ben. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
On 16/08/13 13:32, Benjamin Herrenschmidt wrote: On Fri, 2013-08-16 at 09:48 +0100, Sudeep KarkadaNagesha wrote: Naming is a bit gross. You might want to make it clearer that we are talking about CPU IDs in the device-tree here. Any particular preference to the name or just a note is sufficient. Also unlike PPC, in ARM we don't set hard processor id value based values read from device tree. DT must contain the values matching to the hardware ID registers. This is exactly the same on ppc. We don't set HW values. The device-tree content matches the HW internals. Some processors have a PIR register as well which contains the HW value, in this case the device-tree must contain the same value as the PIR on that processor. Ok, I misread the function 'set_hard_smp_processor_id' function. BTW, you didn't mention if you are OK by just have this clearly documented in the function and/or you have any preference/better name. I will send the next version based on that. I have even compile tested :) now on PPC. Regards, Sudeep ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 0/2] Add freescale S/PDIF CPU DAI and machine drivers
Changelog: v5-v6: * Sorted out rxtx clk source in DT binding. * Use devm_() functions. * Use platform_get_resource() instead. v4-v5: * Dropped rx/tx-clksrc-names DT bindings. * Use standard clock binding instead to pass the clock source list. * Update the compatible list by using imx35, the first SoC that has spdif. v3-v4: * Use regmap for CPU DAI driver. * Use individual clock source for 32KHz, 44KHz, 48KHz playback. * Determine clock source configuration from 'clocks' entry. * Added imx53 to compatible list, merged imx6q and imx6dl in the list. * Improve the algorism of reverse_bits(). * Dropped the unneeded clk_put(). v2-v3: * Removed a wrong tag from the commit of patch-1. v1-v2: * Dropped one applied patch for spdif dummy codec drivers. * Use generic DMA DT binding. * Let spdif controller driver calculate the clock div. * Added one optional clock source for spdif tx. * Reivsed documentation accordingly. Nicolin Chen (2): ASoC: fsl: Add S/PDIF CPU DAI driver ASoC: fsl: Add S/PDIF machine driver .../devicetree/bindings/sound/fsl,spdif.txt| 56 + .../devicetree/bindings/sound/imx-audio-spdif.txt | 29 + sound/soc/fsl/Kconfig | 14 + sound/soc/fsl/Makefile |4 + sound/soc/fsl/fsl_spdif.c | 1272 sound/soc/fsl/fsl_spdif.h | 224 sound/soc/fsl/imx-spdif.c | 134 ++ 7 files changed, 1733 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/fsl,spdif.txt create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt create mode 100644 sound/soc/fsl/fsl_spdif.c create mode 100644 sound/soc/fsl/fsl_spdif.h create mode 100644 sound/soc/fsl/imx-spdif.c ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 2/2] ASoC: fsl: Add S/PDIF machine driver
Add S/PDIF machine driver for Freescale i.MX series SoC. Signed-off-by: Nicolin Chen b42...@freescale.com --- .../devicetree/bindings/sound/imx-audio-spdif.txt | 29 + sound/soc/fsl/Kconfig | 11 ++ sound/soc/fsl/Makefile |2 + sound/soc/fsl/imx-spdif.c | 134 4 files changed, 176 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt create mode 100644 sound/soc/fsl/imx-spdif.c diff --git a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt new file mode 100644 index 000..9a3fa26 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt @@ -0,0 +1,29 @@ +Freescale i.MX audio complex with S/PDIF transceiver + +Required properties: + + - compatible : fsl,imx-audio-spdif + + - model : The user-visible name of this sound complex + + - spdif-controller : The phandle of the i.MX S/PDIF controller + + +Optional properties: + + - spdif-transmitter : The phandle of the spdif-transmitter dummy codec + + - spdif-receiver : The phandle of the spdif-receiver dummy codec + +* Note: At least one of these two properties should be set in the DT binding. + + +Example: + +sound-spdif { + compatible = fsl,imx-audio-spdif; + model = imx-spdif; + spdif-controller = spdif; + spdif-transmitter = spdif_tx_codec; + spdif-receiver = spdif_rx_codec; +}; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 2c518db..4cc118c 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -195,6 +195,17 @@ config SND_SOC_IMX_SGTL5000 Say Y if you want to add support for SoC audio on an i.MX board with a sgtl5000 codec. +config SND_SOC_IMX_SPDIF + tristate SoC Audio support for i.MX boards with S/PDIF + select SND_SOC_IMX_PCM_DMA + select SND_SOC_FSL_SPDIF + select SND_SOC_FSL_UTILS + select SND_SOC_SPDIF + help + SoC Audio support for i.MX boards with S/PDIF + Say Y if you want to add support for SoC audio on an i.MX board with + a S/DPDIF. + config SND_SOC_IMX_MC13783 tristate SoC Audio support for I.MX boards with mc13783 depends on MFD_MC13783 ARM diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 4b5970e..e2aaff7 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o snd-soc-wm1133-ev1-objs := wm1133-ev1.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-wm8962-objs := imx-wm8962.o +snd-soc-imx-spdif-objs :=imx-spdif.o snd-soc-imx-mc13783-objs := imx-mc13783.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o @@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o +obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c new file mode 100644 index 000..893f3d1 --- /dev/null +++ b/sound/soc/fsl/imx-spdif.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include linux/module.h +#include linux/of_platform.h +#include sound/soc.h + +struct imx_spdif_data { + struct snd_soc_dai_link dai[2]; + struct snd_soc_card card; +}; + +static int imx_spdif_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev-dev.of_node; + struct device_node *spdif_np, *codec_tx_np, *codec_rx_np; + struct platform_device *spdif_pdev; + struct imx_spdif_data *data; + int ret = 0, num_links = 0; + + spdif_np = of_parse_phandle(np, spdif-controller, 0); + if (!spdif_np) { + dev_err(pdev-dev, failed to find spdif-controller\n); + ret = -EINVAL; + goto fail; + } + + spdif_pdev = of_find_device_by_node(spdif_np); + if (!spdif_pdev) { + dev_err(pdev-dev, failed to find S/PDIF device\n); + ret = -EINVAL; + goto fail; + } + + data = devm_kzalloc(pdev-dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(pdev-dev, failed to allocate memory\n); + ret = -ENOMEM; + goto fail; + } + + codec_tx_np = of_parse_phandle(np,
[PATCH v6 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
This patch add S/PDIF controller driver for Freescale SoC. Signed-off-by: Nicolin Chen b42...@freescale.com --- .../devicetree/bindings/sound/fsl,spdif.txt| 56 + sound/soc/fsl/Kconfig |3 + sound/soc/fsl/Makefile |2 + sound/soc/fsl/fsl_spdif.c | 1272 sound/soc/fsl/fsl_spdif.h | 224 5 files changed, 1557 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/fsl,spdif.txt create mode 100644 sound/soc/fsl/fsl_spdif.c create mode 100644 sound/soc/fsl/fsl_spdif.h diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt new file mode 100644 index 000..5549ce3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -0,0 +1,56 @@ +Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller + +The Freescale S/PDIF audio block is a stereo transceiver that allows the +processor to receive and transmit digital audio via an coaxial cable or +a fibre cable. + +Required properties: + + - compatible : Compatible list, contains fsl,chip-spdif. + + - reg : Offset and length of the register set for the device. + + - interrupts : Contains spdif interrupt. + + - dmas : Generic dma devicetree binding as described in + Documentation/devicetree/bindings/dma/dma.txt. + + - dma-names : Two dmas have to be defined, tx and rx. + + - clocks : Contains an entry for each entry in clock-names. + + - clock-names : Includes the following entries: + namecomments + core The core clock of spdif controller + rxtx0-7 Clock source list for tx and rx clock. + This clock list should be identical to + the source list connecting to the spdif + clock mux in SPDIF Transceiver Clock + Diagram of SoC reference manual. It + can also be referred to TxClk_Source + bit of register SPDIF_STC. + +Example: + +spdif: spdif@02004000 { + compatible = fsl,imx6q-spdif, + fsl,imx35-spdif; + reg = 0x02004000 0x4000; + interrupts = 0 52 0x04; + dmas = sdma 14 18 0, + sdma 15 18 0; + dma-names = rx, tx; + + clocks = clks 197, clks 3, + clks 197, clks 107, + clks 0, clks 118, + clks 62, clks 139, + clks 0; + clock-names = core, rxtx0, + rxtx1, rxtx2, + rxtx3, rxtx4, + rxtx5, rxtx6, + rxtx7; + + status = okay; +}; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index e15f771..2c518db 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,6 +1,9 @@ config SND_SOC_FSL_SSI tristate +config SND_SOC_FSL_SPDIF + tristate + config SND_SOC_FSL_UTILS tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index d4b4aa8..4b5970e 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -12,9 +12,11 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o # Freescale PowerPC SSI/DMA Platform Support snd-soc-fsl-ssi-objs := fsl_ssi.o +snd-soc-fsl-spdif-objs := fsl_spdif.o snd-soc-fsl-utils-objs := fsl_utils.o snd-soc-fsl-dma-objs := fsl_dma.o obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o +obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c new file mode 100644 index 000..e00125e --- /dev/null +++ b/sound/soc/fsl/fsl_spdif.c @@ -0,0 +1,1272 @@ +/* + * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Based on stmp3xxx_spdif_dai.c + * Vladimir Barinov vbari...@embeddedalley.com + * Copyright 2008 SigmaTel, Inc + * Copyright 2008 Embedded Alley Solutions, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed as is without any warranty of any + * kind, whether express or implied. + */ + +#include linux/module.h +#include linux/clk.h +#include linux/clk-private.h +#include linux/regmap.h +#include linux/of_address.h +#include linux/of_device.h +#include linux/of_irq.h + +#include sound/asoundef.h +#include sound/soc.h +#include sound/dmaengine_pcm.h + +#include fsl_spdif.h +#include imx-pcm.h + +#define FSL_SPDIF_TXFIFO_WML 0x8 +#define FSL_SPDIF_RXFIFO_WML 0x8 + +#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) +#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\ + INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\ + INT_RXFIFO_RESYNC | INT_LOSS_LOCK |
[RFC PATCH v2 00/11] Add (de)compression support to pstore
Changes from v1: - Allocate compression workspace during initialisation as per Tony's suggestion - Copy the recent messages from big_oops_buf to psinfo-buf when compression fails, since the printk buffer would be fetched for compression calling it again when compression fails would have moved the iterator of printk buffer which results in fetching old contents. The patchset adds compression and decompression support to pstore. As the non-volatile storage space is limited, adding compression support results in capturing more data within limited space. Size of dmesg file in a powerpc/pseries box with nvram's oops partition (to store oops-log) size 4k: Without compression: dmesg-nvram-1: ~ 4k (3980) WIth compression: dmesg-nvram-1: ~8.8k (8844) Writing to persistent store Compression will reduce the size of oops/panic report to atmost 45% of its original size. (Based on experiments done while providing compression support to nvram by Jim keniston). Hence buffer of size ( (100/45 approx 2.22) *registered_buffer is allocated). The compression parameters selected based on some experiments: compression_level = 6, window_bits = 12, memory_level = 4 achieved a significant compression. Data is compressed from the bigger buffer to registered buffer which is returned to backends. Pstore will indicate that with a flag 'compressed' which is passed to backends. Using this flag, backends will add a flag in their header to indicate the data is compressed or not while writing to persistent store. Reading from persistent store - When backends read data from persistent store it will use the flag added by it while writing to persistent store to determine if the data is compressed or not. Using the information, it will set the flag in pstore's read call back. Pstore will decompress the data based on the flag and writes decompressed data to the file. Test results: Have tested the patches on powerpc/pseries. Needs testing with erst backend, efivars and persistent ram. --- Aruna Balakrishnaiah (11): powerpc/pseries: Remove (de)compression in nvram with pstore enabled pstore: Add new argument 'compressed' in pstore write callback pstore/Kconfig: Select ZLIB_DEFLATE and ZLIB_INFLATE when PSTORE is selected pstore: Add compression support to pstore pstore: Introduce new argument 'compressed' in the read callback pstore: Add decompression support to pstore pstore: Add file extension to pstore file if compressed powerpc/pseries: Read and write to the 'compressed' flag of pstore erst: Read and write to the 'compressed' flag of pstore efi-pstore: Read and write to the 'compressed' flag of pstore pstore/ram: Read and write to the 'compressed' flag of pstore arch/powerpc/platforms/pseries/nvram.c | 112 +++-- drivers/acpi/apei/erst.c | 21 ++- drivers/firmware/efi/efi-pstore.c | 27 +++- fs/pstore/Kconfig |2 fs/pstore/inode.c |7 + fs/pstore/internal.h |5 - fs/pstore/platform.c | 212 ++-- fs/pstore/ram.c| 41 +- include/linux/pstore.h |6 - 9 files changed, 299 insertions(+), 134 deletions(-) -- ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 01/11] powerpc/pseries: Remove (de)compression in nvram with pstore enabled
(De)compression support is provided in pstore in subsequent patches which needs an additional argument 'compressed' to determine if the data is compressed or not. This patch will take care of removing (de)compression in nvram with pstore which was making use of 'hsize' argument in pstore write as 'hsize' will be removed in the subsequent patch. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- arch/powerpc/platforms/pseries/nvram.c | 102 1 file changed, 12 insertions(+), 90 deletions(-) diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 6a5f2b1..b966458 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -539,36 +539,6 @@ static int zip_oops(size_t text_len) } #ifdef CONFIG_PSTORE -/* Derived from logfs_uncompress */ -int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen) -{ - int err, ret; - - ret = -EIO; - err = zlib_inflateInit(stream); - if (err != Z_OK) - goto error; - - stream.next_in = in; - stream.avail_in = inlen; - stream.total_in = 0; - stream.next_out = out; - stream.avail_out = outlen; - stream.total_out = 0; - - err = zlib_inflate(stream, Z_FINISH); - if (err != Z_STREAM_END) - goto error; - - err = zlib_inflateEnd(stream); - if (err != Z_OK) - goto error; - - ret = stream.total_out; -error: - return ret; -} - static int nvram_pstore_open(struct pstore_info *psi) { /* Reset the iterator to start reading partitions again */ @@ -611,30 +581,8 @@ static int nvram_pstore_write(enum pstore_type_id type, oops_hdr-report_length = (u16) size; oops_hdr-timestamp = get_seconds(); - if (big_oops_buf) { - rc = zip_oops(size); - /* -* If compression fails copy recent log messages from -* big_oops_buf to oops_data. -*/ - if (rc != 0) { - size_t diff = size - oops_data_sz + hsize; - - if (size oops_data_sz) { - memcpy(oops_data, big_oops_buf, hsize); - memcpy(oops_data + hsize, big_oops_buf + diff, - oops_data_sz - hsize); - - oops_hdr-report_length = (u16) oops_data_sz; - } else - memcpy(oops_data, big_oops_buf, size); - } else - err_type = ERR_TYPE_KERNEL_PANIC_GZ; - } - rc = nvram_write_os_partition(oops_log_partition, oops_buf, - (int) (sizeof(*oops_hdr) + oops_hdr-report_length), err_type, - count); + (int) (sizeof(*oops_hdr) + size), err_type, count); if (rc != 0) return rc; @@ -655,7 +603,7 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, struct oops_log_info *oops_hdr; unsigned int err_type, id_no, size = 0; struct nvram_os_partition *part = NULL; - char *buff = NULL, *big_buff = NULL; + char *buff = NULL; int sig = 0; loff_t p; @@ -719,8 +667,7 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, *id = id_no; if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { - int length, unzipped_len; - size_t hdr_size; + size_t length, hdr_size; oops_hdr = (struct oops_log_info *)buff; if (oops_hdr-version OOPS_HDR_VERSION) { @@ -740,24 +687,6 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, return -ENOMEM; memcpy(*buf, buff + hdr_size, length); kfree(buff); - - if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { - big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); - if (!big_buff) - return -ENOMEM; - - unzipped_len = nvram_decompress(*buf, big_buff, - length, big_oops_buf_sz); - - if (unzipped_len 0) { - pr_err(nvram: decompression failed, returned - rc %d\n, unzipped_len); - kfree(big_buff); - } else { - *buf = big_buff; - length = unzipped_len; - } - } return length; } @@ -777,13 +706,8 @@ static int nvram_pstore_init(void) { int rc = 0; - if (big_oops_buf) { - nvram_pstore_info.buf = big_oops_buf; -
[RFC PATCH v2 03/11] pstore/Kconfig: Select ZLIB_DEFLATE and ZLIB_INFLATE when PSTORE is selected
Pstore will make use of deflate and inflate algorithm to compress and decompress the data. So when Pstore is enabled select zlib_deflate and zlib_inflate. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- fs/pstore/Kconfig |2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index ca71db6..983d951 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -1,6 +1,8 @@ config PSTORE bool Persistent store support default n + select ZLIB_DEFLATE + select ZLIB_INFLATE help This option enables generic access to platform level persistent storage via pstore filesystem that can ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 02/11] pstore: Add new argument 'compressed' in pstore write callback
Addition of new argument 'compressed' in the write call back will help the backend to know if the data passed from pstore is compressed or not (In case where compression fails.). If compressed, the backend can add a tag indicating the data is compressed while writing to persistent store. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- arch/powerpc/platforms/pseries/nvram.c |4 ++-- drivers/acpi/apei/erst.c |4 ++-- drivers/firmware/efi/efi-pstore.c |2 +- fs/pstore/platform.c |7 --- fs/pstore/ram.c|2 +- include/linux/pstore.h |4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index b966458..dbe5dad 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -554,7 +554,7 @@ static int nvram_pstore_open(struct pstore_info *psi) * @part: pstore writes data to registered buffer in parts, * part number will indicate the same. * @count: Indicates oops count - * @hsize: Size of header added by pstore + * @compressed: Flag to indicate the log is compressed * @size: number of bytes written to the registered buffer * @psi:registered pstore_info structure * @@ -565,7 +565,7 @@ static int nvram_pstore_open(struct pstore_info *psi) static int nvram_pstore_write(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, int count, - size_t hsize, size_t size, + bool compressed, size_t size, struct pstore_info *psi) { int rc; diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 88d0b0f..5e90796 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -935,7 +935,7 @@ static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi); static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, int count, size_t hsize, + u64 *id, unsigned int part, int count, bool compressed, size_t size, struct pstore_info *psi); static int erst_clearer(enum pstore_type_id type, u64 id, int count, struct timespec time, struct pstore_info *psi); @@ -1055,7 +1055,7 @@ out: } static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, int count, size_t hsize, + u64 *id, unsigned int part, int count, bool compressed, size_t size, struct pstore_info *psi) { struct cper_pstore_record *rcd = (struct cper_pstore_record *) diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 73de5a9..fab6892 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -103,7 +103,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, static int efi_pstore_write(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, - unsigned int part, int count, size_t hsize, size_t size, + unsigned int part, int count, bool compressed, size_t size, struct pstore_info *psi) { char name[DUMP_NAME_LEN]; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 422962a..20fa686 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -149,6 +149,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, unsigned long size; int hsize; size_t len; + bool compressed = false; dst = psinfo-buf; hsize = sprintf(dst, %s#%d Part%d\n, why, oopscount, part); @@ -159,7 +160,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, break; ret = psinfo-write(PSTORE_TYPE_DMESG, reason, id, part, - oopscount, hsize, hsize + len, psinfo); + oopscount, compressed, hsize + len, psinfo); if (ret == 0 reason == KMSG_DUMP_OOPS pstore_is_mounted()) pstore_new_entry = 1; @@ -221,10 +222,10 @@ static void pstore_register_console(void) {} static int pstore_write_compat(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, int count, - size_t hsize, size_t size, +
[RFC PATCH v2 04/11] pstore: Add compression support to pstore
Add compression support to pstore which will help in capturing more data. Initially, pstore will make a call to kmsg_dump with a bigger buffer and will pass the size of bigger buffer to kmsg_dump and then compress the data to registered buffer of registered size. In case compression fails, pstore will capture the uncompressed data by making a call again to kmsg_dump with registered_buffer of registered size. Pstore will indicate the data is compressed or not with a flag in the write callback. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- fs/pstore/platform.c | 148 +++--- 1 file changed, 139 insertions(+), 9 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 20fa686..56218cb 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -26,6 +26,7 @@ #include linux/console.h #include linux/module.h #include linux/pstore.h +#include linux/zlib.h #include linux/string.h #include linux/timer.h #include linux/slab.h @@ -65,6 +66,15 @@ struct pstore_info *psinfo; static char *backend; +/* Compression parameters */ +#define COMPR_LEVEL 6 +#define WINDOW_BITS 12 +#define MEM_LEVEL 4 +static struct z_stream_s stream; + +static char *big_oops_buf; +static size_t big_oops_buf_sz; + /* How much of the console log to snapshot */ static unsigned long kmsg_bytes = 10240; @@ -117,6 +127,91 @@ bool pstore_cannot_block_path(enum kmsg_dump_reason reason) } EXPORT_SYMBOL_GPL(pstore_cannot_block_path); +/* Derived from logfs_compress() */ +static int pstore_compress(const void *in, void *out, size_t inlen, + size_t outlen) +{ + int err, ret; + + ret = -EIO; + err = zlib_deflateInit2(stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, + MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (err != Z_OK) + goto error; + + stream.next_in = in; + stream.avail_in = inlen; + stream.total_in = 0; + stream.next_out = out; + stream.avail_out = outlen; + stream.total_out = 0; + + err = zlib_deflate(stream, Z_FINISH); + if (err != Z_STREAM_END) + goto error; + + err = zlib_deflateEnd(stream); + if (err != Z_OK) + goto error; + + if (stream.total_out = stream.total_in) + goto error; + + ret = stream.total_out; +error: + return ret; +} + +static void allocate_buf_for_compression(void) +{ + size_t size; + + big_oops_buf_sz = (psinfo-bufsize * 100) / 45; + big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); + if (big_oops_buf) { + size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), + zlib_inflate_workspacesize()); + stream.workspace = kmalloc(size, GFP_KERNEL); + if (!stream.workspace) { + pr_err(pstore: No memory for compression workspace; + skipping compression\n); + kfree(big_oops_buf); + big_oops_buf = NULL; + } + } else { + pr_err(No memory for uncompressed data; + skipping compression\n); + stream.workspace = NULL; + } + +} + +/* + * Called when compression fails, since the printk buffer + * would be fetched for compression calling it again when + * compression fails would have moved the iterator of + * printk buffer which results in fetching old contents. + * Copy the recent messages from big_oops_buf to psinfo-buf + */ +static size_t copy_kmsg_to_buffer(int hsize, size_t len) +{ + size_t total_len; + size_t diff; + + total_len = hsize + len; + + if (total_len psinfo-bufsize) { + diff = total_len - psinfo-bufsize + hsize; + memcpy(psinfo-buf, big_oops_buf, hsize); + memcpy(psinfo-buf + hsize, big_oops_buf + diff, + psinfo-bufsize - hsize); + total_len = psinfo-bufsize; + } else + memcpy(psinfo-buf, big_oops_buf, total_len); + + return total_len; +} + /* * callback from kmsg_dump. (s2,l2) has the most recently * written bytes, older bytes are in (s1,l1). Save as much @@ -148,23 +243,56 @@ static void pstore_dump(struct kmsg_dumper *dumper, char *dst; unsigned long size; int hsize; + int zipped_len = -1; size_t len; - bool compressed = false; + bool compressed; + size_t total_len; - dst = psinfo-buf; - hsize = sprintf(dst, %s#%d Part%d\n, why, oopscount, part); - size = psinfo-bufsize - hsize; - dst += hsize; + if (big_oops_buf) { + dst = big_oops_buf; +
[RFC PATCH v2 05/11] pstore: Introduce new argument 'compressed' in the read callback
Backends will set the flag 'compressed' after reading the log from persistent store to indicate the data being returned to pstore is compressed or not. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- arch/powerpc/platforms/pseries/nvram.c |2 +- drivers/acpi/apei/erst.c |4 ++-- drivers/firmware/efi/efi-pstore.c |3 ++- fs/pstore/platform.c |4 +++- fs/pstore/ram.c|3 ++- include/linux/pstore.h |2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index dbe5dad..6c4dc52a 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -598,7 +598,7 @@ static int nvram_pstore_write(enum pstore_type_id type, */ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, - struct pstore_info *psi) + bool *compressed, struct pstore_info *psi) { struct oops_log_info *oops_hdr; unsigned int err_type, id_no, size = 0; diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 5e90796..b0dca8e 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -933,7 +933,7 @@ static int erst_open_pstore(struct pstore_info *psi); static int erst_close_pstore(struct pstore_info *psi); static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, - struct pstore_info *psi); + bool *compressed, struct pstore_info *psi); static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, int count, bool compressed, size_t size, struct pstore_info *psi); @@ -989,7 +989,7 @@ static int erst_close_pstore(struct pstore_info *psi) static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, - struct pstore_info *psi) + bool *compressed, struct pstore_info *psi) { int rc; ssize_t len = 0; diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index fab6892..9a5425f 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -87,7 +87,8 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *timespec, - char **buf, struct pstore_info *psi) + char **buf, bool *compressed, + struct pstore_info *psi) { struct pstore_read_data data; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 56218cb..6418eb7 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -428,6 +428,7 @@ void pstore_get_records(int quiet) enum pstore_type_id type; struct timespec time; int failed = 0, rc; + boolcompressed; if (!psi) return; @@ -436,7 +437,8 @@ void pstore_get_records(int quiet) if (psi-open psi-open(psi)) goto out; - while ((size = psi-read(id, type, count, time, buf, psi)) 0) { + while ((size = psi-read(id, type, count, time, buf, compressed, + psi)) 0) { rc = pstore_mkfile(type, psi-name, id, count, buf, (size_t)size, time, psi); kfree(buf); diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index fe7188f..2927223 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -133,7 +133,8 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, - char **buf, struct pstore_info *psi) + char **buf, bool *compressed, + struct pstore_info *psi) { ssize_t size; ssize_t ecc_notice_size; diff --git a/include/linux/pstore.h b/include/linux/pstore.h index abfca4f..abd437d 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -55,7 +55,7 @@ struct pstore_info { int (*close)(struct pstore_info *psi); ssize_t (*read)(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, - struct pstore_info *psi); +
[RFC PATCH v2 06/11] pstore: Add decompression support to pstore
Based on the flag 'compressed' set or not, pstore will decompress the data returning a plain text file. If decompression fails for a particular record it will have the compressed data in the file which can be decompressed with 'openssl' command line tool. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- fs/pstore/platform.c | 53 -- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 6418eb7..0195cca0 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -162,6 +162,36 @@ error: return ret; } +/* Derived from logfs_uncompress */ +int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) +{ + int err, ret; + + ret = -EIO; + err = zlib_inflateInit(stream); + if (err != Z_OK) + goto error; + + stream.next_in = in; + stream.avail_in = inlen; + stream.total_in = 0; + stream.next_out = out; + stream.avail_out = outlen; + stream.total_out = 0; + + err = zlib_inflate(stream, Z_FINISH); + if (err != Z_STREAM_END) + goto error; + + err = zlib_inflateEnd(stream); + if (err != Z_OK) + goto error; + + ret = stream.total_out; +error: + return ret; +} + static void allocate_buf_for_compression(void) { size_t size; @@ -429,6 +459,7 @@ void pstore_get_records(int quiet) struct timespec time; int failed = 0, rc; boolcompressed; + int unzipped_len = -1; if (!psi) return; @@ -439,10 +470,28 @@ void pstore_get_records(int quiet) while ((size = psi-read(id, type, count, time, buf, compressed, psi)) 0) { + if (compressed (type == PSTORE_TYPE_DMESG)) { + if (big_oops_buf) + unzipped_len = pstore_decompress(buf, + big_oops_buf, size, + big_oops_buf_sz); + + if (unzipped_len 0) { + buf = big_oops_buf; + size = unzipped_len; + } else { + pr_err(pstore: decompression failed; + returned %d\n, unzipped_len); + } + } rc = pstore_mkfile(type, psi-name, id, count, buf, (size_t)size, time, psi); - kfree(buf); - buf = NULL; + if (unzipped_len 0) { + /* Free buffer other than big oops */ + kfree(buf); + buf = NULL; + } else + unzipped_len = -1; if (rc (rc != -EEXIST || !quiet)) failed++; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 09/11] erst: Read and write to the 'compressed' flag of pstore
In pstore write, set the section type to CPER_SECTION_TYPE_DMESG_COMPR if the data is compressed. In pstore read, read the section type and update the 'compressed' flag accordingly. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- drivers/acpi/apei/erst.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index b0dca8e..62df189 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -956,6 +956,9 @@ static struct pstore_info erst_info = { #define CPER_SECTION_TYPE_DMESG \ UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \ 0x94, 0x19, 0xeb, 0x12) +#define CPER_SECTION_TYPE_DMESG_Z \ + UUID_LE(0x4f118707, 0x04dd, 0x4055, 0xb5, 0xdd, 0x95, 0x6d, \ + 0x34, 0xdd, 0xfa, 0xc6) #define CPER_SECTION_TYPE_MCE \ UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \ 0x04, 0x4a, 0x38, 0xfc) @@ -1034,7 +1037,12 @@ skip: } memcpy(*buf, rcd-data, len - sizeof(*rcd)); *id = record_id; + *compressed = false; if (uuid_le_cmp(rcd-sec_hdr.section_type, + CPER_SECTION_TYPE_DMESG_Z) == 0) { + *type = PSTORE_TYPE_DMESG; + *compressed = true; + } else if (uuid_le_cmp(rcd-sec_hdr.section_type, CPER_SECTION_TYPE_DMESG) == 0) *type = PSTORE_TYPE_DMESG; else if (uuid_le_cmp(rcd-sec_hdr.section_type, @@ -1085,7 +1093,10 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, rcd-sec_hdr.flags = CPER_SEC_PRIMARY; switch (type) { case PSTORE_TYPE_DMESG: - rcd-sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; + if (compressed) + rcd-sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z; + else + rcd-sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; break; case PSTORE_TYPE_MCE: rcd-sec_hdr.section_type = CPER_SECTION_TYPE_MCE; ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 11/11] pstore/ram: Read and write to the 'compressed' flag of pstore
In pstore write, add character 'C'(compressed) or 'D'(decompressed) in the header while writing to Ram persistent buffer. In pstore read, read the header and update the 'compressed' flag accordingly. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- fs/pstore/ram.c | 36 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 2927223..4027c20 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -131,6 +131,27 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, return prz; } +static void ramoops_read_kmsg_hdr(char *buffer, struct timespec *time, + bool *compressed) +{ + char data_type; + + if (sscanf(buffer, RAMOOPS_KERNMSG_HDR %lu.%lu-%c\n, + time-tv_sec, time-tv_nsec, data_type) == 3) { + if (data_type == 'C') + *compressed = true; + else + *compressed = false; + } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR %lu.%lu\n, + time-tv_sec, time-tv_nsec) == 2) { + *compressed = false; + } else { + time-tv_sec = 0; + time-tv_nsec = 0; + *compressed = false; + } +} + static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, bool *compressed, @@ -153,10 +174,6 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, if (!prz) return 0; - /* TODO(kees): Bogus time for the moment. */ - time-tv_sec = 0; - time-tv_nsec = 0; - size = persistent_ram_old_size(prz); /* ECC correction notice */ @@ -167,12 +184,14 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, return -ENOMEM; memcpy(*buf, persistent_ram_old(prz), size); + ramoops_read_kmsg_hdr(*buf, time, compressed); persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); return size + ecc_notice_size; } -static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz) +static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, +bool compressed) { char *hdr; struct timespec timestamp; @@ -183,8 +202,9 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz) timestamp.tv_sec = 0; timestamp.tv_nsec = 0; } - hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR %lu.%lu\n, - (long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000)); + hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR %lu.%lu-%c\n, + (long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000), + compressed ? 'C' : 'D'); WARN_ON_ONCE(!hdr); len = hdr ? strlen(hdr) : 0; persistent_ram_write(prz, hdr, len); @@ -243,7 +263,7 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, prz = cxt-przs[cxt-dump_write_cnt]; - hlen = ramoops_write_kmsg_hdr(prz); + hlen = ramoops_write_kmsg_hdr(prz, compressed); if (size + hlen prz-buffer_size) size = prz-buffer_size - hlen; persistent_ram_write(prz, buf, size); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 10/11] efi-pstore: Read and write to the 'compressed' flag of pstore
In pstore write, Efi will add a character 'C'(compressed) or D'(decompressed) in its header while writing to persistent store. In pstore read, read the header and update the 'compressed' flag accordingly. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- drivers/firmware/efi/efi-pstore.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 9a5425f..5002d50 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -35,6 +35,7 @@ struct pstore_read_data { enum pstore_type_id *type; int *count; struct timespec *timespec; + bool *compressed; char **buf; }; @@ -42,7 +43,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) { efi_guid_t vendor = LINUX_EFI_CRASH_GUID; struct pstore_read_data *cb_data = data; - char name[DUMP_NAME_LEN]; + char name[DUMP_NAME_LEN], data_type; int i; int cnt; unsigned int part; @@ -54,12 +55,23 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) for (i = 0; i DUMP_NAME_LEN; i++) name[i] = entry-var.VariableName[i]; - if (sscanf(name, dump-type%u-%u-%d-%lu, + if (sscanf(name, dump-type%u-%u-%d-%lu-%c, + cb_data-type, part, cnt, time, data_type) == 5) { + *cb_data-id = part; + *cb_data-count = cnt; + cb_data-timespec-tv_sec = time; + cb_data-timespec-tv_nsec = 0; + if (data_type == 'C') + *cb_data-compressed = true; + else + *cb_data-compressed = false; + } else if (sscanf(name, dump-type%u-%u-%d-%lu, cb_data-type, part, cnt, time) == 4) { *cb_data-id = part; *cb_data-count = cnt; cb_data-timespec-tv_sec = time; cb_data-timespec-tv_nsec = 0; + *cb_data-compressed = false; } else if (sscanf(name, dump-type%u-%u-%lu, cb_data-type, part, time) == 3) { /* @@ -71,6 +83,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) *cb_data-count = 0; cb_data-timespec-tv_sec = time; cb_data-timespec-tv_nsec = 0; + *cb_data-compressed = false; } else return 0; @@ -96,6 +109,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, data.type = type; data.count = count; data.timespec = timespec; + data.compressed = compressed; data.buf = buf; return __efivar_entry_iter(efi_pstore_read_func, efivar_sysfs_list, data, @@ -112,8 +126,8 @@ static int efi_pstore_write(enum pstore_type_id type, efi_guid_t vendor = LINUX_EFI_CRASH_GUID; int i, ret = 0; - sprintf(name, dump-type%u-%u-%d-%lu, type, part, count, - get_seconds()); + sprintf(name, dump-type%u-%u-%d-%lu-%c, type, part, count, + get_seconds(), compressed ? 'C' : 'D'); for (i = 0; i DUMP_NAME_LEN; i++) efi_name[i] = name[i]; ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 08/11] powerpc/pseries: Read and write to the 'compressed' flag of pstore
If data returned from pstore is compressed, nvram's write callback will add a flag ERR_TYPE_KERNEL_PANIC_GZ indicating the data is compressed while writing to nvram. If the data read from nvram is compressed, nvram's read callback will set the flag 'compressed'. The patch adds backward compatibilty with old format oops header when reading from pstore. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- arch/powerpc/platforms/pseries/nvram.c |8 1 file changed, 8 insertions(+) diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 6c4dc52a..d276cd3 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -581,6 +581,9 @@ static int nvram_pstore_write(enum pstore_type_id type, oops_hdr-report_length = (u16) size; oops_hdr-timestamp = get_seconds(); + if (compressed) + err_type = ERR_TYPE_KERNEL_PANIC_GZ; + rc = nvram_write_os_partition(oops_log_partition, oops_buf, (int) (sizeof(*oops_hdr) + size), err_type, count); @@ -687,6 +690,11 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, return -ENOMEM; memcpy(*buf, buff + hdr_size, length); kfree(buff); + + if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) + *compressed = true; + else + *compressed = false; return length; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 07/11] pstore: Add file extension to pstore file if compressed
In case decompression fails, add a .enc.z to indicate the file has compressed data. This will help user space utilities to figure out the file contents. Signed-off-by: Aruna Balakrishnaiah ar...@linux.vnet.ibm.com --- fs/pstore/inode.c|7 --- fs/pstore/internal.h |5 +++-- fs/pstore/platform.c |4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 71bf5f4..519d278 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -275,8 +275,8 @@ int pstore_is_mounted(void) * Set the mtime ctime to the date that this record was originally stored. */ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, - char *data, size_t size, struct timespec time, - struct pstore_info *psi) + char *data, bool compressed, size_t size, + struct timespec time, struct pstore_info *psi) { struct dentry *root = pstore_sb-s_root; struct dentry *dentry; @@ -315,7 +315,8 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, switch (type) { case PSTORE_TYPE_DMESG: - sprintf(name, dmesg-%s-%lld, psname, id); + sprintf(name, dmesg-%s-%lld%s, psname, id, + compressed ? .enc.z : ); break; case PSTORE_TYPE_CONSOLE: sprintf(name, console-%s, psname); diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 937d820..3b3d305 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -50,8 +50,9 @@ extern struct pstore_info *psinfo; extern voidpstore_set_kmsg_bytes(int); extern voidpstore_get_records(int); extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, - int count, char *data, size_t size, - struct timespec time, struct pstore_info *psi); + int count, char *data, bool compressed, + size_t size, struct timespec time, + struct pstore_info *psi); extern int pstore_is_mounted(void); #endif diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 0195cca0..cf0b53f 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -479,13 +479,15 @@ void pstore_get_records(int quiet) if (unzipped_len 0) { buf = big_oops_buf; size = unzipped_len; + compressed = false; } else { pr_err(pstore: decompression failed; returned %d\n, unzipped_len); + compressed = true; } } rc = pstore_mkfile(type, psi-name, id, count, buf, - (size_t)size, time, psi); + compressed, (size_t)size, time, psi); if (unzipped_len 0) { /* Free buffer other than big oops */ kfree(buf); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/2] powerpc/85xx: add hardware automatically enter altivec idle state
On Fri, 2013-08-16 at 06:02 -0500, Kumar Gala wrote: On Aug 16, 2013, at 2:23 AM, Dongsheng Wang wrote: From: Wang Dongsheng dongsheng.w...@freescale.com Each core's AltiVec unit may be placed into a power savings mode by turning off power to the unit. Core hardware will automatically power down the AltiVec unit after no AltiVec instructions have executed in N cycles. The AltiVec power-control is triggered by hardware. Signed-off-by: Wang Dongsheng dongsheng.w...@freescale.com Why treat this as a idle HW governor vs just some one time setup at boot of the time delay? It is being done as one-time setup, despite the function name. Maybe it should be moved into __setup/restore_cpu_e6500 (BTW, we really should refactor those to reduce duplication) with the timebase bit number hardcoded rather than a time in us. As for the PVR check, the upstream kernel doesn't need to care about rev1, so knowing it's an e6500 is good enough. -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 0/4] DT: move of_get_cpu_node from PPC to DT core
From: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com Hi, This series needs to be prepended with the original series[1][2][3] Except the first patch in the original series(which is merged into this as last patch), there is no other change(apart from function signature) I am posting only this part for feedback separately for review as the original series is already reviewed and acked. v1-v2: - Fixed an issue - updating cell pointer - Documentated in arch_match_cpu_phys_id that phys_id are values read from the device tree only in the weak definition [Since first 2 patches have not changed, microblaze and openrisc lists are bouncing for non-members, I am not resending them again. Michal(for microblaze) has acked when it was first pointed. I am waiting for response from Jonas(for openrisc)] Rob, Ben, If you are OK with these patches and ACK, I can combine and post the complete series. Regards, Sudeep Sudeep KarkadaNagesha (4): microblaze: remove undefined of_get_cpu_node declaration openrisc: remove undefined of_get_cpu_node declaration powerpc: refactor of_get_cpu_node to support other architectures of: move of_get_cpu_node implementation to DT core library arch/microblaze/include/asm/prom.h | 3 -- arch/openrisc/include/asm/prom.h | 3 -- arch/powerpc/include/asm/prom.h| 3 -- arch/powerpc/kernel/prom.c | 43 + drivers/of/base.c | 96 ++ include/linux/cpu.h| 1 + include/linux/of.h | 7 +++ 7 files changed, 106 insertions(+), 50 deletions(-) -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH v2 3/4] powerpc: refactor of_get_cpu_node to support other architectures
From: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com Currently different drivers requiring to access cpu device node are parsing the device tree themselves. Since the ordering in the DT need not match the logical cpu ordering, the parsing logic needs to consider that. However, this has resulted in lots of code duplication and in some cases even incorrect logic. It's better to consolidate them by adding support for getting cpu device node for a given logical cpu index in DT core library. However logical to physical index mapping can be architecture specific. PowerPC has it's own implementation to get the cpu node for a given logical index. This patch refactors the current implementation of of_get_cpu_node. This in preparation to move the implementation to DT core library. It separates out the logical to physical mapping so that a default matching of the physical id to the logical cpu index can be added when moved to common code. Architecture specific code can override it. Cc: Rob Herring rob.herr...@calxeda.com Cc: Grant Likely grant.lik...@linaro.org Cc: Benjamin Herrenschmidt b...@kernel.crashing.org Signed-off-by: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com --- arch/powerpc/kernel/prom.c | 76 -- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index eb23ac9..fb12be6 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -865,45 +865,63 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ + return (int)phys_id == get_hard_smp_processor_id(cpu); +} + +static bool __of_find_n_match_cpu_property(struct device_node *cpun, + const char *prop_name, int cpu, unsigned int *thread) +{ + const __be32 *cell; + int ac, prop_len, tid; + u64 hwid; + + ac = of_n_addr_cells(cpun); + cell = of_get_property(cpun, prop_name, prop_len); + if (!cell) + return false; + prop_len /= sizeof(*cell); + for (tid = 0; tid prop_len; tid++) { + hwid = of_read_number(cell, ac); + if (arch_match_cpu_phys_id(cpu, hwid)) { + if (thread) + *thread = tid; + return true; + } + cell += ac; + } + return false; +} + /* Find the device node for a given logical cpu number, also returns the cpu * local thread number (index in ibm,interrupt-server#s) if relevant and * asked for (non NULL) */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) { - int hardid; - struct device_node *np; + struct device_node *cpun, *cpus; - hardid = get_hard_smp_processor_id(cpu); + cpus = of_find_node_by_path(/cpus); + if (!cpus) { + pr_warn(Missing cpus node, bailing out\n); + return NULL; + } - for_each_node_by_type(np, cpu) { - const u32 *intserv; - unsigned int plen, t; + for_each_child_of_node(cpus, cpun) { + if (of_node_cmp(cpun-type, cpu)) + continue; - /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist -* fallback to reg property and assume no threads + /* Check for historical ibm,ppc-interrupt-server#s property +* for thread ids on PowerPC. If it doesn't exist fallback to +* standard reg property. */ - intserv = of_get_property(np, ibm,ppc-interrupt-server#s, - plen); - if (intserv == NULL) { - const u32 *reg = of_get_property(np, reg, NULL); - if (reg == NULL) - continue; - if (*reg == hardid) { - if (thread) - *thread = 0; - return np; - } - } else { - plen /= sizeof(u32); - for (t = 0; t plen; t++) { - if (hardid == intserv[t]) { - if (thread) - *thread = t; - return np; - } - } - } + if (__of_find_n_match_cpu_property(cpun, + ibm,ppc-interrupt-server#s, cpu, thread)) + return cpun; + + if (__of_find_n_match_cpu_property(cpun, reg, cpu, thread)) + return cpun; } return NULL; } -- 1.8.1.2 ___ Linuxppc-dev
[RFC PATCH v2 4/4] of: move of_get_cpu_node implementation to DT core library
From: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com This patch moves the generalized implementation of of_get_cpu_node from PowerPC to DT core library, thereby adding support for retrieving cpu node for a given logical cpu index on any architecture. The CPU subsystem can now use this function to assign of_node in the cpu device while registering CPUs. It is recommended to use these helper function only in pre-SMP/early initialisation stages to retrieve CPU device node pointers in logical ordering. Once the cpu devices are registered, it can be retrieved easily from cpu device of_node which avoids unnecessary parsing and matching. Cc: Rob Herring rob.herr...@calxeda.com Cc: Grant Likely grant.lik...@linaro.org Cc: Benjamin Herrenschmidt b...@kernel.crashing.org Signed-off-by: Sudeep KarkadaNagesha sudeep.karkadanage...@arm.com --- arch/powerpc/include/asm/prom.h | 3 -- arch/powerpc/kernel/prom.c | 57 drivers/of/base.c | 96 + include/linux/cpu.h | 1 + include/linux/of.h | 7 +++ 5 files changed, 104 insertions(+), 60 deletions(-) diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index bc2da15..ac204e0 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h @@ -43,9 +43,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, extern void kdump_move_device_tree(void); -/* CPU OF node matching */ -struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); - /* cache lookup */ struct device_node *of_find_next_cache_node(struct device_node *np); diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index fb12be6..1c14cd4 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -870,63 +870,6 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) return (int)phys_id == get_hard_smp_processor_id(cpu); } -static bool __of_find_n_match_cpu_property(struct device_node *cpun, - const char *prop_name, int cpu, unsigned int *thread) -{ - const __be32 *cell; - int ac, prop_len, tid; - u64 hwid; - - ac = of_n_addr_cells(cpun); - cell = of_get_property(cpun, prop_name, prop_len); - if (!cell) - return false; - prop_len /= sizeof(*cell); - for (tid = 0; tid prop_len; tid++) { - hwid = of_read_number(cell, ac); - if (arch_match_cpu_phys_id(cpu, hwid)) { - if (thread) - *thread = tid; - return true; - } - cell += ac; - } - return false; -} - -/* Find the device node for a given logical cpu number, also returns the cpu - * local thread number (index in ibm,interrupt-server#s) if relevant and - * asked for (non NULL) - */ -struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) -{ - struct device_node *cpun, *cpus; - - cpus = of_find_node_by_path(/cpus); - if (!cpus) { - pr_warn(Missing cpus node, bailing out\n); - return NULL; - } - - for_each_child_of_node(cpus, cpun) { - if (of_node_cmp(cpun-type, cpu)) - continue; - - /* Check for historical ibm,ppc-interrupt-server#s property -* for thread ids on PowerPC. If it doesn't exist fallback to -* standard reg property. -*/ - if (__of_find_n_match_cpu_property(cpun, - ibm,ppc-interrupt-server#s, cpu, thread)) - return cpun; - - if (__of_find_n_match_cpu_property(cpun, reg, cpu, thread)) - return cpun; - } - return NULL; -} -EXPORT_SYMBOL(of_get_cpu_node); - #if defined(CONFIG_DEBUG_FS) defined(DEBUG) static struct debugfs_blob_wrapper flat_dt_blob; diff --git a/drivers/of/base.c b/drivers/of/base.c index 5c54279..6feb823 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -18,6 +18,7 @@ * 2 of the License, or (at your option) any later version. */ #include linux/ctype.h +#include linux/cpu.h #include linux/module.h #include linux/of.h #include linux/spinlock.h @@ -230,6 +231,101 @@ const void *of_get_property(const struct device_node *np, const char *name, } EXPORT_SYMBOL(of_get_property); +/* + * arch_match_cpu_phys_id - Match the given logical CPU and physical id + * + * @cpu: logical cpu index of a core/thread + * @phys_id: physical identifier of a core/thread + * + * CPU logical to physical index mapping is architecture specific. + * However this __weak function provides a default match of physical + * id to logical cpu index. phys_id provided here is usually values read + * from the device tree which must match the hardware internal registers. + * + * Returns true if the physical
RE: [PATCH v6 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
-Original Message- From: Linuxppc-dev [mailto:linuxppc-dev- bounces+bharat.bhushan=freescale@lists.ozlabs.org] On Behalf Of Nicolin Chen Sent: Friday, August 16, 2013 6:27 PM To: broo...@kernel.org; l...@metafoo.de; p.za...@pengutronix.de; s.ha...@pengutronix.de Cc: mark.rutl...@arm.com; devicet...@vger.kernel.org; alsa-devel@alsa- project.org; swar...@wwwdotorg.org; feste...@gmail.com; ti...@tabi.org; rob.herr...@calxeda.com; tomasz.f...@gmail.com; shawn@linaro.org; linuxppc- d...@lists.ozlabs.org Subject: [PATCH v6 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver This patch add S/PDIF controller driver for Freescale SoC. Please give some more description of the driver? Signed-off-by: Nicolin Chen b42...@freescale.com --- .../devicetree/bindings/sound/fsl,spdif.txt| 56 + sound/soc/fsl/Kconfig |3 + sound/soc/fsl/Makefile |2 + sound/soc/fsl/fsl_spdif.c | 1272 sound/soc/fsl/fsl_spdif.h | 224 5 files changed, 1557 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/fsl,spdif.txt create mode 100644 sound/soc/fsl/fsl_spdif.c create mode 100644 sound/soc/fsl/fsl_spdif.h diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt new file mode 100644 index 000..5549ce3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -0,0 +1,56 @@ +Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller + +The Freescale S/PDIF audio block is a stereo transceiver that allows the +processor to receive and transmit digital audio via an coaxial cable or +a fibre cable. + +Required properties: + + - compatible : Compatible list, contains fsl,chip-spdif. + + - reg : Offset and length of the register set for the device. + + - interrupts : Contains spdif interrupt. + + - dmas : Generic dma devicetree binding as described in + Documentation/devicetree/bindings/dma/dma.txt. + + - dma-names : Two dmas have to be defined, tx and rx. + + - clocks : Contains an entry for each entry in clock-names. + + - clock-names : Includes the following entries: + namecomments + core The core clock of spdif controller + rxtx0-7 Clock source list for tx and rx clock. + This clock list should be identical to + the source list connecting to the spdif + clock mux in SPDIF Transceiver Clock + Diagram of SoC reference manual. It + can also be referred to TxClk_Source + bit of register SPDIF_STC. + +Example: + +spdif: spdif@02004000 { + compatible = fsl,imx6q-spdif, + fsl,imx35-spdif; + reg = 0x02004000 0x4000; + interrupts = 0 52 0x04; + dmas = sdma 14 18 0, +sdma 15 18 0; + dma-names = rx, tx; + + clocks = clks 197, clks 3, +clks 197, clks 107, +clks 0, clks 118, +clks 62, clks 139, +clks 0; + clock-names = core, rxtx0, + rxtx1, rxtx2, + rxtx3, rxtx4, + rxtx5, rxtx6, + rxtx7; + + status = okay; +}; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index e15f771..2c518db 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,6 +1,9 @@ config SND_SOC_FSL_SSI tristate +config SND_SOC_FSL_SPDIF + tristate + config SND_SOC_FSL_UTILS tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index d4b4aa8..4b5970e 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -12,9 +12,11 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o # Freescale PowerPC SSI/DMA Platform Support snd-soc-fsl-ssi-objs := fsl_ssi.o +snd-soc-fsl-spdif-objs := fsl_spdif.o snd-soc-fsl-utils-objs := fsl_utils.o snd-soc-fsl-dma-objs := fsl_dma.o obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o +obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c new file mode 100644 index 000..e00125e --- /dev/null +++ b/sound/soc/fsl/fsl_spdif.c @@ -0,0 +1,1272 @@ +/* + * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Based on stmp3xxx_spdif_dai.c + * Vladimir Barinov vbari...@embeddedalley.com + * Copyright 2008 SigmaTel, Inc + * Copyright 2008 Embedded Alley Solutions, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed as is
Re: [RFC] powerpc: put the common parts of the ppc64*defconfigs in a Kconfig file
On Fri, 2013-08-09 at 16:24 +1000, Stephen Rothwell wrote: We cannot put the unsetting of config options in the Kconfig file, nor the integer or string options. I checked that after this we get the same .config files generated (except for the addition of the new PPC64_DEFCONFIG* config options. Any thoughts? Won't this bypass the dependency mechanism? While the dependencies should already be satisfied currently, nothing would prevent them from being switched off later. Even if you have all the dependencies listed in the select, what if dependencies change later? It seems like it would be better to have a way to apply multiple defconfigs at once, and/or have one defconfig include another. -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: PCIE device errors after linux kernel upgrade
On Tue, Aug 6, 2013 at 11:41 PM, Leon Ravich lrav...@gmail.com wrote: From comparison of pci printout from the two kernel , beside the EDAC errors I noticed other strange differences: In 3.8.13 I got BAR 7 and BAR 8: [ 39.017749] pci :00:00.0: BAR 8: assigned [mem 0xc000-0xdfff] [ 39.024530] pci :00:00.0: BAR 7: can't assign io (size 0x1) In 3.8.13 I am getting: [ 38.931873] pci_bus :01: busn_res: can not insert [bus 01-ff] under [bus 00-01] (conflicts with (null) [bus 00-01]) On 6 August 2013 09:32, Leon Ravich lrav...@gmail.com wrote: Thanks Bjorn. Is this still a problem, or have you found a solution in the meantime? 1) If I understand it right this patch only removes the pci :00:00.0: ignoring class 0x0b2000 (doesn't match header type 01) message , don't care about it , had it before . It also affects how the PCI core handles the device. But as you said, if you had the message before, it's probably not the cause of the current problem. 2) regarding the comparing of printouts: Can you post the complete logs somewhere, maybe in a bugzilla or similar? Where are the PCIE ERR_CAP_STAT and similar messages from? My quick grep didn't find them. Bjorn ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH v2 3/4] powerpc: refactor of_get_cpu_node to support other architectures
On Fri, 2013-08-16 at 18:39 +0100, Sudeep KarkadaNagesha wrote: +static bool __of_find_n_match_cpu_property(struct device_node *cpun, + const char *prop_name, int cpu, unsigned int *thread) +{ + const __be32 *cell; + int ac, prop_len, tid; + u64 hwid; + + ac = of_n_addr_cells(cpun); + cell = of_get_property(cpun, prop_name, prop_len); + if (!cell) + return false; + prop_len /= sizeof(*cell); + for (tid = 0; tid prop_len; tid++) { + hwid = of_read_number(cell, ac); + if (arch_match_cpu_phys_id(cpu, hwid)) { + if (thread) + *thread = tid; + return true; + } + cell += ac; + } + return false; +} The only problem I can see here is if ac is not 1, that will not work for the ibm,ppc-interrupt-server#s case. IE. The latter is always 1 cell per entry, only reg depends on #address-cells. However that's only a theorical problem since on ppc #address-cells of /cpus is always 1... Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
RE: [RFC PATCH v2 00/11] Add (de)compression support to pstore
Needs testing with erst backend, efivars and persistent ram. Tested against ERST - works fine for me now. Need to stare at the code to see if there are any more bits that could be cleaned up. Thanks for addressing my issues from v1 -Tony ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC PATCH v2 4/4] of: move of_get_cpu_node implementation to DT core library
On Fri, 2013-08-16 at 18:39 +0100, Sudeep KarkadaNagesha wrote: +#ifdef CONFIG_PPC + /* Check for historical ibm,ppc-interrupt-server#s property +* for thread ids on PowerPC. If it doesn't exist fallback to +* standard reg property. +*/ + if (__of_find_n_match_cpu_property(cpun, + ibm,ppc-interrupt-server#s, cpu, thread)) + return cpun; +#endif It's not historical. It's still very much in use and well defined in PAPR :-) Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [alsa-devel] [PATCH v4 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
On 08/15/2013 03:24 AM, Shawn Guo wrote: On Thu, Aug 15, 2013 at 10:18:23AM +0800, Nicolin Chen wrote: Hi Stephen, On Wed, Aug 14, 2013 at 09:47:19AM -0600, Stephen Warren wrote: If the clock source name list is different, then it needs a different compatible value, so that each compatible value can specify which clock names are required. Also, the compatible value itself should always include the exact HW that's present (most specific HW version), as well as any other HW it's compatible with. Thank you for the comments. Yes, I did so in v1-v3, but after rethinking about the situation (Actually both the HW version and the clock mux itself are same, just the clock sources connecting to the mux might be different), so I decided to do this by abstracting the driver from those source info and letting DT binding to pass such information. Because I think putting the clock sources into the driver differed by compatible value would make the driver more like SoC-specified, not the ideal way -- SoC-independent, since the clock sources are based on SoC design, not on itself. +1 It's pretty much the differences at SoC integration level not the IP itself, and it just happens to be handled in a register of the IP. OK, if the difference are the sources of the clocks and not the set of clocks, then there's no issue. I can't remember what triggered my comments above, but obviously it wasn't clear that this was the case. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
MPC8315 reboot failure, lockdep splat possibly related?
Greetings. I've been experiencing occasional lockups at reboot for a few weeks, but only once every 10-20 boots. A good reboot looks like this: [47529.721640] lm77 0-0048: shutdown [47529.725160] rtc-m41t80 0-0068: shutdown [47529.729169] i2c i2c-0: shutdown [47529.732534] fsl-ehci fsl-ehci.0: shutdown [47529.736842] sd 1:0:0:0: shutdown [47529.740239] sd 1:0:0:0: [sda] Synchronizing SCSI cache [47529.747091] uio_pci_generic :00:0a.0: shutdown [47529.752079] pci :00:00.0: shutdown [47529.756021] Restarting system. While a bad one fails after the EHCI shutdown: [ 747.578001] lm77 0-0048: shutdown [ 747.581522] rtc-m41t80 0-0068: shutdown [ 747.585538] i2c i2c-0: shutdown [ 747.588909] sd 1:0:0:0: shutdown [ 747.592304] sd 1:0:0:0: [sda] Synchronizing SCSI cache [ 747.597973] fsl-ehci fsl-ehci.0: shutdown I enabled lockdep, and I get this splat on every boot, regardless of whether it locks up at reboot or not. Could it possibly be related? Any other ideas on how to avoid the reboot lockup? [9.086051] = [9.090393] [ INFO: inconsistent lock state ] [9.094744] 3.9.7-ajf-gc39503d #1 Not tainted [9.099087] - [9.103432] inconsistent {HARDIRQ-ON-W} - {IN-HARDIRQ-W} usage. [9.109431] scsi_eh_1/39 [HC1[1]:SC0[0]:HE0:SE1] takes: [9.114642] ((host-lock)-rlock){?.+...}, at: [c02f4168] sata_fsl_interrupt+0x50/0x250 [9.123137] {HARDIRQ-ON-W} state was registered at: [9.128004] [c006cdb8] lock_acquire+0x90/0xf4 [9.132737] [c043ef04] _raw_spin_lock+0x34/0x4c [9.137645] [c02f3560] fsl_sata_set_irq_coalescing+0x68/0x100 [9.143750] [c02f36a0] sata_fsl_init_controller+0xa8/0xc0 [9.149505] [c02f3f10] sata_fsl_probe+0x17c/0x2e8 [9.154568] [c02acc90] driver_probe_device+0x90/0x248 [9.159987] [c02acf0c] __driver_attach+0xc4/0xc8 [9.164964] [c02aae74] bus_for_each_dev+0x5c/0xa8 [9.170028] [c02ac218] bus_add_driver+0x100/0x26c [9.175091] [c02ad638] driver_register+0x88/0x198 [9.180155] [c0003a24] do_one_initcall+0x58/0x1b4 [9.185226] [c05aeeac] kernel_init_freeable+0x118/0x1c0 [9.190823] [c0004110] kernel_init+0x18/0x108 [9.195542] [c000f6b8] ret_from_kernel_thread+0x64/0x6c [9.201142] irq event stamp: 160 [9.204366] hardirqs last enabled at (159): [c043f778] _raw_spin_unlock_irq+0x30/0x50 [9.212469] hardirqs last disabled at (160): [c000f414] reenable_mmu+0x30/0x88 [9.219867] softirqs last enabled at (144): [c002ae5c] __do_softirq+0x168/0x218 [9.227435] softirqs last disabled at (137): [c002b0d4] irq_exit+0xa8/0xb4 [9.234481] [9.234481] other info that might help us debug this: [9.240995] Possible unsafe locking scenario: [9.240995] [9.246898]CPU0 [9.249337] [9.251776] lock((host-lock)-rlock); [9.255878] Interrupt [9.258492] lock((host-lock)-rlock); [9.262765] [9.262765] *** DEADLOCK *** [9.262765] [9.268684] no locks held by scsi_eh_1/39. [9.272767] [9.272767] stack backtrace: [9.277117] Call Trace: [9.279589] [cfff9da0] [c0008504] show_stack+0x48/0x150 (unreliable) [9.285972] [cfff9de0] [c0447d5c] print_usage_bug.part.35+0x268/0x27c [9.292425] [cfff9e10] [c006ace4] mark_lock+0x2ac/0x658 [9.297660] [cfff9e40] [c006b7e4] __lock_acquire+0x754/0x1840 [9.303414] [cfff9ee0] [c006cdb8] lock_acquire+0x90/0xf4 [9.308745] [cfff9f20] [c043ef04] _raw_spin_lock+0x34/0x4c [9.314250] [cfff9f30] [c02f4168] sata_fsl_interrupt+0x50/0x250 [9.320187] [cfff9f70] [c0079ff0] handle_irq_event_percpu+0x90/0x254 [9.326547] [cfff9fc0] [c007a1fc] handle_irq_event+0x48/0x78 [9.332220] [cfff9fe0] [c007c95c] handle_level_irq+0x9c/0x104 [9.337981] [cfff9ff0] [c000d978] call_handle_irq+0x18/0x28 [9.343568] [cc7139f0] [c000608c] do_IRQ+0xf0/0x1a8 [9.348464] [cc713a20] [c000fc8c] ret_from_except+0x0/0x14 [9.353983] --- Exception: 501 at _raw_spin_unlock_irq+0x40/0x50 [9.353983] LR = _raw_spin_unlock_irq+0x30/0x50 [9.364839] [cc713af0] [c043db10] wait_for_common+0xac/0x188 [9.370513] [cc713b30] [c02ddee4] ata_exec_internal_sg+0x2b0/0x4f0 [9.376699] [cc713be0] [c02de18c] ata_exec_internal+0x68/0xa8 [9.382454] [cc713c20] [c02de4b8] ata_dev_read_id+0x158/0x594 [9.388205] [cc713ca0] [c02ec244] ata_eh_recover+0xd88/0x13d0 [9.393962] [cc713d20] [c02f2520] sata_pmp_error_handler+0xc0/0x8ac [9.400234] [cc713dd0] [c02ecdc8] ata_scsi_port_error_handler+0x464/0x5e8 [9.407023] [cc713e10] [c02ecfd0] ata_scsi_error+0x84/0xb8 [9.412528] [cc713e40] [c02c4974] scsi_error_handler+0xd8/0x47c [9.418457] [cc713eb0] [c004737c] kthread+0xa8/0xac [9.423355] [cc713f40] [c000f6b8]
RE: MPC8315 reboot failure, lockdep splat possibly related?
-Original Message- From: Linuxppc-dev [mailto:linuxppc-dev- bounces+bharat.bhushan=freescale@lists.ozlabs.org] On Behalf Of Anthony Foiani Sent: Saturday, August 17, 2013 7:10 AM To: linuxppc-dev@lists.ozlabs.org Subject: MPC8315 reboot failure, lockdep splat possibly related? Greetings. I've been experiencing occasional lockups at reboot for a few weeks, but only once every 10-20 boots. A good reboot looks like this: [47529.721640] lm77 0-0048: shutdown [47529.725160] rtc-m41t80 0-0068: shutdown [47529.729169] i2c i2c-0: shutdown [47529.732534] fsl-ehci fsl-ehci.0: shutdown [47529.736842] sd 1:0:0:0: shutdown [47529.740239] sd 1:0:0:0: [sda] Synchronizing SCSI cache [47529.747091] uio_pci_generic :00:0a.0: shutdown [47529.752079] pci :00:00.0: shutdown [47529.756021] Restarting system. While a bad one fails after the EHCI shutdown: [ 747.578001] lm77 0-0048: shutdown [ 747.581522] rtc-m41t80 0-0068: shutdown [ 747.585538] i2c i2c-0: shutdown [ 747.588909] sd 1:0:0:0: shutdown [ 747.592304] sd 1:0:0:0: [sda] Synchronizing SCSI cache [ 747.597973] fsl-ehci fsl-ehci.0: shutdown I enabled lockdep, and I get this splat on every boot, regardless of whether it locks up at reboot or not. Could it possibly be related? Any other ideas on how to avoid the reboot lockup? [9.086051] = [9.090393] [ INFO: inconsistent lock state ] [9.094744] 3.9.7-ajf-gc39503d #1 Not tainted [9.099087] - [9.103432] inconsistent {HARDIRQ-ON-W} - {IN-HARDIRQ-W} usage. [9.109431] scsi_eh_1/39 [HC1[1]:SC0[0]:HE0:SE1] takes: [9.114642] ((host-lock)-rlock){?.+...}, at: [c02f4168] sata_fsl_interrupt+0x50/0x250 [9.123137] {HARDIRQ-ON-W} state was registered at: [9.128004] [c006cdb8] lock_acquire+0x90/0xf4 [9.132737] [c043ef04] _raw_spin_lock+0x34/0x4c [9.137645] [c02f3560] fsl_sata_set_irq_coalescing+0x68/0x100 [9.143750] [c02f36a0] sata_fsl_init_controller+0xa8/0xc0 [9.149505] [c02f3f10] sata_fsl_probe+0x17c/0x2e8 [9.154568] [c02acc90] driver_probe_device+0x90/0x248 [9.159987] [c02acf0c] __driver_attach+0xc4/0xc8 [9.164964] [c02aae74] bus_for_each_dev+0x5c/0xa8 [9.170028] [c02ac218] bus_add_driver+0x100/0x26c [9.175091] [c02ad638] driver_register+0x88/0x198 [9.180155] [c0003a24] do_one_initcall+0x58/0x1b4 [9.185226] [c05aeeac] kernel_init_freeable+0x118/0x1c0 [9.190823] [c0004110] kernel_init+0x18/0x108 [9.195542] [c000f6b8] ret_from_kernel_thread+0x64/0x6c [9.201142] irq event stamp: 160 [9.204366] hardirqs last enabled at (159): [c043f778] _raw_spin_unlock_irq+0x30/0x50 [9.212469] hardirqs last disabled at (160): [c000f414] reenable_mmu+0x30/0x88 [9.219867] softirqs last enabled at (144): [c002ae5c] __do_softirq+0x168/0x218 [9.227435] softirqs last disabled at (137): [c002b0d4] irq_exit+0xa8/0xb4 [9.234481] [9.234481] other info that might help us debug this: [9.240995] Possible unsafe locking scenario: [9.240995] [9.246898]CPU0 [9.249337] [9.251776] lock((host-lock)-rlock); [9.255878] Interrupt [9.258492] lock((host-lock)-rlock); [9.262765] [9.262765] *** DEADLOCK *** You should get rid of this by changing spin_lock/unlock() in fsl_sata_set_irq_coalescing() to spin_lock_irqsave/restore() -Bharat [9.262765] [9.268684] no locks held by scsi_eh_1/39. [9.272767] [9.272767] stack backtrace: [9.277117] Call Trace: [9.279589] [cfff9da0] [c0008504] show_stack+0x48/0x150 (unreliable) [9.285972] [cfff9de0] [c0447d5c] print_usage_bug.part.35+0x268/0x27c [9.292425] [cfff9e10] [c006ace4] mark_lock+0x2ac/0x658 [9.297660] [cfff9e40] [c006b7e4] __lock_acquire+0x754/0x1840 [9.303414] [cfff9ee0] [c006cdb8] lock_acquire+0x90/0xf4 [9.308745] [cfff9f20] [c043ef04] _raw_spin_lock+0x34/0x4c [9.314250] [cfff9f30] [c02f4168] sata_fsl_interrupt+0x50/0x250 [9.320187] [cfff9f70] [c0079ff0] handle_irq_event_percpu+0x90/0x254 [9.326547] [cfff9fc0] [c007a1fc] handle_irq_event+0x48/0x78 [9.332220] [cfff9fe0] [c007c95c] handle_level_irq+0x9c/0x104 [9.337981] [cfff9ff0] [c000d978] call_handle_irq+0x18/0x28 [9.343568] [cc7139f0] [c000608c] do_IRQ+0xf0/0x1a8 [9.348464] [cc713a20] [c000fc8c] ret_from_except+0x0/0x14 [9.353983] --- Exception: 501 at _raw_spin_unlock_irq+0x40/0x50 [9.353983] LR = _raw_spin_unlock_irq+0x30/0x50 [9.364839] [cc713af0] [c043db10] wait_for_common+0xac/0x188 [9.370513] [cc713b30] [c02ddee4] ata_exec_internal_sg+0x2b0/0x4f0 [9.376699] [cc713be0] [c02de18c] ata_exec_internal+0x68/0xa8 [