* [RFC PATCH v2 04/10] powerpc/book3s: Introduce a early machine check hook in cpu_spec.
From: Mahesh J Salgaonkar @ 2013-08-16 8:04 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt
Cc: Jeremy Kerr, Paul Mackerras, Anton Blanchard
In-Reply-To: <20130816080213.680.50794.stgit@mars.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@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 <mahesh@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
^ permalink raw reply related
* [RFC PATCH v2 03/10] powerpc/book3s: handle machine check in Linux host.
From: Mahesh J Salgaonkar @ 2013-08-16 8:04 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt
Cc: Jeremy Kerr, Paul Mackerras, Anton Blanchard
In-Reply-To: <20130816080213.680.50794.stgit@mars.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@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_early ME=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 <mahesh@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 */
+machine_check_pSeries_early:
+BEGIN_FTR_SECTION
+ EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200)
+ /*
+ * Register contents:
+ * R12 = interrupt vector
+ * R13 = PACA
+ * R9 = CR
+ * R11 & R12 is saved on PACA_EXMC
+ *
+ * Switch to mc_emergency stack and handle re-entrancy (though we
+ * currently don't test for overflow). Save MCE registers srr1,
+ * srr0, dar and dsisr and then set ME=1
+ *
+ * We use paca->in_mce to check whether this is the first entry or
+ * nested machine check. We increment paca->in_mce to track nested
+ * machine checks.
+ *
+ * If this is the first entry then set stack pointer to
+ * paca->mc_emergency_sp, otherwise r1 is already pointing to
+ * stack frame on mc_emergency stack.
+ *
+ * NOTE: We are here with MSR_ME=0 (off), which means we risk a
+ * checkstop if we get another machine check exception before we do
+ * rfid with MSR_ME=1.
+ */
+ mr r11,r1 /* Save r1 */
+ lhz r10,PACA_IN_MCE(r13)
+ cmpwi r10,0 /* Are we in nested machine check */
+ bne 0f /* Yes, we are. */
+ /* First machine check entry */
+ ld r1,PACAMCEMERGSP(r13) /* Use MC emergency stack */
+0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */
+ addi r10,r10,1 /* increment paca->in_mce */
+ sth r10,PACA_IN_MCE(r13)
+ std r11,GPR1(r1) /* Save r1 on the stack. */
+ std r11,0(r1) /* make stack chain pointer */
+ mfspr r11,SPRN_SRR0 /* Save SRR0 */
+ std r11,_NIP(r1)
+ mfspr r11,SPRN_SRR1 /* Save SRR1 */
+ std r11,_MSR(r1)
+ mfspr r11,SPRN_DAR /* Save DAR */
+ std r11,_DAR(r1)
+ mfspr r11,SPRN_DSISR /* Save DSISR */
+ std r11,_DSISR(r1)
+ mfmsr r11 /* get MSR value */
+ ori r11,r11,MSR_ME /* turn on ME bit */
+ ld r12,PACAKBASE(r13) /* get high part of &label */
+ LOAD_HANDLER(r12, machine_check_handle_early)
+ mtspr SPRN_SRR0,r12
+ mtspr SPRN_SRR1,r11
+ rfid
+ b . /* prevent speculative execution */
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
machine_check_pSeries:
.globl machine_check_fwnmi
machine_check_fwnmi:
@@ -681,6 +740,55 @@ machine_check_common:
bl .machine_check_exception
b .ret_from_except
+ /*
+ * Handle machine check early in real mode. We come here with
+ * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
+ */
+ .align 7
+ .globl machine_check_handle_early
+machine_check_handle_early:
+BEGIN_FTR_SECTION
+ std r9,_CCR(r1) /* Save CR in stackframe */
+ std r0,GPR0(r1) /* Save r0 */
+ EXCEPTION_PROLOG_COMMON_2(0x200, PACA_EXMC)
+ bl .save_nvgprs
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .machine_check_early
+ /* Move original SRR0 and SRR1 into the respective regs */
+ ld r9,_MSR(r1)
+ mtspr SPRN_SRR1,r9
+ ld r3,_NIP(r1)
+ mtspr SPRN_SRR0,r3
+ REST_NVGPRS(r1)
+ ld r9,_CTR(r1)
+ mtctr r9
+ ld r9,_XER(r1)
+ mtxer r9
+ ld r9,_CCR(r1)
+ mtcr r9
+BEGIN_FTR_SECTION_NESTED(66)
+ ld r9,ORIG_GPR3(r1)
+ mtspr SPRN_CFAR,r9
+END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66)
+ ld r9,_LINK(r1)
+ mtlr r9
+ REST_GPR(0, r1)
+ REST_8GPRS(2, r1)
+ REST_2GPRS(10, r1)
+
+ /* Decrement paca->in_mce. */
+ lhz r12,PACA_IN_MCE(r13)
+ subi r12,r12,1
+ sth r12,PACA_IN_MCE(r13)
+ REST_2GPRS(12, r1)
+ /*
+ * restore original r1. We have already saved MCE info to per
+ * cpu MCE event buffer.
+ */
+ ld r1,GPR1(r1)
+ b machine_check_pSeries
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf33c22..1720e08 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -286,6 +286,18 @@ void system_reset_exception(struct pt_regs *regs)
/* What should we do here? We could issue a shutdown or hard reset. */
}
+
+/*
+ * This function is called in real mode. Strictly no printk's please.
+ *
+ * regs->nip and regs->msr contains srr0 and ssr1.
+ */
+long machine_check_early(struct pt_regs *regs)
+{
+ /* TODO: handle/decode machine check reason */
+ return 0;
+}
+
#endif
/*
^ permalink raw reply related
* [RFC PATCH v2 02/10] powerpc/book3s: Introduce exclusive emergency stack for machine check exception.
From: Mahesh J Salgaonkar @ 2013-08-16 8:04 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt
Cc: Jeremy Kerr, Paul Mackerras, Anton Blanchard
In-Reply-To: <20130816080213.680.50794.stgit@mars.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@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 <mahesh@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");
^ permalink raw reply related
* [RFC PATCH v2 01/10] powerpc/book3s: Split the common exception prolog logic into two section.
From: Mahesh J Salgaonkar @ 2013-08-16 8:03 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt
Cc: Jeremy Kerr, Paul Mackerras, Anton Blanchard
In-Reply-To: <20130816080213.680.50794.stgit@mars.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@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 <mahesh@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); \
- 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 */ \
+4: EXCEPTION_PROLOG_COMMON_2(n, area) \
ACCOUNT_STOLEN_TIME
/*
^ permalink raw reply related
* [RFC PATCH v2 00/10] Machine check handling in linux host.
From: Mahesh J Salgaonkar @ 2013-08-16 8:03 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt
Cc: Jeremy Kerr, Paul Mackerras, Anton Blanchard
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
^ permalink raw reply
* Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
From: Nicolin Chen @ 2013-08-16 8:01 UTC (permalink / raw)
To: Sascha Hauer
Cc: mark.rutland, devicetree, alsa-devel, lars, ian.campbell,
pawel.moll, swarren, festevam, Tomasz Figa, rob.herring, timur,
broonie, p.zabel, galak, shawn.guo, linuxppc-dev
In-Reply-To: <20130816070818.GM26614@pengutronix.de>
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:
"tx<0-8>" Optional Tx 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:
"rx<0-16>" Optional Rx 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
^ permalink raw reply
* Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
From: Sascha Hauer @ 2013-08-16 7:08 UTC (permalink / raw)
To: Nicolin Chen
Cc: mark.rutland, devicetree, alsa-devel, lars, ian.campbell,
pawel.moll, swarren, festevam, Tomasz Figa, rob.herring, timur,
broonie, p.zabel, galak, shawn.guo, linuxppc-dev
In-Reply-To: <20130816044330.GD1846@MrMyself>
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:
> > > + name type comments
> > > + "core" Required The core clock of spdif controller
> > > +
> > > + "rx" Optional Rx clock source for spdif record.
> > > + If absent, will use core clock.
> > > +
> > > + "tx" Optional Tx clock source for spdif playback.
> > > + If absent, will use core clock.
> > > +
> > > + "tx-32000" Optional Tx clock source for 32000Hz sample rate
> > > + playback. If absent, will use tx clock.
> > > +
> > > + "tx-44100" Optional Tx clock source for 44100Hz sample rate
> > > + playback. If absent, will use tx clock.
> > > +
> > > + "tx-48000" Optional Tx clock source for 48000Hz sample rate
> > > + playback. If absent, will use tx clock.
> > > +
> > > + "src<0-7>" Optional Clock 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 "src<0-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 src<0-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
> 'src<num>'.
>
> 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:
>
> 0000 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 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.
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-5555 |
^ permalink raw reply
* [PATCH 6/6 v4] kvm: powerpc: use caching attributes as per linux pte
From: Bharat Bhushan @ 2013-08-16 5:14 UTC (permalink / raw)
To: benh, agraf, paulus, kvm, kvm-ppc, linuxppc-dev, scottwood; +Cc: Bharat Bhushan
KVM uses same WIM tlb attributes as the corresponding qemu pte.
For this we now search the linux pte for the requested page and
get these cache caching/coherency attributes from pte.
Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v3->v4
- s/printk/printk_ratelimited till we return machine check in mmu setup
v2->v3
- setting pgdir before kvmppc_fix_ee_before_entry() on vcpu_run
- Aligned as per changes in patch 5/6
- setting WIMG for pfnmap pages also
v1->v2
- Use Linux pte for wimge rather than RAM/no-RAM mechanism
arch/powerpc/include/asm/kvm_host.h | 2 +-
arch/powerpc/kvm/booke.c | 2 +-
arch/powerpc/kvm/e500.h | 8 ++++--
arch/powerpc/kvm/e500_mmu_host.c | 38 ++++++++++++++++++++--------------
4 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 3328353..583d405 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -535,6 +535,7 @@ struct kvm_vcpu_arch {
#endif
gpa_t paddr_accessed;
gva_t vaddr_accessed;
+ pgd_t *pgdir;
u8 io_gpr; /* GPR used as IO source/target */
u8 mmio_is_bigendian;
@@ -592,7 +593,6 @@ struct kvm_vcpu_arch {
struct list_head run_list;
struct task_struct *run_task;
struct kvm_run *kvm_run;
- pgd_t *pgdir;
spinlock_t vpa_update_lock;
struct kvmppc_vpa vpa;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 17722d8..0d96d50 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -696,8 +696,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
kvmppc_load_guest_fp(vcpu);
#endif
+ vcpu->arch.pgdir = current->mm->pgd;
kvmppc_fix_ee_before_entry();
-
ret = __kvmppc_vcpu_run(kvm_run, vcpu);
/* No need for kvm_guest_exit. It's done in handle_exit.
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 4fd9650..fc4b2f6 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -31,11 +31,13 @@ enum vcpu_ftr {
#define E500_TLB_NUM 2
/* entry is mapped somewhere in host TLB */
-#define E500_TLB_VALID (1 << 0)
+#define E500_TLB_VALID (1 << 31)
/* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
-#define E500_TLB_BITMAP (1 << 1)
+#define E500_TLB_BITMAP (1 << 30)
/* TLB1 entry is mapped by host TLB0 */
-#define E500_TLB_TLB0 (1 << 2)
+#define E500_TLB_TLB0 (1 << 29)
+/* Lower 5 bits have WIMGE value */
+#define E500_TLB_WIMGE_MASK (0x1f)
struct tlbe_ref {
pfn_t pfn; /* valid only for TLB0, except briefly */
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 1c6a9d7..603f5ba 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -64,15 +64,6 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode)
return mas3;
}
-static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
-{
-#ifdef CONFIG_SMP
- return (mas2 & MAS2_ATTRIB_MASK) | MAS2_M;
-#else
- return mas2 & MAS2_ATTRIB_MASK;
-#endif
-}
-
/*
* writing shadow tlb entry to host TLB
*/
@@ -248,10 +239,12 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
struct kvm_book3e_206_tlb_entry *gtlbe,
- pfn_t pfn)
+ pfn_t pfn, int wimg)
{
ref->pfn = pfn;
ref->flags |= E500_TLB_VALID;
+ /* Use guest supplied MAS2_G and MAS2_E */
+ ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg;
if (tlbe_is_writable(gtlbe))
kvm_set_pfn_dirty(pfn);
@@ -312,8 +305,7 @@ static void kvmppc_e500_setup_stlbe(
/* Force IPROT=0 for all guest mappings. */
stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID;
- stlbe->mas2 = (gvaddr & MAS2_EPN) |
- e500_shadow_mas2_attrib(gtlbe->mas2, pr);
+ stlbe->mas2 = (gvaddr & MAS2_EPN) | (ref->flags & E500_TLB_WIMGE_MASK);
stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT) |
e500_shadow_mas3_attrib(gtlbe->mas7_3, pr);
@@ -332,6 +324,10 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
unsigned long hva;
int pfnmap = 0;
int tsize = BOOK3E_PAGESZ_4K;
+ unsigned long tsize_pages = 0;
+ pte_t *ptep;
+ int wimg = 0;
+ pgd_t *pgdir;
/*
* Translate guest physical to true physical, acquiring
@@ -394,7 +390,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
*/
for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
- unsigned long gfn_start, gfn_end, tsize_pages;
+ unsigned long gfn_start, gfn_end;
tsize_pages = 1 << (tsize - 2);
gfn_start = gfn & ~(tsize_pages - 1);
@@ -436,9 +432,10 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
}
if (likely(!pfnmap)) {
- unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
+ tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
+
pfn = gfn_to_pfn_memslot(slot, gfn);
- if (is_error_noslot_pfn(pfn)) {
+ if (printk_ratelimit() && is_error_noslot_pfn(pfn)) {
printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
(long)gfn);
return -EINVAL;
@@ -449,7 +446,16 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
}
- kvmppc_e500_ref_setup(ref, gtlbe, pfn);
+ pgdir = vcpu_e500->vcpu.arch.pgdir;
+ ptep = lookup_linux_pte(pgdir, hva, &tsize_pages);
+ if (pte_present(*ptep)) {
+ wimg = (pte_val(*ptep) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+ } else if (printk_ratelimit()) {
+ printk(KERN_ERR "%s: pte not present: gfn %lx, pfn %lx\n",
+ __func__, (long)gfn, pfn);
+ return -EINVAL;
+ }
+ kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
ref, gvaddr, stlbe);
--
1.7.0.4
^ permalink raw reply related
* Critical Interrupt Input
From: Henry Bausley @ 2013-08-16 4:57 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 602 bytes --]
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?
Outbound scan for Spam or Virus by Barracuda at Delta Tau
[-- Attachment #2: Type: text/html, Size: 748 bytes --]
^ permalink raw reply
* Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
From: Benjamin Herrenschmidt @ 2013-08-16 4:49 UTC (permalink / raw)
To: Sudeep KarkadaNagesha
Cc: Jonas Bonn, devicetree, Michal Simek, linux-pm,
microblaze-uclinux, linux, linux-kernel, Rob Herring,
Rafael J. Wysocki, Grant Likely, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1376586580-5409-4-git-send-email-Sudeep.KarkadaNagesha@arm.com>
On Thu, 2013-08-15 at 18:09 +0100, Sudeep KarkadaNagesha wrote:
> From: Sudeep KarkadaNagesha <sudeep.karkadanagesha@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.
> +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;
> + }
> + 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
> */
> - 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;
> }
Cheers,
Ben.
^ permalink raw reply
* Re: [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
From: Benjamin Herrenschmidt @ 2013-08-16 4:50 UTC (permalink / raw)
To: Sudeep KarkadaNagesha
Cc: Jonas Bonn, devicetree, Michal Simek, linux-pm,
microblaze-uclinux, linux, linux-kernel, Rob Herring,
Rafael J. Wysocki, Grant Likely, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1376586580-5409-4-git-send-email-Sudeep.KarkadaNagesha@arm.com>
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...
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH v5 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
From: Nicolin Chen @ 2013-08-16 4:43 UTC (permalink / raw)
To: Tomasz Figa
Cc: mark.rutland, devicetree, alsa-devel, lars, ian.campbell,
pawel.moll, swarren, festevam, s.hauer, timur, rob.herring,
broonie, p.zabel, galak, shawn.guo, linuxppc-dev
In-Reply-To: <2188999.03O3zirCAO@flatron>
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:
> > + name type comments
> > + "core" Required The core clock of spdif controller
> > +
> > + "rx" Optional Rx clock source for spdif record.
> > + If absent, will use core clock.
> > +
> > + "tx" Optional Tx clock source for spdif playback.
> > + If absent, will use core clock.
> > +
> > + "tx-32000" Optional Tx clock source for 32000Hz sample rate
> > + playback. If absent, will use tx clock.
> > +
> > + "tx-44100" Optional Tx clock source for 44100Hz sample rate
> > + playback. If absent, will use tx clock.
> > +
> > + "tx-48000" Optional Tx clock source for 48000Hz sample rate
> > + playback. If absent, will use tx clock.
> > +
> > + "src<0-7>" Optional Clock 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 "src<0-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 src<0-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
'src<num>'.
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:
0000 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 for the below part:
> > +Optional properties:
> > +
> > + - rx-clksrc-lock: This is a boolean property. If present, ClkSrc_Sel
> > bit + of SPDIF_SRPC would be set a clock source that cares DPLL locked
> > condition. +
>
> This again looks like software configuration, not hardware description.
> Could you elaborate a bit more on meaning of this property?
I think the rx-clksrc-lock property should be included in DT as well, since
it's exactly a available clock source for rx. But I guess I just need to
figure out a better way or a more elaborated description.
Thank you,
Nicolin Chen
^ permalink raw reply
* Re: [PATCH] powerpc/powernv: Return secondary CPUs to firmware on kexec
From: Benjamin Herrenschmidt @ 2013-08-16 3:34 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev
In-Reply-To: <CAEjGV6wdjnoh__eAZ0pFh9o+-=ZpDB-Sg9CBuA2Z+FepgK1-1w@mail.gmail.com>
On Fri, 2013-08-16 at 11:16 +1000, Michael Neuling wrote:
>
> > With OPAL v3 we can return secondary CPUs to firmware on kexec. This
> > allows firmware to do various cleanups making things generally more
> > reliable, and will enable the "new" kernel to call OPAL to perform
> > some reconfiguration tasks early on that can only be done while
> > all the CPUs are in firmware.
>
> Dumb question, but isn't the point of kexec to avoid fw interactions
> like this?
The point of kexec is to avoid rebooting :-)
Sending secondaries back to the OPAL internal spin loop doesn't take a
noticeable amount of time.
We could avoid doing it and solve the problem of needing all CPUs in
firmware for "reconfig" differently however. We could have the "target"
kernel code take them out of kexec into a special path that goes back
into the fw ... I chose the kexec solution because it was simpler and
less code :-)
Cheers,
Ben.
> Mikey
>
>
> > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >
> > diff --git a/arch/powerpc/platforms/powernv/setup.c
> b/arch/powerpc/platforms/powernv/setup.c
> > index d4459bf..b59a1da 100644
> > --- a/arch/powerpc/platforms/powernv/setup.c
> > +++ b/arch/powerpc/platforms/powernv/setup.c
> > @@ -31,6 +31,7 @@
> > #include <asm/xics.h>
> > #include <asm/rtas.h>
> > #include <asm/opal.h>
> > +#include <asm/kexec.h>
> >
> > #include "powernv.h"
> >
> > @@ -143,6 +144,16 @@ static void pnv_shutdown(void)
> > static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
> > {
> > xics_kexec_teardown_cpu(secondary);
> > +
> > + /* Return secondary CPUs to firmware on OPAL v3 */
> > + if (firmware_has_feature(FW_FEATURE_OPALv3) && secondary) {
> > + mb();
> > + get_paca()->kexec_state = KEXEC_STATE_REAL_MODE;
> > + mb();
> > +
> > + /* Return the CPU to OPAL */
> > + opal_return_cpu();
> > + }
> > }
> > #endif /* CONFIG_KEXEC */
> >
> >
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> >
>
>
^ permalink raw reply
* Re: [PATCH v3 0/7] net: use platform_{get,set}_drvdata()
From: Libo Chen @ 2013-08-16 2:15 UTC (permalink / raw)
To: David Miller
Cc: sergei.shtylyov, gregkh, netdev, jg1.han, lizefan, vbordug,
linuxppc-dev
In-Reply-To: <20130815.153903.859166500375208182.davem@davemloft.net>
On 2013/8/16 6:39, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Thu, 15 Aug 2013 15:23:59 -0700 (PDT)
>
>> From: Libo Chen <clbchenlibo.chen@huawei.com>
>> Date: Thu, 15 Aug 2013 21:01:17 +0800
>>
>>> Use the wrapper functions for getting and setting the driver data using
>>> platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev,
>>> so we can directly pass a struct platform_device.
>>>
>>> changelog v3:
>>> remove modify about dev_set_drvdata()
>>> changelog v2:
>>> this version add modify record about dev_set_drvdata().
>>
>> Series applied.
>
> Actually, I had to revert, these patches break the build.
>
> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_probe’:
> drivers/net/ethernet/sun/sunhme.c:3114:2: error: implicit declaration of function ‘platform_set_drvdata’ [-Werror=implicit-function-declaration]
> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_remove’:
> drivers/net/ethernet/sun/sunhme.c:3162:9: error: implicit declaration of function ‘platform_get_drvdata’ [-Werror=implicit-function-declaration]
> drivers/net/ethernet/sun/sunhme.c:3162:26: warning: initialization makes pointer from integer without a cast [enabled by default]
>
oh, it is my fault, I will update!
^ permalink raw reply
* Re: [PATCH] powerpc/powernv: Return secondary CPUs to firmware on kexec
From: Michael Neuling @ 2013-08-16 1:16 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1376611546.4255.120.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 1561 bytes --]
> With OPAL v3 we can return secondary CPUs to firmware on kexec. This
> allows firmware to do various cleanups making things generally more
> reliable, and will enable the "new" kernel to call OPAL to perform
> some reconfiguration tasks early on that can only be done while
> all the CPUs are in firmware.
Dumb question, but isn't the point of kexec to avoid fw interactions like
this?
Mikey
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> diff --git a/arch/powerpc/platforms/powernv/setup.c
b/arch/powerpc/platforms/powernv/setup.c
> index d4459bf..b59a1da 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -31,6 +31,7 @@
> #include <asm/xics.h>
> #include <asm/rtas.h>
> #include <asm/opal.h>
> +#include <asm/kexec.h>
>
> #include "powernv.h"
>
> @@ -143,6 +144,16 @@ static void pnv_shutdown(void)
> static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
> {
> xics_kexec_teardown_cpu(secondary);
> +
> + /* Return secondary CPUs to firmware on OPAL v3 */
> + if (firmware_has_feature(FW_FEATURE_OPALv3) && secondary) {
> + mb();
> + get_paca()->kexec_state = KEXEC_STATE_REAL_MODE;
> + mb();
> +
> + /* Return the CPU to OPAL */
> + opal_return_cpu();
> + }
> }
> #endif /* CONFIG_KEXEC */
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
[-- Attachment #2: Type: text/html, Size: 2203 bytes --]
^ permalink raw reply
* [PATCH] powerpc/wsp: Fix early debug build
From: Benjamin Herrenschmidt @ 2013-08-16 0:13 UTC (permalink / raw)
To: linuxppc-dev
When reworking udbg_16550.c I forgot to remove the old and now useless
code for the CONFIG_PPC_EARLY_DEBUG_WSP case, which doesn't build as
a result. I also missed a cast.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 25c58e8..75702e2 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -300,45 +300,9 @@ void __init udbg_init_40x_realmode(void)
#ifdef CONFIG_PPC_EARLY_DEBUG_WSP
-static void udbg_wsp_flush(void)
-{
- if (udbg_comport) {
- while ((readb(&udbg_comport->lsr) & LSR_THRE) == 0)
- /* wait for idle */;
- }
-}
-
-static void udbg_wsp_putc(char c)
-{
- if (udbg_comport) {
- if (c == '\n')
- udbg_wsp_putc('\r');
- udbg_wsp_flush();
- writeb(c, &udbg_comport->thr); eieio();
- }
-}
-
-static int udbg_wsp_getc(void)
-{
- if (udbg_comport) {
- while ((readb(&udbg_comport->lsr) & LSR_DR) == 0)
- ; /* wait for char */
- return readb(&udbg_comport->rbr);
- }
- return -1;
-}
-
-static int udbg_wsp_getc_poll(void)
-{
- if (udbg_comport)
- if (readb(&udbg_comport->lsr) & LSR_DR)
- return readb(&udbg_comport->rbr);
- return -1;
-}
-
void __init udbg_init_wsp(void)
{
- udbg_uart_init_mmio(WSP_UART_VIRT, 1);
+ udbg_uart_init_mmio((void *)WSP_UART_VIRT, 1);
udbg_uart_setup(57600, 50000000);
}
^ permalink raw reply related
* [PATCH] powerpc/powernv: Return secondary CPUs to firmware on kexec
From: Benjamin Herrenschmidt @ 2013-08-16 0:05 UTC (permalink / raw)
To: linuxppc-dev
With OPAL v3 we can return secondary CPUs to firmware on kexec. This
allows firmware to do various cleanups making things generally more
reliable, and will enable the "new" kernel to call OPAL to perform
some reconfiguration tasks early on that can only be done while
all the CPUs are in firmware.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index d4459bf..b59a1da 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -31,6 +31,7 @@
#include <asm/xics.h>
#include <asm/rtas.h>
#include <asm/opal.h>
+#include <asm/kexec.h>
#include "powernv.h"
@@ -143,6 +144,16 @@ static void pnv_shutdown(void)
static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
{
xics_kexec_teardown_cpu(secondary);
+
+ /* Return secondary CPUs to firmware on OPAL v3 */
+ if (firmware_has_feature(FW_FEATURE_OPALv3) && secondary) {
+ mb();
+ get_paca()->kexec_state = KEXEC_STATE_REAL_MODE;
+ mb();
+
+ /* Return the CPU to OPAL */
+ opal_return_cpu();
+ }
}
#endif /* CONFIG_KEXEC */
^ permalink raw reply related
* Re: [PATCH v3 0/7] net: use platform_{get,set}_drvdata()
From: Sergei Shtylyov @ 2013-08-15 23:04 UTC (permalink / raw)
To: David Miller, clbchenlibo.chen
Cc: gregkh, netdev, jg1.han, lizefan, vbordug, linuxppc-dev
In-Reply-To: <520D5B88.7080304@cogentembedded.com>
On 08/16/2013 02:51 AM, Sergei Shtylyov wrote:
>>> From: Libo Chen <clbchenlibo.chen@huawei.com>
>>> Date: Thu, 15 Aug 2013 21:01:17 +0800
>>>> Use the wrapper functions for getting and setting the driver data using
>>>> platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev,
>>>> so we can directly pass a struct platform_device.
>>>> changelog v3:
>>>> remove modify about dev_set_drvdata()
>>>> changelog v2:
>>>> this version add modify record about dev_set_drvdata().
>>> Series applied.
>> Actually, I had to revert, these patches break the build.
>> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_probe’:
>> drivers/net/ethernet/sun/sunhme.c:3114:2: error: implicit declaration of
>> function ‘platform_set_drvdata’ [-Werror=implicit-function-declaration]
>> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_remove’:
>> drivers/net/ethernet/sun/sunhme.c:3162:9: error: implicit declaration of
>> function ‘platform_get_drvdata’ [-Werror=implicit-function-declaration]
>> drivers/net/ethernet/sun/sunhme.c:3162:26: warning: initialization makes
>> pointer from integer without a cast [enabled by default]
> Hm, patch #5 was clearly defective as it tried to call
> platform_{get|set}_drvdata() on PCI devices -- I've read the patch but
> overlooked that. And the driver lacks #include <linux/platform_device.h>, so
> I'm not sure it always compiled flawlessly.
Ah, the platform code is protected by #ifdef CONFIG_SBUS... probably some
header #include's <linux/platform_device.h>?
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v3 0/7] net: use platform_{get,set}_drvdata()
From: Sergei Shtylyov @ 2013-08-15 22:51 UTC (permalink / raw)
To: David Miller, clbchenlibo.chen
Cc: gregkh, netdev, jg1.han, lizefan, vbordug, linuxppc-dev
In-Reply-To: <20130815.153903.859166500375208182.davem@davemloft.net>
Hello.
On 08/16/2013 02:39 AM, David Miller wrote:
>> From: Libo Chen <clbchenlibo.chen@huawei.com>
>> Date: Thu, 15 Aug 2013 21:01:17 +0800
>>> Use the wrapper functions for getting and setting the driver data using
>>> platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev,
>>> so we can directly pass a struct platform_device.
>>> changelog v3:
>>> remove modify about dev_set_drvdata()
>>> changelog v2:
>>> this version add modify record about dev_set_drvdata().
>> Series applied.
> Actually, I had to revert, these patches break the build.
> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_probe’:
> drivers/net/ethernet/sun/sunhme.c:3114:2: error: implicit declaration of function ‘platform_set_drvdata’ [-Werror=implicit-function-declaration]
> drivers/net/ethernet/sun/sunhme.c: In function ‘happy_meal_pci_remove’:
> drivers/net/ethernet/sun/sunhme.c:3162:9: error: implicit declaration of function ‘platform_get_drvdata’ [-Werror=implicit-function-declaration]
> drivers/net/ethernet/sun/sunhme.c:3162:26: warning: initialization makes pointer from integer without a cast [enabled by default]
Hm, patch #5 was clearly defective as it tried to call
platform_{get|set}_drvdata() on PCI devices -- I've read the patch but
overlooked that. And the driver lacks #include <linux/platform_device.h>, so
I'm not sure it always compiled flawlessly.
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v3 0/7] net: use platform_{get,set}_drvdata()
From: David Miller @ 2013-08-15 22:39 UTC (permalink / raw)
To: clbchenlibo.chen
Cc: sergei.shtylyov, gregkh, netdev, jg1.han, lizefan, vbordug,
linuxppc-dev
In-Reply-To: <20130815.152359.920302339053249583.davem@davemloft.net>
RnJvbTogRGF2aWQgTWlsbGVyIDxkYXZlbUBkYXZlbWxvZnQubmV0Pg0KRGF0ZTogVGh1LCAxNSBB
dWcgMjAxMyAxNToyMzo1OSAtMDcwMCAoUERUKQ0KDQo+IEZyb206IExpYm8gQ2hlbiA8Y2xiY2hl
bmxpYm8uY2hlbkBodWF3ZWkuY29tPg0KPiBEYXRlOiBUaHUsIDE1IEF1ZyAyMDEzIDIxOjAxOjE3
ICswODAwDQo+IA0KPj4gVXNlIHRoZSB3cmFwcGVyIGZ1bmN0aW9ucyBmb3IgZ2V0dGluZyBhbmQg
c2V0dGluZyB0aGUgZHJpdmVyIGRhdGEgdXNpbmcNCj4+IHBsYXRmb3JtX2RldmljZSBpbnN0ZWFk
IG9mIHVzaW5nIGRldl97Z2V0LHNldH1fZHJ2ZGF0YSgpIHdpdGggJnBkZXYtPmRldiwNCj4+IHNv
IHdlIGNhbiBkaXJlY3RseSBwYXNzIGEgc3RydWN0IHBsYXRmb3JtX2RldmljZS4NCj4+IA0KPj4g
Y2hhbmdlbG9nIHYzOg0KPj4gCXJlbW92ZSBtb2RpZnkgYWJvdXQgZGV2X3NldF9kcnZkYXRhKCkN
Cj4+IGNoYW5nZWxvZyB2MjoNCj4+IAl0aGlzIHZlcnNpb24gYWRkIG1vZGlmeSByZWNvcmQgYWJv
dXQgZGV2X3NldF9kcnZkYXRhKCkuDQo+IA0KPiBTZXJpZXMgYXBwbGllZC4NCg0KQWN0dWFsbHks
IEkgaGFkIHRvIHJldmVydCwgdGhlc2UgcGF0Y2hlcyBicmVhayB0aGUgYnVpbGQuDQoNCmRyaXZl
cnMvbmV0L2V0aGVybmV0L3N1bi9zdW5obWUuYzogSW4gZnVuY3Rpb24goWhhcHB5X21lYWxfcGNp
X3Byb2JlojoNCmRyaXZlcnMvbmV0L2V0aGVybmV0L3N1bi9zdW5obWUuYzozMTE0OjI6IGVycm9y
OiBpbXBsaWNpdCBkZWNsYXJhdGlvbiBvZiBmdW5jdGlvbiChcGxhdGZvcm1fc2V0X2RydmRhdGGi
IFstV2Vycm9yPWltcGxpY2l0LWZ1bmN0aW9uLWRlY2xhcmF0aW9uXQ0KZHJpdmVycy9uZXQvZXRo
ZXJuZXQvc3VuL3N1bmhtZS5jOiBJbiBmdW5jdGlvbiChaGFwcHlfbWVhbF9wY2lfcmVtb3ZlojoN
CmRyaXZlcnMvbmV0L2V0aGVybmV0L3N1bi9zdW5obWUuYzozMTYyOjk6IGVycm9yOiBpbXBsaWNp
dCBkZWNsYXJhdGlvbiBvZiBmdW5jdGlvbiChcGxhdGZvcm1fZ2V0X2RydmRhdGGiIFstV2Vycm9y
PWltcGxpY2l0LWZ1bmN0aW9uLWRlY2xhcmF0aW9uXQ0KZHJpdmVycy9uZXQvZXRoZXJuZXQvc3Vu
L3N1bmhtZS5jOjMxNjI6MjY6IHdhcm5pbmc6IGluaXRpYWxpemF0aW9uIG1ha2VzIHBvaW50ZXIg
ZnJvbSBpbnRlZ2VyIHdpdGhvdXQgYSBjYXN0IFtlbmFibGVkIGJ5IGRlZmF1bHRdDQo=
^ permalink raw reply
* Re: [PATCH v3 0/7] net: use platform_{get,set}_drvdata()
From: David Miller @ 2013-08-15 22:23 UTC (permalink / raw)
To: clbchenlibo.chen
Cc: sergei.shtylyov, gregkh, netdev, jg1.han, lizefan, vbordug,
linuxppc-dev
In-Reply-To: <520CD11D.8010202@huawei.com>
From: Libo Chen <clbchenlibo.chen@huawei.com>
Date: Thu, 15 Aug 2013 21:01:17 +0800
> Use the wrapper functions for getting and setting the driver data using
> platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev,
> so we can directly pass a struct platform_device.
>
> changelog v3:
> remove modify about dev_set_drvdata()
> changelog v2:
> this version add modify record about dev_set_drvdata().
Series applied.
^ permalink raw reply
* Re: [PATCH 1/3] cpufreq: pmac64: speed up frequency switch
From: Benjamin Herrenschmidt @ 2013-08-15 22:14 UTC (permalink / raw)
To: Aaro Koskinen
Cc: Rafael J. Wysocki, Nick Piggin, linux-pm, linuxppc-dev,
Viresh Kumar
In-Reply-To: <20130815201000.GB3067@blackmetal.musicnaut.iki.fi>
On Thu, 2013-08-15 at 23:10 +0300, Aaro Koskinen wrote:
> I guess we should keep the current 12us latency in g5_neo2_cpufreq_init()
> (although I doubt it's correct...), and only add the new 10ms latency
> value to g5_pm72_cpufreq_init() - that way we can enable the older systems
> to use ondemand (despite long latencies), while not risking regressing
> any of the current functionality.
>
> I'll resend the series with the changes.
Well, mine is a 11,2, it's not a neo2.
I suppose we could try to measure the latency :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 1/3] cpufreq: pmac64: speed up frequency switch
From: Aaro Koskinen @ 2013-08-15 20:10 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Rafael J. Wysocki, Nick Piggin, linux-pm, linuxppc-dev,
Viresh Kumar
In-Reply-To: <1376269668.32100.148.camel@pasglop>
Hi,
On Mon, Aug 12, 2013 at 11:07:48AM +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2013-07-24 at 07:14 +1000, Benjamin Herrenschmidt wrote:
> > On Tue, 2013-07-23 at 23:20 +0200, Rafael J. Wysocki wrote:
> > > All looks good in the patchset from 10000 feet (or more), but I need
> > > Ben to speak here.
> >
> > I want to give it a quick spin on the HW here, I'll ack then. But yes,
> > it looks good.
>
> Seems to work here on the quad G5.
>
> However, If I use on-demand, there's a huge latency of switch as far as
> I can tell (about 10s) after I start/stop a bunch of CPU eaters... I
> quite like how the userspace "powernowd" which I used to use switches
> more aggressively.
>
> Is that expected ?
I guess we should keep the current 12us latency in g5_neo2_cpufreq_init()
(although I doubt it's correct...), and only add the new 10ms latency
value to g5_pm72_cpufreq_init() - that way we can enable the older systems
to use ondemand (despite long latencies), while not risking regressing
any of the current functionality.
I'll resend the series with the changes.
A.
^ permalink raw reply
* [RFC PATCH 3/4] powerpc: refactor of_get_cpu_node to support other architectures
From: Sudeep KarkadaNagesha @ 2013-08-15 17:09 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, linux-pm, devicetree,
microblaze-uclinux, linux, linuxppc-dev
Cc: Jonas Bonn, Michal Simek, Sudeep KarkadaNagesha, Rob Herring,
Rafael J. Wysocki, Grant Likely
In-Reply-To: <1376586580-5409-1-git-send-email-Sudeep.KarkadaNagesha@arm.com>
From: Sudeep KarkadaNagesha <sudeep.karkadanagesha@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.herring@calxeda.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
---
arch/powerpc/kernel/prom.c | 70 ++++++++++++++++++++++++++++--------------=
----
1 file changed, 43 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eb23ac9..594c9f9 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -865,45 +865,61 @@ static int __init prom_reconfig_setup(void)
__initcall(prom_reconfig_setup);
#endif
=20
+bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+=09return (int)phys_id =3D=3D get_hard_smp_processor_id(cpu);
+}
+
+static bool __of_find_n_match_cpu_property(struct device_node *cpun,
+=09=09=09const char *prop_name, int cpu, unsigned int *thread)
+{
+=09const __be32 *cell;
+=09int ac, prop_len, tid;
+=09u64 hwid;
+
+=09ac =3D of_n_addr_cells(cpun);
+=09cell =3D of_get_property(cpun, prop_name, &prop_len);
+=09if (!cell)
+=09=09return false;
+=09prop_len /=3D sizeof(*cell);
+=09for (tid =3D 0; tid < prop_len; tid++) {
+=09=09hwid =3D of_read_number(cell, ac);
+=09=09if (arch_match_cpu_phys_id(cpu, hwid)) {
+=09=09=09if (thread)
+=09=09=09=09*thread =3D tid;
+=09=09=09return true;
+=09=09}
+=09}
+=09return false;
+}
+
/* Find the device node for a given logical cpu number, also returns the c=
pu
* 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)
{
-=09int hardid;
-=09struct device_node *np;
+=09struct device_node *cpun, *cpus;
=20
-=09hardid =3D get_hard_smp_processor_id(cpu);
+=09cpus =3D of_find_node_by_path("/cpus");
+=09if (!cpus) {
+=09=09pr_warn("Missing cpus node, bailing out\n");
+=09=09return NULL;
+=09}
=20
-=09for_each_node_by_type(np, "cpu") {
-=09=09const u32 *intserv;
-=09=09unsigned int plen, t;
+=09for_each_child_of_node(cpus, cpun) {
+=09=09if (of_node_cmp(cpun->type, "cpu"))
+=09=09=09continue;
=20
=09=09/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
=09=09 * fallback to "reg" property and assume no threads
=09=09 */
-=09=09intserv =3D of_get_property(np, "ibm,ppc-interrupt-server#s",
-=09=09=09=09&plen);
-=09=09if (intserv =3D=3D NULL) {
-=09=09=09const u32 *reg =3D of_get_property(np, "reg", NULL);
-=09=09=09if (reg =3D=3D NULL)
-=09=09=09=09continue;
-=09=09=09if (*reg =3D=3D hardid) {
-=09=09=09=09if (thread)
-=09=09=09=09=09*thread =3D 0;
-=09=09=09=09return np;
-=09=09=09}
-=09=09} else {
-=09=09=09plen /=3D sizeof(u32);
-=09=09=09for (t =3D 0; t < plen; t++) {
-=09=09=09=09if (hardid =3D=3D intserv[t]) {
-=09=09=09=09=09if (thread)
-=09=09=09=09=09=09*thread =3D t;
-=09=09=09=09=09return np;
-=09=09=09=09}
-=09=09=09}
-=09=09}
+=09=09if (__of_find_n_match_cpu_property(cpun,
+=09=09=09=09"ibm,ppc-interrupt-server#s", cpu, thread))
+=09=09=09return cpun;
+
+=09=09if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
+=09=09=09return cpun;
=09}
=09return NULL;
}
--=20
1.8.1.2
^ permalink raw reply related
* [RFC PATCH 4/4] of: move of_get_cpu_node implementation to DT core library
From: Sudeep KarkadaNagesha @ 2013-08-15 17:09 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, linux-pm, devicetree,
microblaze-uclinux, linux, linuxppc-dev
Cc: Jonas Bonn, Michal Simek, Sudeep KarkadaNagesha, Rob Herring,
Rafael J. Wysocki, Grant Likely
In-Reply-To: <1376586580-5409-1-git-send-email-Sudeep.KarkadaNagesha@arm.com>
From: Sudeep KarkadaNagesha <sudeep.karkadanagesha@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.herring@calxeda.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
---
arch/powerpc/include/asm/prom.h | 3 --
arch/powerpc/kernel/prom.c | 55 ------------------------
drivers/of/base.c | 94 +++++++++++++++++++++++++++++++++++++=
++++
include/linux/cpu.h | 1 +
include/linux/of.h | 7 +++
5 files changed, 102 insertions(+), 58 deletions(-)
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/pro=
m.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 vo=
id *dma_window_prop,
=20
extern void kdump_move_device_tree(void);
=20
-/* 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);
=20
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 594c9f9..1c14cd4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -870,61 +870,6 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
=09return (int)phys_id =3D=3D get_hard_smp_processor_id(cpu);
}
=20
-static bool __of_find_n_match_cpu_property(struct device_node *cpun,
-=09=09=09const char *prop_name, int cpu, unsigned int *thread)
-{
-=09const __be32 *cell;
-=09int ac, prop_len, tid;
-=09u64 hwid;
-
-=09ac =3D of_n_addr_cells(cpun);
-=09cell =3D of_get_property(cpun, prop_name, &prop_len);
-=09if (!cell)
-=09=09return false;
-=09prop_len /=3D sizeof(*cell);
-=09for (tid =3D 0; tid < prop_len; tid++) {
-=09=09hwid =3D of_read_number(cell, ac);
-=09=09if (arch_match_cpu_phys_id(cpu, hwid)) {
-=09=09=09if (thread)
-=09=09=09=09*thread =3D tid;
-=09=09=09return true;
-=09=09}
-=09}
-=09return false;
-}
-
-/* Find the device node for a given logical cpu number, also returns the c=
pu
- * 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)
-{
-=09struct device_node *cpun, *cpus;
-
-=09cpus =3D of_find_node_by_path("/cpus");
-=09if (!cpus) {
-=09=09pr_warn("Missing cpus node, bailing out\n");
-=09=09return NULL;
-=09}
-
-=09for_each_child_of_node(cpus, cpun) {
-=09=09if (of_node_cmp(cpun->type, "cpu"))
-=09=09=09continue;
-
-=09=09/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
-=09=09 * fallback to "reg" property and assume no threads
-=09=09 */
-=09=09if (__of_find_n_match_cpu_property(cpun,
-=09=09=09=09"ibm,ppc-interrupt-server#s", cpu, thread))
-=09=09=09return cpun;
-
-=09=09if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
-=09=09=09return cpun;
-=09}
-=09return NULL;
-}
-EXPORT_SYMBOL(of_get_cpu_node);
-
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
static struct debugfs_blob_wrapper flat_dt_blob;
=20
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 5c54279..d088e45 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,99 @@ const void *of_get_property(const struct device_node *=
np, const char *name,
}
EXPORT_SYMBOL(of_get_property);
=20
+/*
+ * arch_match_cpu_phys_id - Match the given logical CPU and physical id
+ *
+ * @cpu: logical index of a cpu
+ * @phys_id: physical identifier of a cpu
+ *
+ * CPU logical to physical index mapping is architecture specific.
+ * However this __weak function provides a default match of physical
+ * id to logical cpu index.
+ *
+ * Returns true if the physical identifier and the logical index correspon=
d
+ * to the same cpu, false otherwise.
+ */
+bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+=09return (u32)phys_id =3D=3D cpu;
+}
+
+/**
+ * Checks if the given "prop_name" property holds the physical id of the
+ * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
+ * NULL, local thread number within the core is returned in it.
+ */
+static bool __of_find_n_match_cpu_property(struct device_node *cpun,
+=09=09=09const char *prop_name, int cpu, unsigned int *thread)
+{
+=09const __be32 *cell;
+=09int ac, prop_len, tid;
+=09u64 hwid;
+
+=09ac =3D of_n_addr_cells(cpun);
+=09cell =3D of_get_property(cpun, prop_name, &prop_len);
+=09if (!cell)
+=09=09return false;
+=09prop_len /=3D sizeof(*cell);
+=09for (tid =3D 0; tid < prop_len; tid++) {
+=09=09hwid =3D of_read_number(cell, ac);
+=09=09if (arch_match_cpu_phys_id(cpu, hwid)) {
+=09=09=09if (thread)
+=09=09=09=09*thread =3D tid;
+=09=09=09return true;
+=09=09}
+=09}
+=09return false;
+}
+
+/**
+ * of_get_cpu_node - Get device node associated with the given logical CPU
+ *
+ * @cpu: CPU number(logical index) for which device node is required
+ * @thread: if not NULL, local thread number within the physical core is
+ * returned
+ *
+ * The main purpose of this function is to retrieve the device node for th=
e
+ * given logical CPU index. It should be used to initialize the of_node in
+ * cpu device. Once of_node in cpu device is populated, all the further
+ * references can use that instead.
+ *
+ * CPU logical to physical index mapping is architecture specific and is b=
uilt
+ * before booting secondary cores. This function uses arch_match_cpu_phys_=
id
+ * which can be overridden by architecture specific implementation.
+ *
+ * Returns a node pointer for the logical cpu if found, else NULL.
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
+{
+=09struct device_node *cpun, *cpus;
+
+=09cpus =3D of_find_node_by_path("/cpus");
+=09if (!cpus) {
+=09=09pr_warn("Missing cpus node, bailing out\n");
+=09=09return NULL;
+=09}
+
+=09for_each_child_of_node(cpus, cpun) {
+=09=09if (of_node_cmp(cpun->type, "cpu"))
+=09=09=09continue;
+#ifdef CONFIG_PPC
+=09=09/* Check for historical "ibm,ppc-interrupt-server#s" property
+=09=09 * for thread ids on PowerPC. If it doesn't exist fallback to
+=09=09 * standard "reg" property.
+=09=09 */
+=09=09if (__of_find_n_match_cpu_property(cpun,
+=09=09=09=09"ibm,ppc-interrupt-server#s", cpu, thread))
+=09=09=09return cpun;
+#endif
+=09=09if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
+=09=09=09return cpun;
+=09}
+=09return NULL;
+}
+EXPORT_SYMBOL(of_get_cpu_node);
+
/** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property
*/
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index ab0eade..3dfed2b 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -28,6 +28,7 @@ struct cpu {
extern int register_cpu(struct cpu *cpu, int num);
extern struct device *get_cpu_device(unsigned cpu);
extern bool cpu_is_hotpluggable(unsigned cpu);
+extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
=20
extern int cpu_add_dev_attr(struct device_attribute *attr);
extern void cpu_remove_dev_attr(struct device_attribute *attr);
diff --git a/include/linux/of.h b/include/linux/of.h
index 1fd08ca..c0bb2f1 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -266,6 +266,7 @@ extern int of_device_is_available(const struct device_n=
ode *device);
extern const void *of_get_property(const struct device_node *node,
=09=09=09=09const char *name,
=09=09=09=09int *lenp);
+extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
#define for_each_property_of_node(dn, pp) \
=09for (pp =3D dn->properties; pp !=3D NULL; pp =3D pp->next)
=20
@@ -459,6 +460,12 @@ static inline const void *of_get_property(const struct=
device_node *node,
=09return NULL;
}
=20
+static inline struct device_node *of_get_cpu_node(int cpu,
+=09=09=09=09=09unsigned int *thread)
+{
+=09return NULL;
+}
+
static inline int of_property_read_u64(const struct device_node *np,
=09=09=09=09 const char *propname, u64 *out_value)
{
--=20
1.8.1.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox