* [PATCH 1/3] powerpc/tm: Disable IRQ in tm_recheckpoint
From: Michael Neuling @ 2014-03-28 5:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Michael Neuling, Paul Mackerras
We can't take an IRQ when we're about to do a trechkpt as our GPR state is set
to user GPR values.
We've hit this when running some IBM Java stress tests in the lab resulting in
the following dump:
cpu 0x3f: Vector: 700 (Program Check) at [c000000007eb3d40]
pc: c000000000050074: restore_gprs+0xc0/0x148
lr: 00000000b52a8184
sp: ac57d360
msr: 8000000100201030
current = 0xc00000002c500000
paca = 0xc000000007dbfc00 softe: 0 irq_happened: 0x00
pid = 34535, comm = Pooled Thread #
R00 = 00000000b52a8184 R16 = 00000000b3e48fda
R01 = 00000000ac57d360 R17 = 00000000ade79bd8
R02 = 00000000ac586930 R18 = 000000000fac9bcc
R03 = 00000000ade60000 R19 = 00000000ac57f930
R04 = 00000000f6624918 R20 = 00000000ade79be8
R05 = 00000000f663f238 R21 = 00000000ac218a54
R06 = 0000000000000002 R22 = 000000000f956280
R07 = 0000000000000008 R23 = 000000000000007e
R08 = 000000000000000a R24 = 000000000000000c
R09 = 00000000b6e69160 R25 = 00000000b424cf00
R10 = 0000000000000181 R26 = 00000000f66256d4
R11 = 000000000f365ec0 R27 = 00000000b6fdcdd0
R12 = 00000000f66400f0 R28 = 0000000000000001
R13 = 00000000ada71900 R29 = 00000000ade5a300
R14 = 00000000ac2185a8 R30 = 00000000f663f238
R15 = 0000000000000004 R31 = 00000000f6624918
pc = c000000000050074 restore_gprs+0xc0/0x148
cfar= c00000000004fe28 dont_restore_vec+0x1c/0x1a4
lr = 00000000b52a8184
msr = 8000000100201030 cr = 24804888
ctr = 0000000000000000 xer = 0000000000000000 trap = 700
This moves tm_recheckpoint to a C function and moves the tm_restore_sprs into
that function. It then adds IRQ disabling over the trechkpt critical section.
It also sets the TEXASR FS in the signals code to ensure this is never set now
that we explictly write the TM sprs in tm_recheckpoint.
Signed-off-by: Michael Neuling <mikey@neuling.org>
cc: stable@vger.kernel.org
---
arch/powerpc/kernel/process.c | 30 +++++++++++++++++++++++++-----
arch/powerpc/kernel/signal_32.c | 2 ++
arch/powerpc/kernel/signal_64.c | 2 ++
arch/powerpc/kernel/tm.S | 2 +-
4 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index af064d2..913334c 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -610,6 +610,31 @@ out_and_saveregs:
tm_save_sprs(thr);
}
+extern void __tm_recheckpoint(struct thread_struct *thread,
+ unsigned long orig_msr);
+
+void tm_recheckpoint(struct thread_struct *thread,
+ unsigned long orig_msr)
+{
+ unsigned long flags;
+
+ /* We really can't be interrupted here as the TEXASR registers can't
+ * change and later in the trecheckpoint code, we have a userspace R1.
+ * So let's hard disable over this region.
+ */
+ local_irq_save(flags);
+ hard_irq_disable();
+
+ /* The TM SPRs are restored here, so that TEXASR.FS can be set
+ * before the trecheckpoint and no explosion occurs.
+ */
+ tm_restore_sprs(thread);
+
+ __tm_recheckpoint(thread, orig_msr);
+
+ local_irq_restore(flags);
+}
+
static inline void tm_recheckpoint_new_task(struct task_struct *new)
{
unsigned long msr;
@@ -628,11 +653,6 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
if (!new->thread.regs)
return;
- /* The TM SPRs are restored here, so that TEXASR.FS can be set
- * before the trecheckpoint and no explosion occurs.
- */
- tm_restore_sprs(&new->thread);
-
if (!MSR_TM_ACTIVE(new->thread.regs->msr))
return;
msr = new->thread.tm_orig_msr;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index a67e00a..4e47db6 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -881,6 +881,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
* transactional versions should be loaded.
*/
tm_enable();
+ /* Make sure the transaction is marked as failed */
+ current->thread.tm_texasr |= TEXASR_FS;
/* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(¤t->thread, msr);
/* Get the top half of the MSR */
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 8d253c2..d501dc4 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -527,6 +527,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
}
#endif
tm_enable();
+ /* Make sure the transaction is marked as failed */
+ current->thread.tm_texasr |= TEXASR_FS;
/* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(¤t->thread, msr);
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index ef47bcb..03567c0 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -307,7 +307,7 @@ dont_backup_fp:
* Call with IRQs off, stacks get all out of sync for
* some periods in here!
*/
-_GLOBAL(tm_recheckpoint)
+_GLOBAL(__tm_recheckpoint)
mfcr r5
mflr r0
stw r5, 8(r1)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/3] powerpc/tm: Remove unnecessary r1 save
From: Michael Neuling @ 2014-03-28 5:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Michael Neuling, Paul Mackerras
In-Reply-To: <1395985234-27281-1-git-send-email-mikey@neuling.org>
We save r1 to the scratch SPR and restore it from there after the trechkpt so
saving r1 to the paca is not needed.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/tm.S | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 03567c0..0535c7f 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -320,8 +320,6 @@ _GLOBAL(__tm_recheckpoint)
*/
SAVE_NVGPRS(r1)
- std r1, PACAR1(r13)
-
/* Load complete register state from ts_ckpt* registers */
addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/3] powerpc/tm: Add checking to treclaim/trechkpt
From: Michael Neuling @ 2014-03-28 5:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Michael Neuling, Paul Mackerras
In-Reply-To: <1395985234-27281-1-git-send-email-mikey@neuling.org>
If we do a treclaim and we are not in TM suspend mode, it results in a TM bad
thing (ie. a 0x700 program check). Similarly if we do a trechkpt and we have
an active transaction or TEXASR Failure Summary (FS) is not set, we also take a
TM bad thing.
This should never happen, but if it does (ie. a kernel bug), the cause is
almost impossible to debug as the GPR state is mostly userspace and hence we
don't get a call chain.
This adds some checks in these cases case a BUG_ON() (in asm) in case we ever
hit these cases. It moves the register saving around to preserve r1 till later
also.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/kernel/tm.S | 38 +++++++++++++++++++++++++++++++++++---
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1a36b8e..c09627d 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -214,6 +214,7 @@
#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
#define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */
#define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */
+#define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */
#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 0535c7f..508c54b 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -10,6 +10,7 @@
#include <asm/ppc-opcode.h>
#include <asm/ptrace.h>
#include <asm/reg.h>
+#include <asm/bug.h>
#ifdef CONFIG_VSX
/* See fpu.S, this is borrowed from there */
@@ -175,6 +176,13 @@ dont_backup_vec:
stfd fr0,FPSTATE_FPSCR(r7)
dont_backup_fp:
+ /* Do sanity check on MSR to make sure we are suspended */
+ li r7, (MSR_TS_S)@higher
+ srdi r6, r14, 32
+ and r6, r6, r7
+1: tdeqi r6, 0
+ EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
/* The moment we treclaim, ALL of our GPRs will switch
* to user register state. (FPRs, CCR etc. also!)
* Use an sprg and a tm_scratch in the PACA to shuffle.
@@ -383,12 +391,10 @@ restore_gprs:
/* ******************** CR,LR,CCR,MSR ********** */
ld r4, _CTR(r7)
ld r5, _LINK(r7)
- ld r6, _CCR(r7)
ld r8, _XER(r7)
mtctr r4
mtlr r5
- mtcr r6
mtxer r8
/* ******************** TAR ******************** */
@@ -404,7 +410,8 @@ restore_gprs:
li r4, 0
mtmsrd r4, 1
- REST_4GPRS(0, r7) /* GPR0-3 */
+ REST_GPR(0, r7) /* GPR0 */
+ REST_2GPRS(2, r7) /* GPR2-3 */
REST_GPR(4, r7) /* GPR4 */
REST_4GPRS(8, r7) /* GPR8-11 */
REST_2GPRS(12, r7) /* GPR12-13 */
@@ -416,6 +423,31 @@ restore_gprs:
mtspr SPRN_DSCR, r5
mtspr SPRN_PPR, r6
+ /* Do final sanity check on TEXASR to make sure FS is set. Do this
+ * here before we load up the userspace r1 so any bugs we hit will get
+ * a call chain */
+ mfspr r5, SPRN_TEXASR
+ srdi r5, r5, 16
+ li r6, (TEXASR_FS)@h
+ and r6, r6, r5
+1: tdeqi r6, 0
+ EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
+ /* Do final sanity check on MSR to make sure we are not transactional
+ * or suspended
+ */
+ mfmsr r6
+ li r5, (MSR_TS_MASK)@higher
+ srdi r6, r6, 32
+ and r6, r6, r5
+1: tdnei r6, 0
+ EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
+ /* Restore CR */
+ ld r6, _CCR(r7)
+ mtcr r6
+
+ REST_GPR(1, r7) /* GPR1 */
REST_GPR(5, r7) /* GPR5-7 */
REST_GPR(6, r7)
ld r7, GPR7(r7)
--
1.8.3.2
^ permalink raw reply related
* [PATCH] powerpc: Remove dead code in sycall entry
From: Michael Neuling @ 2014-03-28 5:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Michael Neuling, Paul Mackerras
In:
commit 742415d6b66bf09e3e73280178ef7ec85c90b7ee
Author: Michael Neuling <mikey@neuling.org>
powerpc: Turn syscall handler into macros
We converted the syscall entry code onto macros, but in doing this we
introduced some cruft that's never run and should never have been added.
This removes that code.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/exceptions-64s.S | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 4c34c3c..46af63d 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -54,14 +54,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
xori r12,r12,MSR_LE ; \
mtspr SPRN_SRR1,r12 ; \
rfid ; /* return to userspace */ \
- b . ; \
-2: mfspr r12,SPRN_SRR1 ; \
- andi. r12,r12,MSR_PR ; \
- bne 0b ; \
- mtspr SPRN_SRR0,r3 ; \
- mtspr SPRN_SRR1,r4 ; \
- mtspr SPRN_SDR1,r5 ; \
- rfid ; \
b . ; /* prevent speculative execution */
#if defined(CONFIG_RELOCATABLE)
--
1.8.3.2
^ permalink raw reply related
* [PATCH] powerpc: Add lq/stq emulation
From: Anton Blanchard @ 2014-03-28 6:01 UTC (permalink / raw)
To: benh, paulus, tommusta; +Cc: linuxppc-dev
Recent CPUs support quad word load and store instructions. Add
support to the alignment handler for them.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: b/arch/powerpc/include/asm/emulated_ops.h
===================================================================
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -54,6 +54,7 @@ extern struct ppc_emulated {
#ifdef CONFIG_PPC64
struct ppc_emulated_entry mfdscr;
struct ppc_emulated_entry mtdscr;
+ struct ppc_emulated_entry lq_stq;
#endif
} ppc_emulated;
Index: b/arch/powerpc/kernel/align.c
===================================================================
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -73,7 +73,7 @@ static struct aligninfo aligninfo[128] =
{ 8, LD+F }, /* 00 0 1001: lfd */
{ 4, ST+F+S }, /* 00 0 1010: stfs */
{ 8, ST+F }, /* 00 0 1011: stfd */
- INVALID, /* 00 0 1100 */
+ { 16, LD }, /* 00 0 1100: lq */
{ 8, LD }, /* 00 0 1101: ld/ldu/lwa */
INVALID, /* 00 0 1110 */
{ 8, ST }, /* 00 0 1111: std/stdu */
@@ -140,7 +140,7 @@ static struct aligninfo aligninfo[128] =
{ 2, LD+SW }, /* 10 0 1100: lhbrx */
{ 4, LD+SE }, /* 10 0 1101 lwa */
{ 2, ST+SW }, /* 10 0 1110: sthbrx */
- INVALID, /* 10 0 1111 */
+ { 16, ST }, /* 10 0 1111: stq */
INVALID, /* 10 1 0000 */
INVALID, /* 10 1 0001 */
INVALID, /* 10 1 0010 */
@@ -385,8 +385,6 @@ static int emulate_fp_pair(unsigned char
char *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1);
int i, ret, sw = 0;
- if (!(flags & F))
- return 0;
if (reg & 1)
return 0; /* invalid form: FRS/FRT must be even */
if (flags & SW)
@@ -406,6 +404,32 @@ static int emulate_fp_pair(unsigned char
return 1; /* exception handled and fixed up */
}
+static int emulate_lq_stq(struct pt_regs *regs, unsigned char __user *addr,
+ unsigned int reg, unsigned int flags)
+{
+ char *ptr0 = (char *)®s->gpr[reg];
+ char *ptr1 = (char *)®s->gpr[reg+1];
+ int i, ret, sw = 0;
+
+ if (reg & 1)
+ return 0; /* invalid form: GPR must be even */
+ if (flags & SW)
+ sw = 7;
+ ret = 0;
+ for (i = 0; i < 8; ++i) {
+ if (!(flags & ST)) {
+ ret |= __get_user(ptr0[i^sw], addr + i);
+ ret |= __get_user(ptr1[i^sw], addr + i + 8);
+ } else {
+ ret |= __put_user(ptr0[i^sw], addr + i);
+ ret |= __put_user(ptr1[i^sw], addr + i + 8);
+ }
+ }
+ if (ret)
+ return -EFAULT;
+ return 1; /* exception handled and fixed up */
+}
+
#ifdef CONFIG_SPE
static struct aligninfo spe_aligninfo[32] = {
@@ -914,10 +938,20 @@ int fix_alignment(struct pt_regs *regs)
flush_fp_to_thread(current);
}
- /* Special case for 16-byte FP loads and stores */
- if (nb == 16) {
- PPC_WARN_ALIGNMENT(fp_pair, regs);
- return emulate_fp_pair(addr, reg, flags);
+ if ((nb == 16)) {
+ if (flags & F) {
+ /* Special case for 16-byte FP loads and stores */
+ PPC_WARN_ALIGNMENT(fp_pair, regs);
+ return emulate_fp_pair(addr, reg, flags);
+ } else {
+#ifdef CONFIG_PPC64
+ /* Special case for 16-byte loads and stores */
+ PPC_WARN_ALIGNMENT(lq_stq, regs);
+ return emulate_lq_stq(regs, addr, reg, flags);
+#else
+ return 0;
+#endif
+ }
}
PPC_WARN_ALIGNMENT(unaligned, regs);
Index: b/arch/powerpc/kernel/traps.c
===================================================================
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1868,6 +1868,7 @@ struct ppc_emulated ppc_emulated = {
#ifdef CONFIG_PPC64
WARN_EMULATED_SETUP(mfdscr),
WARN_EMULATED_SETUP(mtdscr),
+ WARN_EMULATED_SETUP(lq_stq),
#endif
};
^ permalink raw reply
* Re: [PATCH 6/7] DMA: Freescale: use spin_lock_bh instead of spin_lock_irqsave
From: Hongbo Zhang @ 2014-03-28 6:33 UTC (permalink / raw)
To: Vinod Koul
Cc: vinod.koul, linux-kernel, scottwood, dmaengine, dan.j.williams,
linuxppc-dev
In-Reply-To: <1395817294.6569.2.camel@vkoul-udesk3>
On 03/26/2014 03:01 PM, Vinod Koul wrote:
> On Thu, 2014-01-16 at 13:47 +0800, hongbo.zhang@freescale.com wrote:
>> From: Hongbo Zhang <hongbo.zhang@freescale.com>
>>
>> The usage of spin_lock_irqsave() is a stronger locking mechanism than is
>> required throughout the driver. The minimum locking required should be used
>> instead. Interrupts will be turned off and context will be saved, it is
>> unnecessary to use irqsave.
>>
>> This patch changes all instances of spin_lock_irqsave() to spin_lock_bh(). All
>> manipulation of protected fields is done using tasklet context or weaker, which
>> makes spin_lock_bh() the correct choice.
>>
>> Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
>> Signed-off-by: Qiang Liu <qiang.liu@freescale.com>
>> ---
>> drivers/dma/fsldma.c | 25 ++++++++++---------------
>> 1 file changed, 10 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
>> index bbace54..437794e 100644
>> --- a/drivers/dma/fsldma.c
>> +++ b/drivers/dma/fsldma.c
>> @@ -396,10 +396,9 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
>> struct fsldma_chan *chan = to_fsl_chan(tx->chan);
>> struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
>> struct fsl_desc_sw *child;
>> - unsigned long flags;
>> dma_cookie_t cookie = -EINVAL;
>>
>> - spin_lock_irqsave(&chan->desc_lock, flags);
>> + spin_lock_bh(&chan->desc_lock);
>>
>> /*
>> * assign cookies to all of the software descriptors
>> @@ -412,7 +411,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
>> /* put this transaction onto the tail of the pending queue */
>> append_ld_queue(chan, desc);
>>
>> - spin_unlock_irqrestore(&chan->desc_lock, flags);
>> + spin_unlock_bh(&chan->desc_lock);
>>
>> return cookie;
>> }
>> @@ -731,15 +730,14 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
>> static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
>> {
>> struct fsldma_chan *chan = to_fsl_chan(dchan);
>> - unsigned long flags;
>>
>> chan_dbg(chan, "free all channel resources\n");
>> - spin_lock_irqsave(&chan->desc_lock, flags);
>> + spin_lock_bh(&chan->desc_lock);
>> fsldma_cleanup_descriptors(chan);
>> fsldma_free_desc_list(chan, &chan->ld_pending);
>> fsldma_free_desc_list(chan, &chan->ld_running);
>> fsldma_free_desc_list(chan, &chan->ld_completed);
>> - spin_unlock_irqrestore(&chan->desc_lock, flags);
>> + spin_unlock_bh(&chan->desc_lock);
>>
>> dma_pool_destroy(chan->desc_pool);
>> chan->desc_pool = NULL;
>> @@ -958,7 +956,6 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
>> {
>> struct dma_slave_config *config;
>> struct fsldma_chan *chan;
>> - unsigned long flags;
>> int size;
>>
>> if (!dchan)
>> @@ -968,7 +965,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
>>
>> switch (cmd) {
>> case DMA_TERMINATE_ALL:
>> - spin_lock_irqsave(&chan->desc_lock, flags);
>> + spin_lock_bh(&chan->desc_lock);
>>
>> /* Halt the DMA engine */
>> dma_halt(chan);
>> @@ -979,7 +976,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
>> fsldma_free_desc_list(chan, &chan->ld_completed);
>> chan->idle = true;
>>
>> - spin_unlock_irqrestore(&chan->desc_lock, flags);
>> + spin_unlock_bh(&chan->desc_lock);
>> return 0;
>>
>> case DMA_SLAVE_CONFIG:
>> @@ -1021,11 +1018,10 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
>> static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
>> {
>> struct fsldma_chan *chan = to_fsl_chan(dchan);
>> - unsigned long flags;
>>
>> - spin_lock_irqsave(&chan->desc_lock, flags);
>> + spin_lock_bh(&chan->desc_lock);
>> fsl_chan_xfer_ld_queue(chan);
>> - spin_unlock_irqrestore(&chan->desc_lock, flags);
>> + spin_unlock_bh(&chan->desc_lock);
>> }
>>
>> /**
>> @@ -1124,11 +1120,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
>> static void dma_do_tasklet(unsigned long data)
>> {
>> struct fsldma_chan *chan = (struct fsldma_chan *)data;
>> - unsigned long flags;
>>
>> chan_dbg(chan, "tasklet entry\n");
>>
>> - spin_lock_irqsave(&chan->desc_lock, flags);
>> + spin_lock_bh(&chan->desc_lock);
> okay here is the problem :(
>
> You moved to _bh variant. So if you grab the lock in rest of the code
> and irq gets triggered then here we will be spinning to grab the lock.
> So effectively you made right locking solution into deadlock situation!
If the rest code grabs lock by spin_lock_bh(), and if irq raised, the
tasklet could not be executed because it has been disabled by the _bh
variant function.
Right?
>>
>> /* the hardware is now idle and ready for more */
>> chan->idle = true;
>> @@ -1136,7 +1131,7 @@ static void dma_do_tasklet(unsigned long data)
>> /* Run all cleanup for descriptors which have been completed */
>> fsldma_cleanup_descriptors(chan);
>>
>> - spin_unlock_irqrestore(&chan->desc_lock, flags);
>> + spin_unlock_bh(&chan->desc_lock);
>>
>> chan_dbg(chan, "tasklet exit\n");
>> }
>
^ permalink raw reply
* [PATCH] powerpc/le: enable RTAS events support
From: Greg Kurz @ 2014-03-28 7:33 UTC (permalink / raw)
To: benh; +Cc: linux-kernel, paulus, anton, nfont, linuxppc-dev
The current kernel code assumes big endian and parses RTAS events all
wrong. The most visible effect is that we cannot honor EPOW events,
meaning, for example, we cannot shut down a guest properly from the
hypervisor.
This patch fixes that.
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/rtas.h | 46 ++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/rtas.c | 11 ++++----
arch/powerpc/kernel/rtasd.c | 8 ++++--
arch/powerpc/platforms/pseries/ras.c | 3 +-
4 files changed, 59 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 9bd52c6..8bb99d0 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -150,15 +150,37 @@ struct rtas_suspend_me_data {
#define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
struct rtas_error_log {
+#ifdef __BIG_ENDIAN__
+ /* Byte 0 */
unsigned long version:8; /* Architectural version */
+ /* Byte 1 */
unsigned long severity:3; /* Severity level of error */
unsigned long disposition:2; /* Degree of recovery */
unsigned long extended:1; /* extended log present? */
unsigned long /* reserved */ :2; /* Reserved for future use */
+ /* Byte 2 */
unsigned long initiator:4; /* Initiator of event */
unsigned long target:4; /* Target of failed operation */
+ /* Byte 3 */
unsigned long type:8; /* General event or error*/
+ /* Byte 4 */
unsigned long extended_log_length:32; /* length in bytes */
+#else
+ /* Byte 0 */
+ unsigned long version:8;
+ /* Byte 1 */
+ unsigned long :2;
+ unsigned long extended:1;
+ unsigned long disposition:2;
+ unsigned long severity:3;
+ unsigned long target:4;
+ /* Byte 2 */
+ unsigned long initiator:4;
+ /* Byte 3 */
+ unsigned long type:8;
+ /* Byte 4 */
+ unsigned long extended_log_length:32;
+#endif
unsigned char buffer[1]; /* Start of extended log */
/* Variable length. */
};
@@ -171,6 +193,7 @@ struct rtas_error_log {
* from "buffer" field of struct rtas_error_log defined above.
*/
struct rtas_ext_event_log_v6 {
+#ifdef __BIG_ENDIAN__
/* Byte 0 */
uint32_t log_valid:1; /* 1:Log valid */
uint32_t unrecoverable_error:1; /* 1:Unrecoverable error */
@@ -200,6 +223,29 @@ struct rtas_ext_event_log_v6 {
uint32_t company_id; /* Company ID of the company */
/* that defines the format for */
/* the vendor specific log type */
+#else
+ /* Byte 0 */
+ uint32_t :1;
+ uint32_t big_endian:1;
+ uint32_t new_log:1;
+ uint32_t predictive_error:1;
+ uint32_t degraded_operation:1;
+ uint32_t recoverable_error:1;
+ uint32_t unrecoverable_error:1;
+ uint32_t log_valid:1;
+ /* Byte 1 */
+ uint32_t :8;
+ /* Byte 2 */
+ uint32_t log_format:4;
+ uint32_t :3;
+ uint32_t powerpc_format:1;
+ /* Byte 3 */
+ uint32_t :8;
+ /* Byte 4-11 */
+ uint8_t reserved[8];
+ /* Byte 12-15 */
+ uint32_t company_id;
+#endif
/* Byte 16-end of log */
uint8_t vendor_log[1]; /* Start of vendor specific log */
/* Variable length. */
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f386296..e18ab12 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -993,21 +993,22 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
(struct rtas_ext_event_log_v6 *)log->buffer;
struct pseries_errorlog *sect;
unsigned char *p, *log_end;
+ uint32_t extended_log_length = be32_to_cpu(log->extended_log_length);
/* Check that we understand the format */
- if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
+ if (extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
- ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
+ be32_to_cpu(ext_log->company_id) != RTAS_V6EXT_COMPANY_ID_IBM)
return NULL;
- log_end = log->buffer + log->extended_log_length;
+ log_end = log->buffer + extended_log_length;
p = ext_log->vendor_log;
while (p < log_end) {
sect = (struct pseries_errorlog *)p;
- if (sect->id == section_id)
+ if (be16_to_cpu(sect->id) == section_id)
return sect;
- p += sect->length;
+ p += be16_to_cpu(sect->length);
}
return NULL;
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 1130c53..1987825 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -159,14 +159,16 @@ static int log_rtas_len(char * buf)
{
int len;
struct rtas_error_log *err;
+ uint32_t extended_log_length;
/* rtas fixed header */
len = 8;
err = (struct rtas_error_log *)buf;
- if (err->extended && err->extended_log_length) {
+ extended_log_length = be32_to_cpu(err->extended_log_length);
+ if (err->extended && extended_log_length) {
/* extended header */
- len += err->extended_log_length;
+ len += extended_log_length;
}
if (rtas_error_log_max == 0)
@@ -298,7 +300,7 @@ static void handle_rtas_event(const struct rtas_error_log *log)
* the scope for calling rtas update-nodes.
*/
if (prrn_is_enabled())
- prrn_schedule_update(log->extended_log_length);
+ prrn_schedule_update(be32_to_cpu(log->extended_log_length));
}
return;
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 721c058..39e7557 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -306,7 +306,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
} else {
int len;
- len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
+ len = max_t(int, 8+be32_to_cpu(h->extended_log_length),
+ RTAS_ERROR_LOG_MAX);
memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
memcpy(global_mce_data_buf, h, len);
errhdr = (struct rtas_error_log *)global_mce_data_buf;
^ permalink raw reply related
* RE: [PATCH] phy/at8031: enable at8031 to work on interrupt mode
From: qiang.zhao @ 2014-03-28 7:36 UTC (permalink / raw)
To: Sergei Shtylyov, linuxppc-dev@lists.ozlabs.org,
netdev@vger.kernel.org, Scott Wood
Cc: mugunthanvnm@ti.com, linux-kernel@vger.kernel.org,
helmut.schaa@googlemail.com, zonque@gmail.com,
davem@davemloft.net, Xiaobo Xie
In-Reply-To: <53341101.9000404@cogentembedded.com>
On Thursday, March 27, 2014 7:53 PM, Sergei Shtylyov wrote:
> -----Original Message-----
> From: Sergei Shtylyov [mailto:sergei.shtylyov@cogentembedded.com]
> Sent: Thursday, March 27, 2014 7:53 PM
> To: Zhao Qiang-B45475; linuxppc-dev@lists.ozlabs.org;
> netdev@vger.kernel.org; Wood Scott-B07421
> Cc: linux-kernel@vger.kernel.org; davem@davemloft.net;
> mugunthanvnm@ti.com; zonque@gmail.com; helmut.schaa@googlemail.com; Xie
> Xiaobo-R63061
> Subject: Re: [PATCH] phy/at8031: enable at8031 to work on interrupt mode
>=20
> Hello.
>=20
> On 27-03-2014 10:18, Zhao Qiang wrote:
>=20
> > The at8031 can work on polling mode and interrupt mode.
> > Add ack_interrupt and config intr funcs to enable interrupt mode for
> > it.
>=20
> > Signed-off-by: Zhao Qiang <B45475@freescale.com>
> > ---
> > drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++++++++
> > 1 file changed, 30 insertions(+)
>=20
> > diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index
> > bc71947..d034ef5 100644
> > --- a/drivers/net/phy/at803x.c
> > +++ b/drivers/net/phy/at803x.c
> [...]
> > @@ -191,6 +194,31 @@ static int at803x_config_init(struct phy_device
> *phydev)
> > return 0;
> > }
> >
> > +static int at803x_ack_interrupt(struct phy_device *phydev) {
> > + int err;
> > +
> > + err =3D phy_read(phydev, AT803X_INSR);
>=20
> Could make this an initializer...
Thank you very much. However I have no idea about "make this an initializer=
".
>=20
> > +
> > + return (err < 0) ? err : 0;
> > +}
> > +
> > +static int at803x_config_intr(struct phy_device *phydev) {
> > + int err;
> > + int value;
> > +
> > + value =3D phy_read(phydev, AT803X_INER);
> > +
> > + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED)
> > + err =3D phy_write(phydev, AT803X_INER,
> > + (value | AT803X_INER_INIT));
>=20
> Inner parens not needed.
>=20
> > + else
> > + err =3D phy_write(phydev, AT803X_INER, value);
>=20
> Why are you not clearing the bits here? Why write back what has been
> read at all?
>=20
> WBR, Sergei
>=20
>=20
^ permalink raw reply
* [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Dongsheng Wang @ 2014-03-28 7:38 UTC (permalink / raw)
To: fweisbec
Cc: James Hogan, Andrew Morton, David S. Miller, Peter Zijlstra,
Helge Deller, H. Peter Anvin, Heiko Carstens, linux-kernel,
Paul Mackerras, Wang Dongsheng, James E.J. Bottomley,
Linus Torvalds, jason.jin, scottwood, Thomas Gleixner,
linuxppc-dev, Ingo Molnar, Martin Schwidefsky
From: Wang Dongsheng <dongsheng.wang@freescale.com>
If softirq use hardirq stack, we will get kernel painc when a hard irq coming again
during __do_softirq enable local irq to deal with softirq action. So we need to switch
satck into softirq stack when invoke soft irq.
Task--->
| Task stack
|
Interrput->EXCEPTION->do_IRQ->
^ | Hard irq stack
| |
| irq_exit->__do_softirq->local_irq_enable-- -->local_irq_disable
| | Hard irq stack
| |
| Interrupt coming again
| There will get a Interrupt nesting |
------------------------------------------------------------------------
Trace 1: Trap 900
Kernel stack overflow in process e8152f40, r1=e8e05ec0
CPU: 0 PID: 2399 Comm: image_compress/ Not tainted 3.13.0-rc3-03475-g2e3f85b #432
task: e8152f40 ti: c080a000 task.ti: ef176000
NIP: c05bec04 LR: c0305590 CTR: 00000010
REGS: e8e05e10 TRAP: 0901 Not tainted (3.13.0-rc3-03475-g2e3f85b)
MSR: 00029000 <CE,EE,ME> CR: 22f22722 XER: 20000000
GPR00: c0305590 e8e05ec0 e8152f40 c07e1e2c 00029000 000000ec fffffffc 00000010
GPR08: 0000007f 00000000 00000000 b02539f3 a00ae278
NIP [c05bec04] _raw_spin_unlock_irqrestore+0x10/0x14
LR [c0305590] add_timer_randomness+0x60/0xfc
Call Trace:
[e8e05ec0] [c0305590] add_timer_randomness+0x60/0xfc (unreliable)
[e8e05ee0] [c026c9a8] blk_update_bidi_request+0x64/0x94
[e8e05f00] [c026cd00] blk_end_bidi_request+0x20/0x7c
[e8e05f20] [c032f21c] scsi_io_completion+0xe0/0x5e8
[e8e05f70] [c0272b84] blk_done_softirq+0x98/0xb8
[e8e05f90] [c004893c] __do_softirq+0xf8/0x1f8
[e8e05fe0] [c0048dbc] irq_exit+0xa4/0xc8
[e8e05ff0] [c000d5f4] call_do_irq+0x24/0x3c
[ef177d50] [c00046ec] do_IRQ+0x8c/0xf8
[ef177d70] [c000f6dc] ret_from_except+0x0/0x18
--- Exception: 501 at lzo1x_1_do_compress+0x248/0x40c
LR = lzo1x_1_compress+0x98/0x268
[ef177e30] [c07c7440] runqueues+0x0/0x540 (unreliable)
[ef177e60] [00000000] (null)
[ef177ea0] [c0085a9c] lzo_compress_threadfn+0x6c/0x138
[ef177ef0] [c0062a00] kthread+0xc4/0xd8
[ef177f40] [c000f158] ret_from_kernel_thread+0x5c/0x64
Instruction dump:
40a2fff0 4c00012c 2f890000 419e000c 38600000 4e800020 38600001 4e800020
7c0004ac 39200000 91230000 7c800106 <4e800020> 7d201828 35290001 40810010
Kernel panic - not syncing: kernel stack overflow
CPU: 0 PID: 2399 Comm: image_compress/ Not tainted 3.13.0-rc3-03475-g2e3f85b #432
Call Trace:
Rebooting in 180 seconds..
Trace 2: Trap 500
VFS: Mounted root (ext2 filesystem) on device 1:0.
devtmpfs: mounted
Freeing unused kernel memory: 268K (c079a000 - c07dd000)
INIT: version 2.88 booting
Starting udev
udevd[1423]: starting version 182
random: nonblocking pool is initialized
Kernel stack overflow in process e829ca80, r1=e8badf90
CPU: 0 PID: 1553 Comm: mount.sh Not tainted 3.13.0-rc1-148228-gea7ca7c #21
task: e829ca80 ti: c081c000 task.ti: e9d28000
NIP: c00434bc LR: c0043444 CTR: c0018cec
REGS: e8badee0 TRAP: 0501 Not tainted (3.13.0-rc1-148228-gea7ca7c)
MSR: 00029000 <CE,EE,ME> CR: 48222422 XER: 20000000
GPR00: c00439a0 e8badf90 e829ca80 00000001 e80cc780 00000001 b92f44af 00000000
GPR08: 00000001 010ba000 010ba000 ddd3e6d1 48222422
NIP [c00434bc] __do_softirq+0x94/0x1f8
LR [c0043444] __do_softirq+0x1c/0x1f8
Call Trace:
[e8badf90] [100f0000] 0x100f0000 (unreliable)
[e8badfe0] [c00439a0] irq_exit+0xa4/0xc8
[e8badff0] [c000ccd8] call_do_irq+0x24/0x3c
[e9d29f20] [c000479c] do_IRQ+0x8c/0xf8
[e9d29f40] [c000eb54] ret_from_except+0x0/0x18
--- Exception: 501 at 0x1003d540
LR = 0x10041974
Instruction dump:
3e80c082 3f40c07e 3b60000a 3a941040 3aa00000 3b5a9388 7f16c378 812f0008
5529103a 7d3c482e 7eb8492e 7c008146 <3ba00000> 7e9ea378 48000014 57fff87f
Kernel panic - not syncing: kernel stack overflow
CPU: 0 PID: 1553 Comm: mount.sh Not tainted 3.13.0-rc1-148228-gea7ca7c #21
Call Trace:
Rebooting in 180 seconds..
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Paul Mackerras <paulus@au1.ibm.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: James E.J. Bottomley <jejb@parisc-linux.org>
Cc: Helge Deller <deller@gmx.de>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 957bf34..ffde3fb 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -139,7 +139,6 @@ config PPC
select OLD_SIGSUSPEND
select OLD_SIGACTION if PPC32
select HAVE_DEBUG_STACKOVERFLOW
- select HAVE_IRQ_EXIT_ON_IRQ_STACK
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
config GENERIC_CSUM
--
1.8.5
^ permalink raw reply related
* [PATCH v2] phy/at8031: enable at8031 to work on interrupt mode
From: Zhao Qiang @ 2014-03-28 7:39 UTC (permalink / raw)
To: linuxppc-dev, netdev, B07421
Cc: mugunthanvnm, Zhao Qiang, linux-kernel, helmut.schaa, zonque,
R63061, davem
The at8031 can work on polling mode and interrupt mode.
Add ack_interrupt and config intr funcs to enable
interrupt mode for it.
Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
changes for v2:
- when interrupt is not enabled, write 0 to interrupt enbale register
- delete a inner parens not needed
drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index bc71947..643464d 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -27,6 +27,9 @@
#define AT803X_MMD_ACCESS_CONTROL 0x0D
#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
#define AT803X_FUNC_DATA 0x4003
+#define AT803X_INER 0x0012
+#define AT803X_INER_INIT 0xec00
+#define AT803X_INSR 0x0013
#define AT803X_DEBUG_ADDR 0x1D
#define AT803X_DEBUG_DATA 0x1E
#define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
@@ -191,6 +194,31 @@ static int at803x_config_init(struct phy_device *phydev)
return 0;
}
+static int at803x_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, AT803X_INSR);
+
+ return (err < 0) ? err : 0;
+}
+
+static int at803x_config_intr(struct phy_device *phydev)
+{
+ int err;
+ int value;
+
+ value = phy_read(phydev, AT803X_INER);
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, AT803X_INER,
+ value | AT803X_INER_INIT);
+ else
+ err = phy_write(phydev, AT803X_INER, 0);
+
+ return err;
+}
+
static struct phy_driver at803x_driver[] = {
{
/* ATHEROS 8035 */
@@ -240,6 +268,8 @@ static struct phy_driver at803x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = &at803x_ack_interrupt,
+ .config_intr = &at803x_config_intr,
.driver = {
.owner = THIS_MODULE,
},
--
1.8.5
^ permalink raw reply related
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Kevin Hao @ 2014-03-28 8:18 UTC (permalink / raw)
To: Dongsheng Wang
Cc: Ingo Molnar, James Hogan, Peter Zijlstra, fweisbec, Helge Deller,
linuxppc-dev, Heiko Carstens, linux-kernel, Paul Mackerras,
James E.J. Bottomley, Martin Schwidefsky, Thomas Gleixner,
jason.jin, H. Peter Anvin, scottwood, Andrew Morton,
Linus Torvalds, David S. Miller
In-Reply-To: <1395992312-23035-1-git-send-email-dongsheng.wang@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 3397 bytes --]
On Fri, Mar 28, 2014 at 03:38:32PM +0800, Dongsheng Wang wrote:
> From: Wang Dongsheng <dongsheng.wang@freescale.com>
>
> If softirq use hardirq stack, we will get kernel painc when a hard irq coming again
> during __do_softirq enable local irq to deal with softirq action. So we need to switch
> satck into softirq stack when invoke soft irq.
>
> Task--->
> | Task stack
> |
> Interrput->EXCEPTION->do_IRQ->
> ^ | Hard irq stack
> | |
> | irq_exit->__do_softirq->local_irq_enable-- -->local_irq_disable
> | | Hard irq stack
> | |
> | Interrupt coming again
> | There will get a Interrupt nesting |
> ------------------------------------------------------------------------
>
> Trace 1: Trap 900
>
> Kernel stack overflow in process e8152f40, r1=e8e05ec0
> CPU: 0 PID: 2399 Comm: image_compress/ Not tainted 3.13.0-rc3-03475-g2e3f85b #432
> task: e8152f40 ti: c080a000 task.ti: ef176000
> NIP: c05bec04 LR: c0305590 CTR: 00000010
> REGS: e8e05e10 TRAP: 0901 Not tainted (3.13.0-rc3-03475-g2e3f85b)
Could you double check if you got the following patch applied?
commit 1a18a66446f3f289b05b634f18012424d82aa63a
Author: Kevin Hao <haokexin@gmail.com>
Date: Fri Jan 17 12:25:28 2014 +0800
powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack
Guenter Roeck has got the following call trace on a p2020 board:
Kernel stack overflow in process eb3e5a00, r1=eb79df90
CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4
task: eb3e5a00 ti: c0616000 task.ti: ef440000
NIP: c003a420 LR: c003a410 CTR: c0017518
REGS: eb79dee0 TRAP: 0901 Not tainted (3.13.0-rc8-juniper-00146-g19eca00)
MSR: 00029000 <CE,EE,ME> CR: 24008444 XER: 00000000
GPR00: c003a410 eb79df90 eb3e5a00 00000000 eb05d900 00000001 65d87646 00000000
GPR08: 00000000 020b8000 00000000 00000000 44008442
NIP [c003a420] __do_softirq+0x94/0x1ec
LR [c003a410] __do_softirq+0x84/0x1ec
Call Trace:
[eb79df90] [c003a410] __do_softirq+0x84/0x1ec (unreliable)
[eb79dfe0] [c003a970] irq_exit+0xbc/0xc8
[eb79dff0] [c000cc1c] call_do_irq+0x24/0x3c
[ef441f20] [c00046a8] do_IRQ+0x8c/0xf8
[ef441f40] [c000e7f4] ret_from_except+0x0/0x18
--- Exception: 501 at 0xfcda524
LR = 0x10024900
Instruction dump:
7c781b78 3b40000a 3a73b040 543c0024 3a800000 3b3913a0 7ef5bb78 48201bf9
5463103a 7d3b182e 7e89b92e 7c008146 <3ba00000> 7e7e9b78 48000014 57fff87f
Kernel panic - not syncing: kernel stack overflow
CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4
Call Trace:
The reason is that we have used the wrong register to calculate the
ksp_limit in commit cbc9565ee826 (powerpc: Remove ksp_limit on ppc64).
Just fix it.
As suggested by Benjamin Herrenschmidt, also add the C prototype of the
function in the comment in order to avoid such kind of errors in the
future.
Cc: stable@vger.kernel.org # 3.12
Reported-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Kevin Hao <haokexin@gmail.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Laurent Dufour @ 2014-03-28 8:29 UTC (permalink / raw)
To: Greg Kurz, benh; +Cc: nfont, linuxppc-dev, paulus, linux-kernel, anton
In-Reply-To: <20140328073344.26823.32931.stgit@bahia.local>
On 28/03/2014 08:33, Greg Kurz wrote:
> The current kernel code assumes big endian and parses RTAS events all
> wrong. The most visible effect is that we cannot honor EPOW events,
> meaning, for example, we cannot shut down a guest properly from the
> hypervisor.
>
> This patch fixes that.
>
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/rtas.h | 46 ++++++++++++++++++++++++++++++++++
> arch/powerpc/kernel/rtas.c | 11 ++++----
> arch/powerpc/kernel/rtasd.c | 8 ++++--
> arch/powerpc/platforms/pseries/ras.c | 3 +-
> 4 files changed, 59 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
> index 9bd52c6..8bb99d0 100644
> --- a/arch/powerpc/include/asm/rtas.h
> +++ b/arch/powerpc/include/asm/rtas.h
> @@ -150,15 +150,37 @@ struct rtas_suspend_me_data {
> #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
>
> struct rtas_error_log {
> +#ifdef __BIG_ENDIAN__
> + /* Byte 0 */
> unsigned long version:8; /* Architectural version */
> + /* Byte 1 */
> unsigned long severity:3; /* Severity level of error */
> unsigned long disposition:2; /* Degree of recovery */
> unsigned long extended:1; /* extended log present? */
> unsigned long /* reserved */ :2; /* Reserved for future use */
> + /* Byte 2 */
> unsigned long initiator:4; /* Initiator of event */
> unsigned long target:4; /* Target of failed operation */
> + /* Byte 3 */
> unsigned long type:8; /* General event or error*/
> + /* Byte 4 */
> unsigned long extended_log_length:32; /* length in bytes */
> +#else
> + /* Byte 0 */
> + unsigned long version:8;
> + /* Byte 1 */
> + unsigned long :2;
> + unsigned long extended:1;
> + unsigned long disposition:2;
> + unsigned long severity:3;
> + unsigned long target:4;
Hi Greg,
A cosmetic detail: 'target' is in the 'Byte 2'.
Laurent.
> + /* Byte 2 */
> + unsigned long initiator:4;
> + /* Byte 3 */
> + unsigned long type:8;
> + /* Byte 4 */
> + unsigned long extended_log_length:32;
> +#endif
> unsigned char buffer[1]; /* Start of extended log */
> /* Variable length. */
> };
> @@ -171,6 +193,7 @@ struct rtas_error_log {
> * from "buffer" field of struct rtas_error_log defined above.
> */
> struct rtas_ext_event_log_v6 {
> +#ifdef __BIG_ENDIAN__
> /* Byte 0 */
> uint32_t log_valid:1; /* 1:Log valid */
> uint32_t unrecoverable_error:1; /* 1:Unrecoverable error */
> @@ -200,6 +223,29 @@ struct rtas_ext_event_log_v6 {
> uint32_t company_id; /* Company ID of the company */
> /* that defines the format for */
> /* the vendor specific log type */
> +#else
> + /* Byte 0 */
> + uint32_t :1;
> + uint32_t big_endian:1;
> + uint32_t new_log:1;
> + uint32_t predictive_error:1;
> + uint32_t degraded_operation:1;
> + uint32_t recoverable_error:1;
> + uint32_t unrecoverable_error:1;
> + uint32_t log_valid:1;
> + /* Byte 1 */
> + uint32_t :8;
> + /* Byte 2 */
> + uint32_t log_format:4;
> + uint32_t :3;
> + uint32_t powerpc_format:1;
> + /* Byte 3 */
> + uint32_t :8;
> + /* Byte 4-11 */
> + uint8_t reserved[8];
> + /* Byte 12-15 */
> + uint32_t company_id;
> +#endif
> /* Byte 16-end of log */
> uint8_t vendor_log[1]; /* Start of vendor specific log */
> /* Variable length. */
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index f386296..e18ab12 100644
> --- a/arch/powerpc/kernel/rtas.c
> +++ b/arch/powerpc/kernel/rtas.c
> @@ -993,21 +993,22 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
> (struct rtas_ext_event_log_v6 *)log->buffer;
> struct pseries_errorlog *sect;
> unsigned char *p, *log_end;
> + uint32_t extended_log_length = be32_to_cpu(log->extended_log_length);
>
> /* Check that we understand the format */
> - if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> + if (extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
> - ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
> + be32_to_cpu(ext_log->company_id) != RTAS_V6EXT_COMPANY_ID_IBM)
> return NULL;
>
> - log_end = log->buffer + log->extended_log_length;
> + log_end = log->buffer + extended_log_length;
> p = ext_log->vendor_log;
>
> while (p < log_end) {
> sect = (struct pseries_errorlog *)p;
> - if (sect->id == section_id)
> + if (be16_to_cpu(sect->id) == section_id)
> return sect;
> - p += sect->length;
> + p += be16_to_cpu(sect->length);
> }
>
> return NULL;
> diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
> index 1130c53..1987825 100644
> --- a/arch/powerpc/kernel/rtasd.c
> +++ b/arch/powerpc/kernel/rtasd.c
> @@ -159,14 +159,16 @@ static int log_rtas_len(char * buf)
> {
> int len;
> struct rtas_error_log *err;
> + uint32_t extended_log_length;
>
> /* rtas fixed header */
> len = 8;
> err = (struct rtas_error_log *)buf;
> - if (err->extended && err->extended_log_length) {
> + extended_log_length = be32_to_cpu(err->extended_log_length);
> + if (err->extended && extended_log_length) {
>
> /* extended header */
> - len += err->extended_log_length;
> + len += extended_log_length;
> }
>
> if (rtas_error_log_max == 0)
> @@ -298,7 +300,7 @@ static void handle_rtas_event(const struct rtas_error_log *log)
> * the scope for calling rtas update-nodes.
> */
> if (prrn_is_enabled())
> - prrn_schedule_update(log->extended_log_length);
> + prrn_schedule_update(be32_to_cpu(log->extended_log_length));
> }
>
> return;
> diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
> index 721c058..39e7557 100644
> --- a/arch/powerpc/platforms/pseries/ras.c
> +++ b/arch/powerpc/platforms/pseries/ras.c
> @@ -306,7 +306,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
> } else {
> int len;
>
> - len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
> + len = max_t(int, 8+be32_to_cpu(h->extended_log_length),
> + RTAS_ERROR_LOG_MAX);
> memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
> memcpy(global_mce_data_buf, h, len);
> errhdr = (struct rtas_error_log *)global_mce_data_buf;
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Greg Kurz @ 2014-03-28 8:36 UTC (permalink / raw)
To: Laurent Dufour; +Cc: linux-kernel, paulus, anton, nfont, linuxppc-dev
In-Reply-To: <533532E2.4020505@fr.ibm.com>
On Fri, 28 Mar 2014 09:29:22 +0100
Laurent Dufour <laurent.dufour@fr.ibm.com> wrote:
> On 28/03/2014 08:33, Greg Kurz wrote:
> > The current kernel code assumes big endian and parses RTAS events all
> > wrong. The most visible effect is that we cannot honor EPOW events,
> > meaning, for example, we cannot shut down a guest properly from the
> > hypervisor.
> >
> > This patch fixes that.
> >
> > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
>
> Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
>
> > ---
> > arch/powerpc/include/asm/rtas.h | 46 ++++++++++++++++++++++++++++++++++
> > arch/powerpc/kernel/rtas.c | 11 ++++----
> > arch/powerpc/kernel/rtasd.c | 8 ++++--
> > arch/powerpc/platforms/pseries/ras.c | 3 +-
> > 4 files changed, 59 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
> > index 9bd52c6..8bb99d0 100644
> > --- a/arch/powerpc/include/asm/rtas.h
> > +++ b/arch/powerpc/include/asm/rtas.h
> > @@ -150,15 +150,37 @@ struct rtas_suspend_me_data {
> > #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
> >
> > struct rtas_error_log {
> > +#ifdef __BIG_ENDIAN__
> > + /* Byte 0 */
> > unsigned long version:8; /* Architectural version */
> > + /* Byte 1 */
> > unsigned long severity:3; /* Severity level of error */
> > unsigned long disposition:2; /* Degree of recovery */
> > unsigned long extended:1; /* extended log present? */
> > unsigned long /* reserved */ :2; /* Reserved for future use */
> > + /* Byte 2 */
> > unsigned long initiator:4; /* Initiator of event */
> > unsigned long target:4; /* Target of failed operation */
> > + /* Byte 3 */
> > unsigned long type:8; /* General event or error*/
> > + /* Byte 4 */
> > unsigned long extended_log_length:32; /* length in bytes */
> > +#else
> > + /* Byte 0 */
> > + unsigned long version:8;
> > + /* Byte 1 */
> > + unsigned long :2;
> > + unsigned long extended:1;
> > + unsigned long disposition:2;
> > + unsigned long severity:3;
> > + unsigned long target:4;
>
> Hi Greg,
>
> A cosmetic detail: 'target' is in the 'Byte 2'.
>
> Laurent.
>
Good catch ! Thanks.
> > + /* Byte 2 */
> > + unsigned long initiator:4;
> > + /* Byte 3 */
> > + unsigned long type:8;
> > + /* Byte 4 */
> > + unsigned long extended_log_length:32;
> > +#endif
> > unsigned char buffer[1]; /* Start of extended log */
> > /* Variable length. */
> > };
> > @@ -171,6 +193,7 @@ struct rtas_error_log {
> > * from "buffer" field of struct rtas_error_log defined above.
> > */
> > struct rtas_ext_event_log_v6 {
> > +#ifdef __BIG_ENDIAN__
> > /* Byte 0 */
> > uint32_t log_valid:1; /* 1:Log valid */
> > uint32_t unrecoverable_error:1; /* 1:Unrecoverable error */
> > @@ -200,6 +223,29 @@ struct rtas_ext_event_log_v6 {
> > uint32_t company_id; /* Company ID of the company */
> > /* that defines the format for */
> > /* the vendor specific log type */
> > +#else
> > + /* Byte 0 */
> > + uint32_t :1;
> > + uint32_t big_endian:1;
> > + uint32_t new_log:1;
> > + uint32_t predictive_error:1;
> > + uint32_t degraded_operation:1;
> > + uint32_t recoverable_error:1;
> > + uint32_t unrecoverable_error:1;
> > + uint32_t log_valid:1;
> > + /* Byte 1 */
> > + uint32_t :8;
> > + /* Byte 2 */
> > + uint32_t log_format:4;
> > + uint32_t :3;
> > + uint32_t powerpc_format:1;
> > + /* Byte 3 */
> > + uint32_t :8;
> > + /* Byte 4-11 */
> > + uint8_t reserved[8];
> > + /* Byte 12-15 */
> > + uint32_t company_id;
> > +#endif
> > /* Byte 16-end of log */
> > uint8_t vendor_log[1]; /* Start of vendor specific log */
> > /* Variable length. */
> > diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> > index f386296..e18ab12 100644
> > --- a/arch/powerpc/kernel/rtas.c
> > +++ b/arch/powerpc/kernel/rtas.c
> > @@ -993,21 +993,22 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
> > (struct rtas_ext_event_log_v6 *)log->buffer;
> > struct pseries_errorlog *sect;
> > unsigned char *p, *log_end;
> > + uint32_t extended_log_length = be32_to_cpu(log->extended_log_length);
> >
> > /* Check that we understand the format */
> > - if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> > + if (extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> > ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
> > - ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
> > + be32_to_cpu(ext_log->company_id) != RTAS_V6EXT_COMPANY_ID_IBM)
> > return NULL;
> >
> > - log_end = log->buffer + log->extended_log_length;
> > + log_end = log->buffer + extended_log_length;
> > p = ext_log->vendor_log;
> >
> > while (p < log_end) {
> > sect = (struct pseries_errorlog *)p;
> > - if (sect->id == section_id)
> > + if (be16_to_cpu(sect->id) == section_id)
> > return sect;
> > - p += sect->length;
> > + p += be16_to_cpu(sect->length);
> > }
> >
> > return NULL;
> > diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
> > index 1130c53..1987825 100644
> > --- a/arch/powerpc/kernel/rtasd.c
> > +++ b/arch/powerpc/kernel/rtasd.c
> > @@ -159,14 +159,16 @@ static int log_rtas_len(char * buf)
> > {
> > int len;
> > struct rtas_error_log *err;
> > + uint32_t extended_log_length;
> >
> > /* rtas fixed header */
> > len = 8;
> > err = (struct rtas_error_log *)buf;
> > - if (err->extended && err->extended_log_length) {
> > + extended_log_length = be32_to_cpu(err->extended_log_length);
> > + if (err->extended && extended_log_length) {
> >
> > /* extended header */
> > - len += err->extended_log_length;
> > + len += extended_log_length;
> > }
> >
> > if (rtas_error_log_max == 0)
> > @@ -298,7 +300,7 @@ static void handle_rtas_event(const struct rtas_error_log *log)
> > * the scope for calling rtas update-nodes.
> > */
> > if (prrn_is_enabled())
> > - prrn_schedule_update(log->extended_log_length);
> > + prrn_schedule_update(be32_to_cpu(log->extended_log_length));
> > }
> >
> > return;
> > diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
> > index 721c058..39e7557 100644
> > --- a/arch/powerpc/platforms/pseries/ras.c
> > +++ b/arch/powerpc/platforms/pseries/ras.c
> > @@ -306,7 +306,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
> > } else {
> > int len;
> >
> > - len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
> > + len = max_t(int, 8+be32_to_cpu(h->extended_log_length),
> > + RTAS_ERROR_LOG_MAX);
> > memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
> > memcpy(global_mce_data_buf, h, len);
> > errhdr = (struct rtas_error_log *)global_mce_data_buf;
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> >
>
--
Gregory Kurz kurzgreg@fr.ibm.com
gkurz@linux.vnet.ibm.com
Software Engineer @ IBM/Meiosys http://www.ibm.com
Tel +33 (0)562 165 496
"Anarchy is about taking complete responsibility for yourself."
Alan Moore.
^ permalink raw reply
* RE: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Dongsheng.Wang @ 2014-03-28 9:00 UTC (permalink / raw)
To: Kevin Hao
Cc: Ingo Molnar, James Hogan, Peter Zijlstra, fweisbec@gmail.com,
Helge Deller, linuxppc-dev@lists.ozlabs.org, Heiko Carstens,
linux-kernel@vger.kernel.org, Paul Mackerras,
James E.J. Bottomley, Martin Schwidefsky, Thomas Gleixner,
Jason.Jin@freescale.com, H. Peter Anvin, Scott Wood,
Andrew Morton, Linus Torvalds, David S. Miller
In-Reply-To: <20140328081827.GB2176@pek-khao-d1.corp.ad.wrs.com>
Thanks Kevin. Your patch works normal. :)
I still have some confused. I think when __do_softirq always get a interrup=
t, the hard stack will be run out, isn't it?
Regards,
-Dongsheng
> -----Original Message-----
> From: Kevin Hao [mailto:haokexin@gmail.com]
> Sent: Friday, March 28, 2014 4:18 PM
> To: Wang Dongsheng-B40534
> Cc: fweisbec@gmail.com; James Hogan; Andrew Morton; David S. Miller; Pete=
r
> Zijlstra; Helge Deller; H. Peter Anvin; Heiko Carstens; linux-
> kernel@vger.kernel.org; Paul Mackerras; James E.J. Bottomley; Linus Torva=
lds;
> Jin Zhengxiong-R64188; Wood Scott-B07421; Thomas Gleixner; linuxppc-
> dev@lists.ozlabs.org; Ingo Molnar; Martin Schwidefsky
> Subject: Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK featu=
re at
> powerpc platform
>=20
> On Fri, Mar 28, 2014 at 03:38:32PM +0800, Dongsheng Wang wrote:
> > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> >
> > If softirq use hardirq stack, we will get kernel painc when a hard irq
> > coming again during __do_softirq enable local irq to deal with softirq
> > action. So we need to switch satck into softirq stack when invoke soft =
irq.
> >
> > Task--->
> > | Task stack
> > |
> > Interrput->EXCEPTION->do_IRQ->
> > ^ | Hard irq stack
> > | |
> > | irq_exit->__do_softirq->local_irq_enable-- --
> >local_irq_disable
> > | | Hard irq
> stack
> > | |
> > | Interrupt
> coming again
> > | There will get a Interrupt nesting |
> >
> > ----------------------------------------------------------------------
> > --
> >
> > Trace 1: Trap 900
> >
> > Kernel stack overflow in process e8152f40, r1=3De8e05ec0
> > CPU: 0 PID: 2399 Comm: image_compress/ Not tainted
> > 3.13.0-rc3-03475-g2e3f85b #432
> > task: e8152f40 ti: c080a000 task.ti: ef176000
> > NIP: c05bec04 LR: c0305590 CTR: 00000010
> > REGS: e8e05e10 TRAP: 0901 Not tainted (3.13.0-rc3-03475-g2e3f85b)
>=20
> Could you double check if you got the following patch applied?
>=20
> commit 1a18a66446f3f289b05b634f18012424d82aa63a
> Author: Kevin Hao <haokexin@gmail.com>
> Date: Fri Jan 17 12:25:28 2014 +0800
>=20
> powerpc: Set the correct ksp_limit on ppc32 when switching to irq sta=
ck
>=20
> Guenter Roeck has got the following call trace on a p2020 board:
> Kernel stack overflow in process eb3e5a00, r1=3Deb79df90
> CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19=
eca00
> #4
> task: eb3e5a00 ti: c0616000 task.ti: ef440000
> NIP: c003a420 LR: c003a410 CTR: c0017518
> REGS: eb79dee0 TRAP: 0901 Not tainted (3.13.0-rc8-juniper-00146-g=
19eca00)
> MSR: 00029000 <CE,EE,ME> CR: 24008444 XER: 00000000
> GPR00: c003a410 eb79df90 eb3e5a00 00000000 eb05d900 00000001 65d876=
46
> 00000000
> GPR08: 00000000 020b8000 00000000 00000000 44008442
> NIP [c003a420] __do_softirq+0x94/0x1ec
> LR [c003a410] __do_softirq+0x84/0x1ec
> Call Trace:
> [eb79df90] [c003a410] __do_softirq+0x84/0x1ec (unreliable)
> [eb79dfe0] [c003a970] irq_exit+0xbc/0xc8
> [eb79dff0] [c000cc1c] call_do_irq+0x24/0x3c
> [ef441f20] [c00046a8] do_IRQ+0x8c/0xf8
> [ef441f40] [c000e7f4] ret_from_except+0x0/0x18
> --- Exception: 501 at 0xfcda524
> LR =3D 0x10024900
> Instruction dump:
> 7c781b78 3b40000a 3a73b040 543c0024 3a800000 3b3913a0 7ef5bb78 4820=
1bf9
> 5463103a 7d3b182e 7e89b92e 7c008146 <3ba00000> 7e7e9b78 48000014 57=
fff87f
> Kernel panic - not syncing: kernel stack overflow
> CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19=
eca00
> #4
> Call Trace:
>=20
> The reason is that we have used the wrong register to calculate the
> ksp_limit in commit cbc9565ee826 (powerpc: Remove ksp_limit on ppc64)=
.
> Just fix it.
>=20
> As suggested by Benjamin Herrenschmidt, also add the C prototype of t=
he
> function in the comment in order to avoid such kind of errors in the
> future.
>=20
> Cc: stable@vger.kernel.org # 3.12
> Reported-by: Guenter Roeck <linux@roeck-us.net>
> Tested-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>=20
> Thanks,
> Kevin
^ permalink raw reply
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Kevin Hao @ 2014-03-28 9:54 UTC (permalink / raw)
To: Dongsheng.Wang@freescale.com
Cc: Ingo Molnar, James Hogan, Peter Zijlstra, fweisbec@gmail.com,
Helge Deller, linuxppc-dev@lists.ozlabs.org, Heiko Carstens,
linux-kernel@vger.kernel.org, Paul Mackerras,
James E.J. Bottomley, Martin Schwidefsky, Thomas Gleixner,
Jason.Jin@freescale.com, H. Peter Anvin, Scott Wood,
Andrew Morton, Linus Torvalds, David S. Miller
In-Reply-To: <98283b6c8da549479d924d99d2b6d300@BN1PR03MB188.namprd03.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 1478 bytes --]
On Fri, Mar 28, 2014 at 09:00:13AM +0000, Dongsheng.Wang@freescale.com wrote:
> Thanks Kevin. Your patch works normal. :)
>
> I still have some confused. I think when __do_softirq always get a interrupt, the hard stack will be run out, isn't it?
No, it won't. Please see the explanation in the following commit log.
commit cc1f027454929924471bea2f362431072e3c71be
Author: Frederic Weisbecker <fweisbec@gmail.com>
Date: Tue Sep 24 17:17:47 2013 +0200
irq: Optimize softirq stack selection in irq exit
If irq_exit() is called on the arch's specified irq stack,
it should be safe to run softirqs inline under that same
irq stack as it is near empty by the time we call irq_exit().
For example if we use the same stack for both hard and soft irqs here,
the worst case scenario is:
hardirq -> softirq -> hardirq. But then the softirq supersedes the
first hardirq as the stack user since irq_exit() is called in
a mostly empty stack. So the stack merge in this case looks acceptable.
Stack overrun still have a chance to happen if hardirqs have more
opportunities to nest, but then it's another problem to solve.
So lets adapt the irq exit's softirq stack on top of a new Kconfig symbol
that can be defined when irq_exit() runs on the irq stack. That way
we can spare some stack switch on irq processing and all the cache
issues that come along.
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* [PATCH] ASoC: fsl_sai: Improve fsl_sai_isr()
From: Nicolin Chen @ 2014-03-28 11:39 UTC (permalink / raw)
To: broonie, Li.Xiubo; +Cc: alsa-devel, linuxppc-dev, linux-kernel, timur
This patch improves fsl_sai_isr() in these ways:
1, Add comment for mask fetching code.
2, Return IRQ_NONE if the IRQ is not for the device.
3, Use regmap_write() instead of regmap_update_bits().
Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
---
sound/soc/fsl/fsl_sai.c | 64 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 45 insertions(+), 19 deletions(-)
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 0bc98bb..f088545 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -30,62 +30,88 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
{
struct fsl_sai *sai = (struct fsl_sai *)devid;
struct device *dev = &sai->pdev->dev;
- u32 xcsr, mask;
+ u32 flags, xcsr, mask;
+ bool irq_none = true;
- /* Only handle those what we enabled */
+ /*
+ * Both IRQ status bits and IRQ mask bits are in the xCSR but
+ * different shifts. And we here create a mask only for those
+ * IRQs that we activated.
+ */
mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
/* Tx IRQ */
regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
- xcsr &= mask;
+ flags = xcsr & mask;
- if (xcsr & FSL_SAI_CSR_WSF)
+ if (flags)
+ irq_none = false;
+ else
+ goto irq_rx;
+
+ if (flags & FSL_SAI_CSR_WSF)
dev_dbg(dev, "isr: Start of Tx word detected\n");
- if (xcsr & FSL_SAI_CSR_SEF)
+ if (flags & FSL_SAI_CSR_SEF)
dev_warn(dev, "isr: Tx Frame sync error detected\n");
- if (xcsr & FSL_SAI_CSR_FEF) {
+ if (flags & FSL_SAI_CSR_FEF) {
dev_warn(dev, "isr: Transmit underrun detected\n");
/* FIFO reset for safety */
xcsr |= FSL_SAI_CSR_FR;
}
- if (xcsr & FSL_SAI_CSR_FWF)
+ if (flags & FSL_SAI_CSR_FWF)
dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");
- if (xcsr & FSL_SAI_CSR_FRF)
+ if (flags & FSL_SAI_CSR_FRF)
dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
- FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+ flags &= FSL_SAI_CSR_xF_W_MASK;
+ xcsr &= ~FSL_SAI_CSR_xF_MASK;
+
+ if (flags)
+ regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
+irq_rx:
/* Rx IRQ */
regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
- xcsr &= mask;
+ flags = xcsr & mask;
- if (xcsr & FSL_SAI_CSR_WSF)
+ if (flags)
+ irq_none = false;
+ else
+ goto out;
+
+ if (flags & FSL_SAI_CSR_WSF)
dev_dbg(dev, "isr: Start of Rx word detected\n");
- if (xcsr & FSL_SAI_CSR_SEF)
+ if (flags & FSL_SAI_CSR_SEF)
dev_warn(dev, "isr: Rx Frame sync error detected\n");
- if (xcsr & FSL_SAI_CSR_FEF) {
+ if (flags & FSL_SAI_CSR_FEF) {
dev_warn(dev, "isr: Receive overflow detected\n");
/* FIFO reset for safety */
xcsr |= FSL_SAI_CSR_FR;
}
- if (xcsr & FSL_SAI_CSR_FWF)
+ if (flags & FSL_SAI_CSR_FWF)
dev_dbg(dev, "isr: Enabled receive FIFO is full\n");
- if (xcsr & FSL_SAI_CSR_FRF)
+ if (flags & FSL_SAI_CSR_FRF)
dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
- FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+ flags &= FSL_SAI_CSR_xF_W_MASK;
+ xcsr &= ~FSL_SAI_CSR_xF_MASK;
- return IRQ_HANDLED;
+ if (flags)
+ regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
+
+out:
+ if (irq_none)
+ return IRQ_NONE;
+ else
+ return IRQ_HANDLED;
}
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
--
1.8.4
^ permalink raw reply related
* Re: [PATCH] ASoC: fsl_sai: Improve fsl_sai_isr()
From: Mark Brown @ 2014-03-28 12:30 UTC (permalink / raw)
To: Nicolin Chen; +Cc: alsa-devel, Li.Xiubo, linuxppc-dev, linux-kernel, timur
In-Reply-To: <1396006765-4527-1-git-send-email-Guangyu.Chen@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 480 bytes --]
On Fri, Mar 28, 2014 at 07:39:25PM +0800, Nicolin Chen wrote:
> This patch improves fsl_sai_isr() in these ways:
> 1, Add comment for mask fetching code.
> 2, Return IRQ_NONE if the IRQ is not for the device.
> 3, Use regmap_write() instead of regmap_update_bits().
Applied, thanks. It would have been better to do separate patches here
- actually with your explanation the update_bits() made sense so you
could've left that but equally it doesn't do any harm to skip the read.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Nathan Fontenot @ 2014-03-28 14:57 UTC (permalink / raw)
To: Greg Kurz, benh; +Cc: linuxppc-dev, paulus, linux-kernel, anton
In-Reply-To: <20140328073344.26823.32931.stgit@bahia.local>
Greg,
There is one more place that needs fixing up, in mobility_rtas_call(),
and handle_rtas_event() in arch/powerpc/platforms/pseries/mobility.c.
This relates to rtas event handling for PRRN notifications, we need to
convert the scope variable (PRRN notifications re-use the extended log
length field) when read from the rtas event in handle_rtas_event(), then
convert it back to big endian in mobility_rtas_call().
The double conversion seems yucky but mobility_rtas_call can be called
other places where the scope variable is not originally big endian.
-Nathan
On 03/28/2014 02:33 AM, Greg Kurz wrote:
> The current kernel code assumes big endian and parses RTAS events all
> wrong. The most visible effect is that we cannot honor EPOW events,
> meaning, for example, we cannot shut down a guest properly from the
> hypervisor.
>
> This patch fixes that.
>
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/rtas.h | 46 ++++++++++++++++++++++++++++++++++
> arch/powerpc/kernel/rtas.c | 11 ++++----
> arch/powerpc/kernel/rtasd.c | 8 ++++--
> arch/powerpc/platforms/pseries/ras.c | 3 +-
> 4 files changed, 59 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
> index 9bd52c6..8bb99d0 100644
> --- a/arch/powerpc/include/asm/rtas.h
> +++ b/arch/powerpc/include/asm/rtas.h
> @@ -150,15 +150,37 @@ struct rtas_suspend_me_data {
> #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
>
> struct rtas_error_log {
> +#ifdef __BIG_ENDIAN__
> + /* Byte 0 */
> unsigned long version:8; /* Architectural version */
> + /* Byte 1 */
> unsigned long severity:3; /* Severity level of error */
> unsigned long disposition:2; /* Degree of recovery */
> unsigned long extended:1; /* extended log present? */
> unsigned long /* reserved */ :2; /* Reserved for future use */
> + /* Byte 2 */
> unsigned long initiator:4; /* Initiator of event */
> unsigned long target:4; /* Target of failed operation */
> + /* Byte 3 */
> unsigned long type:8; /* General event or error*/
> + /* Byte 4 */
> unsigned long extended_log_length:32; /* length in bytes */
> +#else
> + /* Byte 0 */
> + unsigned long version:8;
> + /* Byte 1 */
> + unsigned long :2;
> + unsigned long extended:1;
> + unsigned long disposition:2;
> + unsigned long severity:3;
> + unsigned long target:4;
> + /* Byte 2 */
> + unsigned long initiator:4;
> + /* Byte 3 */
> + unsigned long type:8;
> + /* Byte 4 */
> + unsigned long extended_log_length:32;
> +#endif
> unsigned char buffer[1]; /* Start of extended log */
> /* Variable length. */
> };
> @@ -171,6 +193,7 @@ struct rtas_error_log {
> * from "buffer" field of struct rtas_error_log defined above.
> */
> struct rtas_ext_event_log_v6 {
> +#ifdef __BIG_ENDIAN__
> /* Byte 0 */
> uint32_t log_valid:1; /* 1:Log valid */
> uint32_t unrecoverable_error:1; /* 1:Unrecoverable error */
> @@ -200,6 +223,29 @@ struct rtas_ext_event_log_v6 {
> uint32_t company_id; /* Company ID of the company */
> /* that defines the format for */
> /* the vendor specific log type */
> +#else
> + /* Byte 0 */
> + uint32_t :1;
> + uint32_t big_endian:1;
> + uint32_t new_log:1;
> + uint32_t predictive_error:1;
> + uint32_t degraded_operation:1;
> + uint32_t recoverable_error:1;
> + uint32_t unrecoverable_error:1;
> + uint32_t log_valid:1;
> + /* Byte 1 */
> + uint32_t :8;
> + /* Byte 2 */
> + uint32_t log_format:4;
> + uint32_t :3;
> + uint32_t powerpc_format:1;
> + /* Byte 3 */
> + uint32_t :8;
> + /* Byte 4-11 */
> + uint8_t reserved[8];
> + /* Byte 12-15 */
> + uint32_t company_id;
> +#endif
> /* Byte 16-end of log */
> uint8_t vendor_log[1]; /* Start of vendor specific log */
> /* Variable length. */
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index f386296..e18ab12 100644
> --- a/arch/powerpc/kernel/rtas.c
> +++ b/arch/powerpc/kernel/rtas.c
> @@ -993,21 +993,22 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
> (struct rtas_ext_event_log_v6 *)log->buffer;
> struct pseries_errorlog *sect;
> unsigned char *p, *log_end;
> + uint32_t extended_log_length = be32_to_cpu(log->extended_log_length);
>
> /* Check that we understand the format */
> - if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> + if (extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
> - ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
> + be32_to_cpu(ext_log->company_id) != RTAS_V6EXT_COMPANY_ID_IBM)
> return NULL;
>
> - log_end = log->buffer + log->extended_log_length;
> + log_end = log->buffer + extended_log_length;
> p = ext_log->vendor_log;
>
> while (p < log_end) {
> sect = (struct pseries_errorlog *)p;
> - if (sect->id == section_id)
> + if (be16_to_cpu(sect->id) == section_id)
> return sect;
> - p += sect->length;
> + p += be16_to_cpu(sect->length);
> }
>
> return NULL;
> diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
> index 1130c53..1987825 100644
> --- a/arch/powerpc/kernel/rtasd.c
> +++ b/arch/powerpc/kernel/rtasd.c
> @@ -159,14 +159,16 @@ static int log_rtas_len(char * buf)
> {
> int len;
> struct rtas_error_log *err;
> + uint32_t extended_log_length;
>
> /* rtas fixed header */
> len = 8;
> err = (struct rtas_error_log *)buf;
> - if (err->extended && err->extended_log_length) {
> + extended_log_length = be32_to_cpu(err->extended_log_length);
> + if (err->extended && extended_log_length) {
>
> /* extended header */
> - len += err->extended_log_length;
> + len += extended_log_length;
> }
>
> if (rtas_error_log_max == 0)
> @@ -298,7 +300,7 @@ static void handle_rtas_event(const struct rtas_error_log *log)
> * the scope for calling rtas update-nodes.
> */
> if (prrn_is_enabled())
> - prrn_schedule_update(log->extended_log_length);
> + prrn_schedule_update(be32_to_cpu(log->extended_log_length));
> }
>
> return;
> diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
> index 721c058..39e7557 100644
> --- a/arch/powerpc/platforms/pseries/ras.c
> +++ b/arch/powerpc/platforms/pseries/ras.c
> @@ -306,7 +306,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
> } else {
> int len;
>
> - len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
> + len = max_t(int, 8+be32_to_cpu(h->extended_log_length),
> + RTAS_ERROR_LOG_MAX);
> memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
> memcpy(global_mce_data_buf, h, len);
> errhdr = (struct rtas_error_log *)global_mce_data_buf;
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/powernv: Enable fetching of platform sensor data
From: Paul Gortmaker @ 2014-03-28 15:26 UTC (permalink / raw)
To: Neelesh Gupta; +Cc: sbhat, linuxppc-dev
In-Reply-To: <20140307053320.3547.10656.stgit@neelegup-tp-t420.in.ibm.com>
On Fri, Mar 7, 2014 at 12:33 AM, Neelesh Gupta
<neelegup@linux.vnet.ibm.com> wrote:
> This patch enables fetching of various platform sensor data through
> OPAL and expects a sensor handle from the driver to pass to OPAL.
Looks like a missing header, causing build failures on celleb_defconfig
cc1: warnings being treated as errors
In file included from arch/powerpc/platforms/powernv/opal-sensor.c:23:0:
/home/paul/git/linux-head/arch/powerpc/include/asm/opal.h:893:42:
error: 'struct notifier_block' declared inside parameter list
/home/paul/git/linux-head/arch/powerpc/include/asm/opal.h:893:42:
error: its scope is only this definition or declaration, which is
probably not what you want
/home/paul/git/linux-head/arch/powerpc/include/asm/opal.h:895:14:
error: 'struct notifier_block' declared inside parameter list
make[2]: *** [arch/powerpc/platforms/powernv/opal-sensor.o] Error 1
make[1]: *** [arch/powerpc/platforms/powernv] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [arch/powerpc/platforms] Error 2
make: *** Waiting for unfinished jobs....
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[4029cd66545f0a45258eda5313b7559bfeaaaae4] powerpc/powernv: Enable
reading and updating of system parameters
running ./x
#
# configuration written to .config
#
7224adbbb80329d1a3ec5aa98213b50365fcd246 is the first bad commit
commit 7224adbbb80329d1a3ec5aa98213b50365fcd246
Author: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
Date: Fri Mar 7 11:03:27 2014 +0530
powerpc/powernv: Enable fetching of platform sensor data
This patch enables fetching of various platform sensor data through
OPAL and expects a sensor handle from the driver to pass to OPAL.
Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
:040000 040000 ee7c8dec121a0da53be09da0e1449d8b885ef8a1
b8c4906de326638be77387c78173f7148369d6ff M arch
bisect run success
http://kisskb.ellerman.id.au/kisskb/buildresult/10844143/
Paul.
---
>
> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> arch/powerpc/include/asm/opal.h | 4 ++
> arch/powerpc/platforms/powernv/Makefile | 2 -
> arch/powerpc/platforms/powernv/opal-sensor.c | 64 ++++++++++++++++++++++++
> arch/powerpc/platforms/powernv/opal-wrappers.S | 1
> 4 files changed, 70 insertions(+), 1 deletion(-)
> create mode 100644 arch/powerpc/platforms/powernv/opal-sensor.c
>
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 60b3edc..a1cc4dd 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -159,6 +159,7 @@ extern int opal_enter_rtas(struct rtas_args *args,
> #define OPAL_GET_MSG 85
> #define OPAL_CHECK_ASYNC_COMPLETION 86
> #define OPAL_SYNC_HOST_REBOOT 87
> +#define OPAL_SENSOR_READ 88
> #define OPAL_GET_PARAM 89
> #define OPAL_SET_PARAM 90
>
> @@ -847,6 +848,8 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer,
> size_t length);
> int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
> size_t length);
> +int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
> + uint32_t *sensor_data);
>
> /* Internal functions */
> extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
> @@ -875,6 +878,7 @@ extern int opal_async_get_token_interruptible(void);
> extern int __opal_async_release_token(int token);
> extern int opal_async_release_token(int token);
> extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg);
> +extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data);
>
> extern void hvc_opal_init_early(void);
>
> diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
> index e6166d3..00ae938 100644
> --- a/arch/powerpc/platforms/powernv/Makefile
> +++ b/arch/powerpc/platforms/powernv/Makefile
> @@ -1,6 +1,6 @@
> obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
> obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o opal-sysparam.o
> -obj-y += rng.o
> +obj-y += rng.o opal-sensor.o
>
> obj-$(CONFIG_SMP) += smp.o
> obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
> diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c
> new file mode 100644
> index 0000000..663cc9c
> --- /dev/null
> +++ b/arch/powerpc/platforms/powernv/opal-sensor.c
> @@ -0,0 +1,64 @@
> +/*
> + * PowerNV sensor code
> + *
> + * Copyright (C) 2013 IBM
> + *
> + * 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
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/mutex.h>
> +#include <asm/opal.h>
> +
> +static DEFINE_MUTEX(opal_sensor_mutex);
> +
> +/*
> + * This will return sensor information to driver based on the requested sensor
> + * handle. A handle is an opaque id for the powernv, read by the driver from the
> + * device tree..
> + */
> +int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
> +{
> + int ret, token;
> + struct opal_msg msg;
> +
> + token = opal_async_get_token_interruptible();
> + if (token < 0) {
> + pr_err("%s: Couldn't get the token, returning\n", __func__);
> + ret = token;
> + goto out;
> + }
> +
> + mutex_lock(&opal_sensor_mutex);
> + ret = opal_sensor_read(sensor_hndl, token, sensor_data);
> + if (ret != OPAL_ASYNC_COMPLETION)
> + goto out_token;
> +
> + ret = opal_async_wait_response(token, &msg);
> + if (ret) {
> + pr_err("%s: Failed to wait for the async response, %d\n",
> + __func__, ret);
> + goto out_token;
> + }
> +
> + ret = msg.params[1];
> +
> +out_token:
> + mutex_unlock(&opal_sensor_mutex);
> + opal_async_release_token(token);
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(opal_get_sensor_data);
> diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
> index 0afdeca..4279e30 100644
> --- a/arch/powerpc/platforms/powernv/opal-wrappers.S
> +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
> @@ -129,5 +129,6 @@ OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
> OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
> OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
> OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
> +OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ);
> OPAL_CALL(opal_get_param, OPAL_GET_PARAM);
> OPAL_CALL(opal_set_param, OPAL_SET_PARAM);
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Greg Kurz @ 2014-03-28 15:31 UTC (permalink / raw)
To: Nathan Fontenot; +Cc: linuxppc-dev, paulus, linux-kernel, anton
In-Reply-To: <53358DBF.4080808@linux.vnet.ibm.com>
On Fri, 28 Mar 2014 09:57:03 -0500
Nathan Fontenot <nfont@linux.vnet.ibm.com> wrote:
> Greg,
>
> There is one more place that needs fixing up, in mobility_rtas_call(),
> and handle_rtas_event() in arch/powerpc/platforms/pseries/mobility.c.
>
> This relates to rtas event handling for PRRN notifications, we need to
> convert the scope variable (PRRN notifications re-use the extended log
> length field) when read from the rtas event in handle_rtas_event(), then
> convert it back to big endian in mobility_rtas_call().
>
> The double conversion seems yucky but mobility_rtas_call can be called
> other places where the scope variable is not originally big endian.
>
> -Nathan
>
Nathan,
rtas_call() in arch/powerpc/kernel/rtas.c already does the conversion for us.
Thanks.
> On 03/28/2014 02:33 AM, Greg Kurz wrote:
> > The current kernel code assumes big endian and parses RTAS events all
> > wrong. The most visible effect is that we cannot honor EPOW events,
> > meaning, for example, we cannot shut down a guest properly from the
> > hypervisor.
> >
> > This patch fixes that.
> >
> > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > ---
> > arch/powerpc/include/asm/rtas.h | 46 ++++++++++++++++++++++++++++++++++
> > arch/powerpc/kernel/rtas.c | 11 ++++----
> > arch/powerpc/kernel/rtasd.c | 8 ++++--
> > arch/powerpc/platforms/pseries/ras.c | 3 +-
> > 4 files changed, 59 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
> > index 9bd52c6..8bb99d0 100644
> > --- a/arch/powerpc/include/asm/rtas.h
> > +++ b/arch/powerpc/include/asm/rtas.h
> > @@ -150,15 +150,37 @@ struct rtas_suspend_me_data {
> > #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
> >
> > struct rtas_error_log {
> > +#ifdef __BIG_ENDIAN__
> > + /* Byte 0 */
> > unsigned long version:8; /* Architectural version */
> > + /* Byte 1 */
> > unsigned long severity:3; /* Severity level of error */
> > unsigned long disposition:2; /* Degree of recovery */
> > unsigned long extended:1; /* extended log present? */
> > unsigned long /* reserved */ :2; /* Reserved for future use */
> > + /* Byte 2 */
> > unsigned long initiator:4; /* Initiator of event */
> > unsigned long target:4; /* Target of failed operation */
> > + /* Byte 3 */
> > unsigned long type:8; /* General event or error*/
> > + /* Byte 4 */
> > unsigned long extended_log_length:32; /* length in bytes */
> > +#else
> > + /* Byte 0 */
> > + unsigned long version:8;
> > + /* Byte 1 */
> > + unsigned long :2;
> > + unsigned long extended:1;
> > + unsigned long disposition:2;
> > + unsigned long severity:3;
> > + unsigned long target:4;
> > + /* Byte 2 */
> > + unsigned long initiator:4;
> > + /* Byte 3 */
> > + unsigned long type:8;
> > + /* Byte 4 */
> > + unsigned long extended_log_length:32;
> > +#endif
> > unsigned char buffer[1]; /* Start of extended log */
> > /* Variable length. */
> > };
> > @@ -171,6 +193,7 @@ struct rtas_error_log {
> > * from "buffer" field of struct rtas_error_log defined above.
> > */
> > struct rtas_ext_event_log_v6 {
> > +#ifdef __BIG_ENDIAN__
> > /* Byte 0 */
> > uint32_t log_valid:1; /* 1:Log valid */
> > uint32_t unrecoverable_error:1; /* 1:Unrecoverable error */
> > @@ -200,6 +223,29 @@ struct rtas_ext_event_log_v6 {
> > uint32_t company_id; /* Company ID of the company */
> > /* that defines the format for */
> > /* the vendor specific log type */
> > +#else
> > + /* Byte 0 */
> > + uint32_t :1;
> > + uint32_t big_endian:1;
> > + uint32_t new_log:1;
> > + uint32_t predictive_error:1;
> > + uint32_t degraded_operation:1;
> > + uint32_t recoverable_error:1;
> > + uint32_t unrecoverable_error:1;
> > + uint32_t log_valid:1;
> > + /* Byte 1 */
> > + uint32_t :8;
> > + /* Byte 2 */
> > + uint32_t log_format:4;
> > + uint32_t :3;
> > + uint32_t powerpc_format:1;
> > + /* Byte 3 */
> > + uint32_t :8;
> > + /* Byte 4-11 */
> > + uint8_t reserved[8];
> > + /* Byte 12-15 */
> > + uint32_t company_id;
> > +#endif
> > /* Byte 16-end of log */
> > uint8_t vendor_log[1]; /* Start of vendor specific log */
> > /* Variable length. */
> > diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> > index f386296..e18ab12 100644
> > --- a/arch/powerpc/kernel/rtas.c
> > +++ b/arch/powerpc/kernel/rtas.c
> > @@ -993,21 +993,22 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
> > (struct rtas_ext_event_log_v6 *)log->buffer;
> > struct pseries_errorlog *sect;
> > unsigned char *p, *log_end;
> > + uint32_t extended_log_length = be32_to_cpu(log->extended_log_length);
> >
> > /* Check that we understand the format */
> > - if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> > + if (extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
> > ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
> > - ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
> > + be32_to_cpu(ext_log->company_id) != RTAS_V6EXT_COMPANY_ID_IBM)
> > return NULL;
> >
> > - log_end = log->buffer + log->extended_log_length;
> > + log_end = log->buffer + extended_log_length;
> > p = ext_log->vendor_log;
> >
> > while (p < log_end) {
> > sect = (struct pseries_errorlog *)p;
> > - if (sect->id == section_id)
> > + if (be16_to_cpu(sect->id) == section_id)
> > return sect;
> > - p += sect->length;
> > + p += be16_to_cpu(sect->length);
> > }
> >
> > return NULL;
> > diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
> > index 1130c53..1987825 100644
> > --- a/arch/powerpc/kernel/rtasd.c
> > +++ b/arch/powerpc/kernel/rtasd.c
> > @@ -159,14 +159,16 @@ static int log_rtas_len(char * buf)
> > {
> > int len;
> > struct rtas_error_log *err;
> > + uint32_t extended_log_length;
> >
> > /* rtas fixed header */
> > len = 8;
> > err = (struct rtas_error_log *)buf;
> > - if (err->extended && err->extended_log_length) {
> > + extended_log_length = be32_to_cpu(err->extended_log_length);
> > + if (err->extended && extended_log_length) {
> >
> > /* extended header */
> > - len += err->extended_log_length;
> > + len += extended_log_length;
> > }
> >
> > if (rtas_error_log_max == 0)
> > @@ -298,7 +300,7 @@ static void handle_rtas_event(const struct rtas_error_log *log)
> > * the scope for calling rtas update-nodes.
> > */
> > if (prrn_is_enabled())
> > - prrn_schedule_update(log->extended_log_length);
> > + prrn_schedule_update(be32_to_cpu(log->extended_log_length));
> > }
> >
> > return;
> > diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
> > index 721c058..39e7557 100644
> > --- a/arch/powerpc/platforms/pseries/ras.c
> > +++ b/arch/powerpc/platforms/pseries/ras.c
> > @@ -306,7 +306,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
> > } else {
> > int len;
> >
> > - len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
> > + len = max_t(int, 8+be32_to_cpu(h->extended_log_length),
> > + RTAS_ERROR_LOG_MAX);
> > memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
> > memcpy(global_mce_data_buf, h, len);
> > errhdr = (struct rtas_error_log *)global_mce_data_buf;
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> >
--
Gregory Kurz kurzgreg@fr.ibm.com
gkurz@linux.vnet.ibm.com
Software Engineer @ IBM/Meiosys http://www.ibm.com
Tel +33 (0)562 165 496
"Anarchy is about taking complete responsibility for yourself."
Alan Moore.
^ permalink raw reply
* Re: [PATCH] phy/at8031: enable at8031 to work on interrupt mode
From: Sergei Shtylyov @ 2014-03-28 18:09 UTC (permalink / raw)
To: qiang.zhao@freescale.com, linuxppc-dev@lists.ozlabs.org,
netdev@vger.kernel.org, Scott Wood
Cc: mugunthanvnm@ti.com, linux-kernel@vger.kernel.org,
helmut.schaa@googlemail.com, zonque@gmail.com,
davem@davemloft.net, Xiaobo Xie
In-Reply-To: <0ca1e7910cd247c4aebe4cbd48a633cb@BLUPR03MB341.namprd03.prod.outlook.com>
Hello.
On 03/28/2014 10:36 AM, qiang.zhao@freescale.com wrote:
>>> The at8031 can work on polling mode and interrupt mode.
>>> Add ack_interrupt and config intr funcs to enable interrupt mode for
>>> it.
>>> Signed-off-by: Zhao Qiang <B45475@freescale.com>
>>> ---
>>> drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++++++++
>>> 1 file changed, 30 insertions(+)
>>> diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index
>>> bc71947..d034ef5 100644
>>> --- a/drivers/net/phy/at803x.c
>>> +++ b/drivers/net/phy/at803x.c
>> [...]
>>> @@ -191,6 +194,31 @@ static int at803x_config_init(struct phy_device
>> *phydev)
>>> return 0;
>>> }
>>>
>>> +static int at803x_ack_interrupt(struct phy_device *phydev) {
>>> + int err;
>>> +
>>> + err = phy_read(phydev, AT803X_INSR);
>> Could make this an initializer...
> Thank you very much. However I have no idea about "make this an initializer".
int err = phy_read(phydev, AT803X_INSR);
WBR, Sergei
^ permalink raw reply
* [PATCH v5 0/3] powernv,cpufreq: Dynamic Frequency Scaling support
From: Gautham R. Shenoy @ 2014-03-28 20:11 UTC (permalink / raw)
To: Viresh Kumar, rjw, Benjamin Herrenschmidt
Cc: Gautham R. Shenoy, Linux PM list, linux-kernel, cpufreq,
linuxppc-dev, Anton Blanchard, srivatsa.bhat
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
Hi,
This is v5 of the patchset to enable dynamic frequency scaling on IBM
PowerNV platforms. This patchset does address all the review comments
obtained for v4 (which can be found at [1]).
Changes from v4:
* Created a separate patch to select the CPUFreq related Config
options for PowerNV
* Dropped the per-core locking hunks in
drivers/cpufreq/powernv-cpufreq.c since the CPUFreq core takes
care of the for us after the following commit which is present in
linux-next:
commit 12478cf0c55e5969f740bb38a24b1a0104ae18d8
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Date: Mon Mar 24 13:35:44 2014 +0530
cpufreq: Make sure frequency transitions are serialized
* [PATCH v5 3/3] gets rid of the powernv_pstate_ids[] array that
was being used to record the pstate ids. After the following
patch it is safe to use cpufreq_frequency_table.driver_data
since it is opaque to the cpufreq core:
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: 2014-03-28 13:53:47
url: http://marc.info/?l=linux-pm&m=139601416804702&w=2
cpufreq: create another field .flags in cpufreq_frequency_table
The patchset is based on the commit
201544be8c37dffbf069bb5fc9edb5674f8c1754 of the linux-next tree.
While all the patches in the patchset apply cleanly on linux-next,
[PATCH v5 3/3] requires the Viresh's patch that was mentioned
above. Otherwise, the frequency corresponding to pstate id -3 will be
omited while reporting the "scaling_available_frequencies" in sysfs.
[1]: http://marc.info/?l=linux-pm&m=139585297620612&w=2
Gautham R. Shenoy (2):
powernv, cpufreq: Select CPUFreq related Kconfig options for powernv
powernv,cpufreq: Use cpufreq_frequency_table.driver_data to store
pstate ids
Vaidyanathan Srinivasan (1):
powernv, cpufreq: cpufreq driver for powernv platform
arch/powerpc/configs/pseries_defconfig | 1 +
arch/powerpc/configs/pseries_le_defconfig | 1 +
arch/powerpc/include/asm/reg.h | 4 +
arch/powerpc/platforms/powernv/Kconfig | 6 +
drivers/cpufreq/Kconfig.powerpc | 8 +
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/powernv-cpufreq.c | 341 ++++++++++++++++++++++++++++++
7 files changed, 362 insertions(+)
create mode 100644 drivers/cpufreq/powernv-cpufreq.c
--
1.8.3.1
^ permalink raw reply
* [PATCH v5 2/3] powernv, cpufreq: cpufreq driver for powernv platform
From: Gautham R. Shenoy @ 2014-03-28 20:11 UTC (permalink / raw)
To: Viresh Kumar, rjw, Benjamin Herrenschmidt
Cc: Gautham R. Shenoy, Linux PM list, linux-kernel, cpufreq,
linuxppc-dev, Anton Blanchard, srivatsa.bhat
In-Reply-To: <1396037484-23907-1-git-send-email-ego@linux.vnet.ibm.com>
From: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Backend driver to dynamically set voltage and frequency on
IBM POWER non-virtualized platforms. Power management SPRs
are used to set the required PState.
This driver works in conjunction with cpufreq governors
like 'ondemand' to provide a demand based frequency and
voltage setting on IBM POWER non-virtualized platforms.
PState table is obtained from OPAL v3 firmware through device
tree.
powernv_cpufreq back-end driver would parse the relevant device-tree
nodes and initialise the cpufreq subsystem on powernv platform.
The code was originally written by svaidy@linux.vnet.ibm.com. Over
time it was modified to accomodate bug-fixes as well as updates to the
the cpu-freq core. Relevant portions of the change logs corresponding
to those modifications are noted below:
* The policy->cpus needs to be populated in a hotplug-invariant
manner instead of using cpu_sibling_mask() which varies with
cpu-hotplug. This is because the cpufreq core code copies this
content into policy->related_cpus mask which should not vary on
cpu-hotplug. [Authored by srivatsa.bhat@linux.vnet.ibm.com]
* Create a helper routine that can return the cpu-frequency for the
corresponding pstate_id. Also, cache the values of the pstate_max,
pstate_min and pstate_nominal and nr_pstates in a static structure
so that they can be reused in the future to perform any
validations. [Authored by ego@linux.vnet.ibm.com]
* Create a driver attribute named cpuinfo_nominal_freq which creates
a sysfs read-only file named cpuinfo_nominal_freq. Export the
frequency corresponding to the nominal_pstate through this
interface.
Nominal frequency is the highest non-turbo frequency for the
platform. This is generally used for setting governor policies
from user space for optimal energy efficiency. [Authored by
ego@linux.vnet.ibm.com]
* Implement a powernv_cpufreq_get(unsigned int cpu) method which will
return the current operating frequency. Export this via the sysfs
interface cpuinfo_cur_freq by setting powernv_cpufreq_driver.get to
powernv_cpufreq_get(). [Authored by ego@linux.vnet.ibm.com]
[Change log updated by ego@linux.vnet.ibm.com]
Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/reg.h | 4 +
drivers/cpufreq/Kconfig.powerpc | 8 +
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/powernv-cpufreq.c | 342 ++++++++++++++++++++++++++++++++++++++
4 files changed, 355 insertions(+)
create mode 100644 drivers/cpufreq/powernv-cpufreq.c
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1a36b8e..2189f8f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -271,6 +271,10 @@
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
#define SPRN_IC 0x350 /* Virtual Instruction Count */
#define SPRN_VTB 0x351 /* Virtual Time Base */
+#define SPRN_PMICR 0x354 /* Power Management Idle Control Reg */
+#define SPRN_PMSR 0x355 /* Power Management Status Reg */
+#define SPRN_PMCR 0x374 /* Power Management Control Register */
+
/* HFSCR and FSCR bit numbers are the same */
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index ca0021a..72564b7 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -54,3 +54,11 @@ config PPC_PASEMI_CPUFREQ
help
This adds the support for frequency switching on PA Semi
PWRficient processors.
+
+config POWERNV_CPUFREQ
+ tristate "CPU frequency scaling for IBM POWERNV platform"
+ depends on PPC_POWERNV
+ default y
+ help
+ This adds support for CPU frequency switching on IBM POWERNV
+ platform
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 7494565..0dbb963 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o
+obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o
##################################################################################
# Other platform drivers
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
new file mode 100644
index 0000000..e1e5197
--- /dev/null
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -0,0 +1,342 @@
+/*
+ * POWERNV cpufreq driver for the IBM POWER processors
+ *
+ * (C) Copyright IBM 2014
+ *
+ * Author: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
+ *
+ * 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, 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.
+ *
+ */
+
+#define pr_fmt(fmt) "powernv-cpufreq: " fmt
+
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/smp.h>
+#include <linux/of.h>
+
+#include <asm/cputhreads.h>
+#include <asm/reg.h>
+
+#define POWERNV_MAX_PSTATES 256
+
+static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+static int powernv_pstate_ids[POWERNV_MAX_PSTATES+1];
+
+/*
+ * Note: The set of pstates consists of contiguous integers, the
+ * smallest of which is indicated by powernv_pstate_info.min, the
+ * largest of which is indicated by powernv_pstate_info.max.
+ *
+ * The nominal pstate is the highest non-turbo pstate in this
+ * platform. This is indicated by powernv_pstate_info.nominal.
+ */
+static struct powernv_pstate_info {
+ int min;
+ int max;
+ int nominal;
+ int nr_pstates;
+} powernv_pstate_info;
+
+/*
+ * Initialize the freq table based on data obtained
+ * from the firmware passed via device-tree
+ */
+static int init_powernv_pstates(void)
+{
+ struct device_node *power_mgt;
+ int i, pstate_min, pstate_max, pstate_nominal, nr_pstates = 0;
+ const __be32 *pstate_ids, *pstate_freqs;
+ u32 len_ids, len_freqs;
+
+ power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
+ if (!power_mgt) {
+ pr_warn("power-mgt node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-min", &pstate_min)) {
+ pr_warn("ibm,pstate-min node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-max", &pstate_max)) {
+ pr_warn("ibm,pstate-max node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-nominal",
+ &pstate_nominal)) {
+ pr_warn("ibm,pstate-nominal not found\n");
+ return -ENODEV;
+ }
+ pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min,
+ pstate_nominal, pstate_max);
+
+ pstate_ids = of_get_property(power_mgt, "ibm,pstate-ids", &len_ids);
+ if (!pstate_ids) {
+ pr_warn("ibm,pstate-ids not found\n");
+ return -ENODEV;
+ }
+
+ pstate_freqs = of_get_property(power_mgt, "ibm,pstate-frequencies-mhz",
+ &len_freqs);
+ if (!pstate_freqs) {
+ pr_warn("ibm,pstate-frequencies-mhz not found\n");
+ return -ENODEV;
+ }
+
+ WARN_ON(len_ids != len_freqs);
+ nr_pstates = min(len_ids, len_freqs) / sizeof(u32);
+ if (!nr_pstates) {
+ pr_warn("No PStates found\n");
+ return -ENODEV;
+ }
+
+ pr_debug("NR PStates %d\n", nr_pstates);
+ for (i = 0; i < nr_pstates; i++) {
+ u32 id = be32_to_cpu(pstate_ids[i]);
+ u32 freq = be32_to_cpu(pstate_freqs[i]);
+
+ pr_debug("PState id %d freq %d MHz\n", id, freq);
+ powernv_freqs[i].frequency = freq * 1000; /* kHz */
+ powernv_pstate_ids[i] = id;
+ }
+ /* End of list marker entry */
+ powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
+
+ powernv_pstate_info.min = pstate_min;
+ powernv_pstate_info.max = pstate_max;
+ powernv_pstate_info.nominal = pstate_nominal;
+ powernv_pstate_info.nr_pstates = nr_pstates;
+
+ return 0;
+}
+
+/* Returns the CPU frequency corresponding to the pstate_id. */
+static unsigned int pstate_id_to_freq(int pstate_id)
+{
+ int i;
+
+ i = powernv_pstate_info.max - pstate_id;
+ BUG_ON(i >= powernv_pstate_info.nr_pstates || i < 0);
+
+ return powernv_freqs[i].frequency;
+}
+
+/*
+ * cpuinfo_nominal_freq_show - Show the nominal CPU frequency as indicated by
+ * the firmware
+ */
+static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return sprintf(buf, "%u\n",
+ pstate_id_to_freq(powernv_pstate_info.nominal));
+}
+
+struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq =
+ __ATTR_RO(cpuinfo_nominal_freq);
+
+static struct freq_attr *powernv_cpu_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ &cpufreq_freq_attr_cpuinfo_nominal_freq,
+ NULL,
+};
+
+/* Helper routines */
+
+/* Access helpers to power mgt SPR */
+
+static inline unsigned long get_pmspr(unsigned long sprn)
+{
+ switch (sprn) {
+ case SPRN_PMCR:
+ return mfspr(SPRN_PMCR);
+
+ case SPRN_PMICR:
+ return mfspr(SPRN_PMICR);
+
+ case SPRN_PMSR:
+ return mfspr(SPRN_PMSR);
+ }
+ BUG();
+}
+
+static inline void set_pmspr(unsigned long sprn, unsigned long val)
+{
+ switch (sprn) {
+ case SPRN_PMCR:
+ mtspr(SPRN_PMCR, val);
+ return;
+
+ case SPRN_PMICR:
+ mtspr(SPRN_PMICR, val);
+ return;
+ }
+ BUG();
+}
+
+/*
+ * Use objects of this type to query/update
+ * pstates on a remote CPU via smp_call_function.
+ */
+struct powernv_smp_call_data {
+ unsigned int freq;
+ int pstate_id;
+};
+
+/*
+ * powernv_read_cpu_freq: Reads the current frequency on this CPU.
+ *
+ * Called via smp_call_function.
+ *
+ * Note: The caller of the smp_call_function should pass an argument of
+ * the type 'struct powernv_smp_call_data *' along with this function.
+ *
+ * The current frequency on this CPU will be returned via
+ * ((struct powernv_smp_call_data *)arg)->freq;
+ */
+static void powernv_read_cpu_freq(void *arg)
+{
+ unsigned long pmspr_val;
+ s8 local_pstate_id;
+ struct powernv_smp_call_data *freq_data = arg;
+
+ pmspr_val = get_pmspr(SPRN_PMSR);
+
+ /*
+ * The local pstate id corresponds bits 48..55 in the PMSR.
+ * Note: Watch out for the sign!
+ */
+ local_pstate_id = (pmspr_val >> 48) & 0xFF;
+ freq_data->pstate_id = local_pstate_id;
+ freq_data->freq = pstate_id_to_freq(freq_data->pstate_id);
+
+ pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n",
+ raw_smp_processor_id(), pmspr_val, freq_data->pstate_id,
+ freq_data->freq);
+}
+
+/*
+ * powernv_cpufreq_get: Returns the CPU frequency as reported by the
+ * firmware for CPU 'cpu'. This value is reported through the sysfs
+ * file cpuinfo_cur_freq.
+ */
+unsigned int powernv_cpufreq_get(unsigned int cpu)
+{
+ struct powernv_smp_call_data freq_data;
+
+ smp_call_function_any(cpu_sibling_mask(cpu), powernv_read_cpu_freq,
+ &freq_data, 1);
+
+ return freq_data.freq;
+}
+
+/*
+ * set_pstate: Sets the pstate on this CPU.
+ *
+ * This is called via an smp_call_function.
+ *
+ * The caller must ensure that freq_data is of the type
+ * (struct powernv_smp_call_data *) and the pstate_id which needs to be set
+ * on this CPU should be present in freq_data->pstate_id.
+ */
+static void set_pstate(void *freq_data)
+{
+ unsigned long val;
+ unsigned long pstate_ul =
+ ((struct powernv_smp_call_data *) freq_data)->pstate_id;
+
+ val = get_pmspr(SPRN_PMCR);
+ val = val & 0x0000FFFFFFFFFFFFULL;
+
+ pstate_ul = pstate_ul & 0xFF;
+
+ /* Set both global(bits 56..63) and local(bits 48..55) PStates */
+ val = val | (pstate_ul << 56) | (pstate_ul << 48);
+
+ pr_debug("Setting cpu %d pmcr to %016lX\n",
+ raw_smp_processor_id(), val);
+ set_pmspr(SPRN_PMCR, val);
+}
+
+/*
+ * powernv_cpufreq_target_index: Sets the frequency corresponding to
+ * the cpufreq table entry indexed by new_index on the cpus in the
+ * mask policy->cpus
+ */
+static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
+ unsigned int new_index)
+{
+ struct powernv_smp_call_data freq_data;
+
+ freq_data.pstate_id = powernv_pstate_ids[new_index];
+
+ /*
+ * Use smp_call_function to send IPI and execute the
+ * mtspr on target CPU. We could do that without IPI
+ * if current CPU is within policy->cpus (core)
+ */
+ smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
+
+ return 0;
+}
+
+static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ int base, i;
+
+ base = cpu_first_thread_sibling(policy->cpu);
+
+ for (i = 0; i < threads_per_core; i++)
+ cpumask_set_cpu(base + i, policy->cpus);
+
+ return cpufreq_table_validate_and_show(policy, powernv_freqs);
+}
+
+static struct cpufreq_driver powernv_cpufreq_driver = {
+ .name = "powernv-cpufreq",
+ .flags = CPUFREQ_CONST_LOOPS,
+ .init = powernv_cpufreq_cpu_init,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = powernv_cpufreq_target_index,
+ .get = powernv_cpufreq_get,
+ .attr = powernv_cpu_freq_attr,
+};
+
+static int __init powernv_cpufreq_init(void)
+{
+ int rc = 0;
+
+ /* Discover pstates from device tree and init */
+ rc = init_powernv_pstates();
+ if (rc) {
+ pr_info("powernv-cpufreq disabled. System does not support PState control\n");
+ return rc;
+ }
+
+ return cpufreq_register_driver(&powernv_cpufreq_driver);
+}
+module_init(powernv_cpufreq_init);
+
+static void __exit powernv_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&powernv_cpufreq_driver);
+}
+module_exit(powernv_cpufreq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>");
--
1.8.3.1
^ permalink raw reply related
* [PATCH v5 1/3] powernv, cpufreq: Select CPUFreq related Kconfig options for powernv
From: Gautham R. Shenoy @ 2014-03-28 20:11 UTC (permalink / raw)
To: Viresh Kumar, rjw, Benjamin Herrenschmidt
Cc: Gautham R. Shenoy, Linux PM list, linux-kernel, cpufreq,
linuxppc-dev, Anton Blanchard, srivatsa.bhat
In-Reply-To: <1396037484-23907-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
Enable CPUFreq for PowerNV. Select "performance", "powersave",
"userspace" and "ondemand" governors. Choose "ondemand" to be the
default governor.
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
arch/powerpc/configs/pseries_defconfig | 1 +
arch/powerpc/configs/pseries_le_defconfig | 1 +
arch/powerpc/platforms/powernv/Kconfig | 6 ++++++
3 files changed, 8 insertions(+)
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 9ea8342b..a905063 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -306,3 +306,4 @@ CONFIG_KVM_BOOK3S_64=m
CONFIG_KVM_BOOK3S_64_HV=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
diff --git a/arch/powerpc/configs/pseries_le_defconfig b/arch/powerpc/configs/pseries_le_defconfig
index 3c84f9d..58e3dbf 100644
--- a/arch/powerpc/configs/pseries_le_defconfig
+++ b/arch/powerpc/configs/pseries_le_defconfig
@@ -301,3 +301,4 @@ CONFIG_CRYPTO_LZO=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_NX=y
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 895e8a2..c252ee9 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -11,6 +11,12 @@ config PPC_POWERNV
select PPC_UDBG_16550
select PPC_SCOM
select ARCH_RANDOM
+ select CPU_FREQ
+ select CPU_FREQ_GOV_PERFORMANCE
+ select CPU_FREQ_GOV_POWERSAVE
+ select CPU_FREQ_GOV_USERSPACE
+ select CPU_FREQ_GOV_ONDEMAND
+ select CPU_FREQ_GOV_CONSERVATIVE
default y
config PPC_POWERNV_RTAS
--
1.8.3.1
^ permalink raw reply related
* [PATCH v5 3/3] powernv, cpufreq: Use cpufreq_frequency_table.driver_data to store pstate ids
From: Gautham R. Shenoy @ 2014-03-28 20:11 UTC (permalink / raw)
To: Viresh Kumar, rjw, Benjamin Herrenschmidt
Cc: Gautham R. Shenoy, Linux PM list, linux-kernel, cpufreq,
linuxppc-dev, Anton Blanchard, srivatsa.bhat
In-Reply-To: <1396037484-23907-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
The .driver_data field in the cpufreq_frequency_table was supposed to
be private to the drivers. However at some later point, it was being
used to indicate if the particular frequency in the table is the
BOOST_FREQUENCY. After patches [1] and [2], the .driver_data is once
again private to the driver. Thus we can safely use
cpufreq_frequency_table.driver_data to store pstate_ids instead of
having to maintain a separate array powernv_pstate_ids[] for this
purpose.
[1]:
Subject: cpufreq: don't print value of .driver_data from core
From : Viresh Kumar <viresh.kumar@ linaro.org>
url : http://marc.info/?l=linux-pm&m=139601421504709&w=2
[2]:
Subject: cpufreq: create another field .flags in cpufreq_frequency_table
From : Viresh Kumar <viresh.kumar@linaro.org>
url : http://marc.info/?l=linux-pm&m=139601416804702&w=2
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpufreq/powernv-cpufreq.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index e1e5197..9edccc6 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -33,7 +33,6 @@
#define POWERNV_MAX_PSTATES 256
static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
-static int powernv_pstate_ids[POWERNV_MAX_PSTATES+1];
/*
* Note: The set of pstates consists of contiguous integers, the
@@ -112,7 +111,7 @@ static int init_powernv_pstates(void)
pr_debug("PState id %d freq %d MHz\n", id, freq);
powernv_freqs[i].frequency = freq * 1000; /* kHz */
- powernv_pstate_ids[i] = id;
+ powernv_freqs[i].driver_data = id;
}
/* End of list marker entry */
powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
@@ -283,7 +282,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
{
struct powernv_smp_call_data freq_data;
- freq_data.pstate_id = powernv_pstate_ids[new_index];
+ freq_data.pstate_id = powernv_freqs[new_index].driver_data;
/*
* Use smp_call_function to send IPI and execute the
--
1.8.3.1
^ 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