* 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
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Benjamin Herrenschmidt @ 2014-03-28 21:25 UTC (permalink / raw)
To: Dongsheng Wang
Cc: James Hogan, Andrew Morton, David S. Miller, Peter Zijlstra,
fweisbec, Helge Deller, linuxppc-dev, Heiko Carstens,
linux-kernel, Paul Mackerras, James E.J. Bottomley,
Linus Torvalds, jason.jin, H. Peter Anvin, scottwood,
Thomas Gleixner, Ingo Molnar, Martin Schwidefsky
In-Reply-To: <1395992312-23035-1-git-send-email-dongsheng.wang@freescale.com>
On Fri, 2014-03-28 at 15:38 +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.
Yes, an interrupt can potentially nest but we should be near the top of
the stack at that point, as the comment says in softirq.c, it should
be fine. And your backtrace doesn't seem to indicate a major overflow.
The code in do_IRQ() will make sure we don't switch stack again if
we were already on either hard or softirq stack.
I need a better analysis of your problem. Is that really a stack
overflow ? Or is it a false positive due to a bug in the overflow
detection ?
I moved around the code that updates KSP_LIMIT in 32-bit to asm in
misc_32.S a while ago since we don't do that on 64-bit, maybe we are
getting it wrong...
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Benjamin Herrenschmidt @ 2014-03-28 21:27 UTC (permalink / raw)
To: Kevin Hao
Cc: Ingo Molnar, James Hogan, jason.jin, Peter Zijlstra, fweisbec,
Helge Deller, linuxppc-dev, Heiko Carstens, Dongsheng Wang,
Paul Mackerras, linux-kernel, Martin Schwidefsky, Thomas Gleixner,
James E.J. Bottomley, H. Peter Anvin, scottwood, Andrew Morton,
Linus Torvalds, David S. Miller
In-Reply-To: <20140328081827.GB2176@pek-khao-d1.corp.ad.wrs.com>
On Fri, 2014-03-28 at 16:18 +0800, Kevin Hao wrote:
> powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack
>
Kevin. It looks like it was applied to 3.14 and sent to 3.12 stable but
not 3.13 ... can you fix that up ?
Cheers,
Ben.
> 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
^ permalink raw reply
* Re: [RESEND][PATCH 0/2] Cleanup asm/scatterlist.h
From: Andrew Morton @ 2014-03-28 22:14 UTC (permalink / raw)
To: Laura Abbott
Cc: linux-ia64, Heiko Carstens, David Howells, Paul Mackerras,
H. Peter Anvin, sparclinux, Lennox Wu, Chen Liqin, Jesper Nilsson,
linux-am33-list, Russell King, linux-scsi, Hirokazu Takata, x86,
Ingo Molnar, Fenghua Yu, linux-s390, microblaze-uclinux,
Mikael Starvik, linux-m32r, Thomas Gleixner, linux-arm-kernel,
Michal Simek, Tony Luck, linux-cris-kernel, linux-kernel,
James E.J. Bottomley, linux-alpha, Martin Schwidefsky, linux390,
Koichi Yasutake, linuxppc-dev, David S. Miller
In-Reply-To: <1395512032-20575-1-git-send-email-lauraa@codeaurora.org>
On Sat, 22 Mar 2014 11:13:50 -0700 Laura Abbott <lauraa@codeaurora.org> wrote:
> I haven't gotten many responses so I'm going to try sending again
> (this time with a cover letter which I probably should have done in
> the first place...)
>
> ARCH_HAS_SG_CHAIN is currently defined as needed in asm/scatterlist.h.
> It was suggested[1] that this should probably be a proper Kconfig.
> At the same time, we can clean up most of the asm/scatterlist.h files
> to reduce redundancy. This makes parisc the only architecture that still
> has an asm/scatterlist.h file due to the #define sg_virt_addr (which
> could probably be cleaned up further still)
>
> Andrew, once we get a few more Acked-bys can we take this through your tree
> as suggested by Will?
Grabbed. It's super late for 3.15-rc1 and I'm thinking of merging this
in 3.16-rc1. Or I can maybe squeeze it into 3.15-rc2 is there's an
immediatish need for it?
^ permalink raw reply
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Kevin Hao @ 2014-03-29 1:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Ingo Molnar, James Hogan, jason.jin, Peter Zijlstra, fweisbec,
Helge Deller, linuxppc-dev, Heiko Carstens, Dongsheng Wang,
Paul Mackerras, linux-kernel, Martin Schwidefsky, Thomas Gleixner,
James E.J. Bottomley, H. Peter Anvin, scottwood, Andrew Morton,
Linus Torvalds, David S. Miller
In-Reply-To: <1396042027.11529.24.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 517 bytes --]
On Sat, Mar 29, 2014 at 08:27:07AM +1100, Benjamin Herrenschmidt wrote:
> On Fri, 2014-03-28 at 16:18 +0800, Kevin Hao wrote:
>
> > powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack
> >
>
> Kevin. It looks like it was applied to 3.14 and sent to 3.12 stable but
> not 3.13 ... can you fix that up ?
It was already merged into 3.13 stable since 3.13.6:
https://lkml.org/lkml/2014/3/4/787
I guess that Dongsheng didn't use the latest 3.13 stable tree.
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* [PATCH v2] powerpc/book3s: Recover from MC in opal on SCOM read via MMIO.
From: Mahesh J Salgaonkar @ 2014-03-29 4:57 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras, Anton Blanchard
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Detect and recover from machine check when inside opal on a special
scom load instructions. On specific SCOM read via MMIO we may get a machine
check exception with SRR0 pointing inside opal. To recover from MC
in this scenario, get a recovery instruction address and return to it from
MC.
OPAL will export the machine check recoverable ranges through
device tree node mcheck-recoverable-ranges under ibm,opal:
# hexdump /proc/device-tree/ibm,opal/mcheck-recoverable-ranges
0000000 0000 0000 3000 2804 0000 000c 0000 0000
0000010 3000 2814 0000 0000 3000 27f0 0000 000c
0000020 0000 0000 3000 2814 xxxx xxxx xxxx xxxx
0000030 llll llll yyyy yyyy yyyy yyyy
...
...
#
where:
xxxx xxxx xxxx xxxx = Starting instruction address
llll llll = Length of the address range.
yyyy yyyy yyyy yyyy = recovery address
Each recoverable address range entry is (start address, len,
recovery address), 2 cells each for start and recovery address, 1 cell for
len, totalling 5 cells per entry. During kernel boot time, build up the
recovery table with the list of recovery ranges from device-tree node which
will be used during machine check exception to recover from MMIO SCOM UE.
Changes in V2:
- Allocate mc_recoverable_range buffer based on number of entries
of recoverable ranges instead of device property size. Without this
change we end up allocating less memory and run into buffer corruption
issue.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/machdep.h | 3 +
arch/powerpc/include/asm/mce.h | 3 +
arch/powerpc/include/asm/opal.h | 3 +
arch/powerpc/kernel/mce.c | 4 +
arch/powerpc/kernel/mce_power.c | 37 +++++++++--
arch/powerpc/kernel/prom.c | 5 +
arch/powerpc/platforms/powernv/opal.c | 112 +++++++++++++++++++++++++++++++-
arch/powerpc/platforms/powernv/setup.c | 1
8 files changed, 158 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index ad3025d..4da6574 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -170,6 +170,9 @@ struct machdep_calls {
int (*system_reset_exception)(struct pt_regs *regs);
int (*machine_check_exception)(struct pt_regs *regs);
+ /* Called during machine check exception to retrive fixup address. */
+ bool (*mce_check_early_recovery)(struct pt_regs *regs);
+
/* Motherboard/chipset features. This is a kind of general purpose
* hook used to control some machine specific features (like reset
* lines, chip power control, etc...).
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
index 8e99edf..f97d8cb 100644
--- a/arch/powerpc/include/asm/mce.h
+++ b/arch/powerpc/include/asm/mce.h
@@ -187,7 +187,8 @@ struct mce_error_info {
#define MCE_EVENT_DONTRELEASE false
extern void save_mce_event(struct pt_regs *regs, long handled,
- struct mce_error_info *mce_err, uint64_t addr);
+ struct mce_error_info *mce_err, uint64_t nip,
+ uint64_t addr);
extern int get_mce_event(struct machine_check_event *mce, bool release);
extern void release_mce_event(void);
extern void machine_check_queue_event(void);
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index ed82142..ad67c40 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -833,6 +833,8 @@ int64_t opal_sync_host_reboot(void);
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+extern int early_init_dt_scan_recoverable_ranges(unsigned long node,
+ const char *uname, int depth, void *data);
extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
@@ -863,6 +865,7 @@ extern void opal_nvram_init(void);
extern void opal_flash_init(void);
extern int opal_machine_check(struct pt_regs *regs);
+extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
extern void opal_shutdown(void);
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index cadef7e..a7fd4cb 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -70,7 +70,7 @@ static void mce_set_error_info(struct machine_check_event *mce,
*/
void save_mce_event(struct pt_regs *regs, long handled,
struct mce_error_info *mce_err,
- uint64_t addr)
+ uint64_t nip, uint64_t addr)
{
uint64_t srr1;
int index = __get_cpu_var(mce_nest_count)++;
@@ -86,7 +86,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
/* Populate generic machine check info */
mce->version = MCE_V1;
- mce->srr0 = regs->nip;
+ mce->srr0 = nip;
mce->srr1 = regs->msr;
mce->gpr3 = regs->gpr[3];
mce->in_use = 1;
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 27c93f4..aa9aff3 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -26,6 +26,7 @@
#include <linux/ptrace.h>
#include <asm/mmu.h>
#include <asm/mce.h>
+#include <asm/machdep.h>
/* flush SLBs and reload */
static void flush_and_reload_slb(void)
@@ -197,13 +198,32 @@ static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
}
}
+static long mce_handle_ue_error(struct pt_regs *regs)
+{
+ long handled = 0;
+
+ /*
+ * On specific SCOM read via MMIO we may get a machine check
+ * exception with SRR0 pointing inside opal. If that is the
+ * case OPAL may have recovery address to re-read SCOM data in
+ * different way and hence we can recover from this MC.
+ */
+
+ if (ppc_md.mce_check_early_recovery) {
+ if (ppc_md.mce_check_early_recovery(regs))
+ handled = 1;
+ }
+ return handled;
+}
+
long __machine_check_early_realmode_p7(struct pt_regs *regs)
{
- uint64_t srr1, addr;
+ uint64_t srr1, nip, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
+ nip = regs->nip;
/*
* Handle memory errors depending whether this was a load/store or
@@ -221,7 +241,11 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
addr = regs->nip;
}
- save_mce_event(regs, handled, &mce_error_info, addr);
+ /* Handle UE error. */
+ if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
+ handled = mce_handle_ue_error(regs);
+
+ save_mce_event(regs, handled, &mce_error_info, nip, addr);
return handled;
}
@@ -263,11 +287,12 @@ static long mce_handle_derror_p8(uint64_t dsisr)
long __machine_check_early_realmode_p8(struct pt_regs *regs)
{
- uint64_t srr1, addr;
+ uint64_t srr1, nip, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
+ nip = regs->nip;
if (P7_SRR1_MC_LOADSTORE(srr1)) {
handled = mce_handle_derror_p8(regs->dsisr);
@@ -279,6 +304,10 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
addr = regs->nip;
}
- save_mce_event(regs, handled, &mce_error_info, addr);
+ /* Handle UE error. */
+ if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
+ handled = mce_handle_ue_error(regs);
+
+ save_mce_event(regs, handled, &mce_error_info, nip, addr);
return handled;
}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f58c0d3..d711b7e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -752,6 +752,11 @@ void __init early_init_devtree(void *params)
spinning_secondaries = boot_cpu_count - 1;
#endif
+#ifdef CONFIG_PPC_POWERNV
+ /* Scan and build the list of machine check recoverable ranges */
+ of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
+#endif
+
DBG(" <- early_init_devtree()\n");
}
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 65499ad..f52762b 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -21,6 +21,7 @@
#include <linux/sched.h>
#include <linux/kobject.h>
#include <linux/delay.h>
+#include <linux/memblock.h>
#include <asm/opal.h>
#include <asm/firmware.h>
#include <asm/mce.h>
@@ -33,8 +34,18 @@ struct kobject *opal_kobj;
struct opal {
u64 base;
u64 entry;
+ u64 size;
} opal;
+struct mcheck_recoverable_range {
+ u64 start_addr;
+ u64 end_addr;
+ u64 recover_addr;
+};
+
+static struct mcheck_recoverable_range *mc_recoverable_range;
+static int mc_recoverable_range_len;
+
static struct device_node *opal_node;
static DEFINE_SPINLOCK(opal_write_lock);
extern u64 opal_mc_secondary_handler[];
@@ -49,25 +60,29 @@ static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
- const void *basep, *entryp;
- unsigned long basesz, entrysz;
+ const void *basep, *entryp, *sizep;
+ unsigned long basesz, entrysz, runtimesz;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+ sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz);
- if (!basep || !entryp)
+ if (!basep || !entryp || !sizep)
return 1;
opal.base = of_read_number(basep, basesz/4);
opal.entry = of_read_number(entryp, entrysz/4);
+ opal.size = of_read_number(sizep, runtimesz/4);
pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
opal.base, basep, basesz);
pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
opal.entry, entryp, entrysz);
+ pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%ld)\n",
+ opal.size, sizep, runtimesz);
powerpc_firmware_features |= FW_FEATURE_OPAL;
if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
@@ -84,6 +99,65 @@ int __init early_init_dt_scan_opal(unsigned long node,
return 1;
}
+int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ unsigned long i, psize, size;
+ const __be32 *prop;
+
+ if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+ return 0;
+
+ prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
+
+ if (!prop)
+ return 1;
+
+ pr_debug("Found machine check recoverable ranges.\n");
+
+ /*
+ * Calculate number of available entries.
+ *
+ * Each recoverable address range entry is (start address, len,
+ * recovery address), 2 cells each for start and recovery address,
+ * 1 cell for len, totalling 5 cells per entry.
+ */
+ mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
+
+ /* Sanity check */
+ if (!mc_recoverable_range_len)
+ return 1;
+
+ /* Size required to hold all the entries. */
+ size = mc_recoverable_range_len *
+ sizeof(struct mcheck_recoverable_range);
+
+ /*
+ * Allocate a buffer to hold the MC recoverable ranges. We would be
+ * accessing them in real mode, hence it needs to be within
+ * RMO region.
+ */
+ mc_recoverable_range = __va(memblock_alloc_base(size, __alignof__(u64),
+ ppc64_rma_size));
+ memset(mc_recoverable_range, 0, size);
+
+ for (i = 0; i < mc_recoverable_range_len; i++) {
+ mc_recoverable_range[i].start_addr =
+ of_read_number(prop + (i * 5) + 0, 2);
+ mc_recoverable_range[i].end_addr =
+ mc_recoverable_range[i].start_addr +
+ of_read_number(prop + (i * 5) + 2, 1);
+ mc_recoverable_range[i].recover_addr =
+ of_read_number(prop + (i * 5) + 3, 2);
+
+ pr_debug("Machine check recoverable range: %llx..%llx: %llx\n",
+ mc_recoverable_range[i].start_addr,
+ mc_recoverable_range[i].end_addr,
+ mc_recoverable_range[i].recover_addr);
+ }
+ return 1;
+}
+
static int __init opal_register_exception_handlers(void)
{
#ifdef __BIG_ENDIAN__
@@ -401,6 +475,38 @@ int opal_machine_check(struct pt_regs *regs)
return 0;
}
+static uint64_t find_recovery_address(uint64_t nip)
+{
+ int i;
+
+ for (i = 0; i < mc_recoverable_range_len; i++)
+ if ((nip >= mc_recoverable_range[i].start_addr) &&
+ (nip < mc_recoverable_range[i].end_addr))
+ return mc_recoverable_range[i].recover_addr;
+ return 0;
+}
+
+bool opal_mce_check_early_recovery(struct pt_regs *regs)
+{
+ uint64_t recover_addr = 0;
+
+ if (!opal.base || !opal.size)
+ goto out;
+
+ if ((regs->nip >= opal.base) &&
+ (regs->nip <= (opal.base + opal.size)))
+ recover_addr = find_recovery_address(regs->nip);
+
+ /*
+ * Setup regs->nip to rfi into fixup address.
+ */
+ if (recover_addr)
+ regs->nip = recover_addr;
+
+out:
+ return !!recover_addr;
+}
+
static irqreturn_t opal_interrupt(int irq, void *data)
{
__be64 events;
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 110f4fb..2d80845 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -188,6 +188,7 @@ static void __init pnv_setup_machdep_opal(void)
ppc_md.power_off = pnv_power_off;
ppc_md.halt = pnv_halt;
ppc_md.machine_check_exception = opal_machine_check;
+ ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
}
#ifdef CONFIG_PPC_POWERNV_RTAS
^ 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