* [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked()
@ 2015-11-24 11:26 Michael Ellerman
2015-11-24 11:26 ` [PATCH 2/5] powerpc/xmon: Use rtas_call_unlocked() in xmon Michael Ellerman
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:26 UTC (permalink / raw)
To: linuxppc-dev
Most users of RTAS (Run-Time Abstraction Services) use rtas_call(),
which deals with locking as well as endian handling.
However we have two users outside of rtas.c that can't use rtas_call()
because they have different locking requirements.
The hotplug CPU code can't take the RTAS lock because the CPU would go
offline with the lock held and no other CPUs would be able to call RTAS
until the CPU came back online.
The xmon code doesn't want to take the lock because it would risk dead
locking when we are trying to recover from a crash.
Both sites required multiple patches when we added little endian
support, proving that programmers can't do endian right.
Although that ship has sailed, we can still clean the code up by
providing an unlocked version of rtas_call() which avoids the need to
open code the logic elsewhere.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
commit 98bd678fc89575d0f4026a3ced3de19d90d1fe72
Author: Michael Ellerman <mpe@ellerman.id.au>
Date: Fri May 15 16:40:48 2015 +1000
powerpc/rtas: Add rtas_call_unlocked(), make enter_rtas() private
Most users of RTAS (Run-Time Abstraction Services) use rtas_call(),
which deals with locking as well as endian handling.
However we have two users outside of rtas.c that can't use rtas_call()
because they have different locking requirements.
The hotplug CPU code can't take the RTAS lock because the CPU would go
offline with the lock held and no other CPUs would be able to call RTAS
until the CPU came back online.
The xmon code doesn't want to take the lock because it would risk dead
locking when we are trying to recover from a crash.
Both sites required multiple patches when we added little endian
support, proving that programmers can't do endian right.
Although that ship has sailed, we can still clean the code up by
providing an unlocked version of rtas_call() which avoids the need to
open code the logic elsewhere.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index b77ef369c0f0..51400baa8d48 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -334,10 +334,11 @@ extern void (*rtas_flash_term_hook)(int);
extern struct rtas_t rtas;
-extern void enter_rtas(unsigned long);
extern int rtas_token(const char *service);
extern int rtas_service_present(const char *service);
extern int rtas_call(int token, int, int, int *, ...);
+void rtas_call_unlocked(struct rtas_args *args, int token, int nargs,
+ int nret, ...);
extern void rtas_restart(char *cmd);
extern void rtas_power_off(void);
extern void rtas_halt(void);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 5a753fae8265..dda465b62e9b 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -44,6 +44,9 @@
#include <asm/mmu.h>
#include <asm/topology.h>
+/* This is here deliberately so it's only used in this file */
+void enter_rtas(unsigned long);
+
struct rtas_t rtas = {
.lock = __ARCH_SPIN_LOCK_UNLOCKED
};
@@ -418,6 +421,36 @@ static char *__fetch_rtas_last_error(char *altbuf)
#define get_errorlog_buffer() NULL
#endif
+
+static void
+va_rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret,
+ va_list list)
+{
+ int i;
+
+ args->token = cpu_to_be32(token);
+ args->nargs = cpu_to_be32(nargs);
+ args->nret = cpu_to_be32(nret);
+ args->rets = &(args->args[nargs]);
+
+ for (i = 0; i < nargs; ++i)
+ args->args[i] = cpu_to_be32(va_arg(list, __u32));
+
+ for (i = 0; i < nret; ++i)
+ args->rets[i] = 0;
+
+ enter_rtas(__pa(args));
+}
+
+void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, ...)
+{
+ va_list list;
+
+ va_start(list, nret);
+ va_rtas_call_unlocked(args, token, nargs, nret, list);
+ va_end(list);
+}
+
int rtas_call(int token, int nargs, int nret, int *outputs, ...)
{
va_list list;
@@ -431,22 +464,14 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
return -1;
s = lock_rtas();
+
+ /* We use the global rtas args buffer */
rtas_args = &rtas.args;
- rtas_args->token = cpu_to_be32(token);
- rtas_args->nargs = cpu_to_be32(nargs);
- rtas_args->nret = cpu_to_be32(nret);
- rtas_args->rets = &(rtas_args->args[nargs]);
va_start(list, outputs);
- for (i = 0; i < nargs; ++i)
- rtas_args->args[i] = cpu_to_be32(va_arg(list, __u32));
+ va_rtas_call_unlocked(rtas_args, token, nargs, nret, list);
va_end(list);
- for (i = 0; i < nret; ++i)
- rtas_args->rets[i] = 0;
-
- enter_rtas(__pa(rtas_args));
-
/* A -1 return code indicates that the last command couldn't
be completed due to a hardware error. */
if (be32_to_cpu(rtas_args->rets[0]) == -1)
---
arch/powerpc/include/asm/rtas.h | 2 ++
arch/powerpc/kernel/rtas.c | 44 ++++++++++++++++++++++++++++++-----------
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index b77ef369c0f0..6db1d6977a0d 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -338,6 +338,8 @@ extern void enter_rtas(unsigned long);
extern int rtas_token(const char *service);
extern int rtas_service_present(const char *service);
extern int rtas_call(int token, int, int, int *, ...);
+void rtas_call_unlocked(struct rtas_args *args, int token, int nargs,
+ int nret, ...);
extern void rtas_restart(char *cmd);
extern void rtas_power_off(void);
extern void rtas_halt(void);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 5a753fae8265..fcf2d653a6fe 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -418,6 +418,36 @@ static char *__fetch_rtas_last_error(char *altbuf)
#define get_errorlog_buffer() NULL
#endif
+
+static void
+va_rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret,
+ va_list list)
+{
+ int i;
+
+ args->token = cpu_to_be32(token);
+ args->nargs = cpu_to_be32(nargs);
+ args->nret = cpu_to_be32(nret);
+ args->rets = &(args->args[nargs]);
+
+ for (i = 0; i < nargs; ++i)
+ args->args[i] = cpu_to_be32(va_arg(list, __u32));
+
+ for (i = 0; i < nret; ++i)
+ args->rets[i] = 0;
+
+ enter_rtas(__pa(args));
+}
+
+void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, ...)
+{
+ va_list list;
+
+ va_start(list, nret);
+ va_rtas_call_unlocked(args, token, nargs, nret, list);
+ va_end(list);
+}
+
int rtas_call(int token, int nargs, int nret, int *outputs, ...)
{
va_list list;
@@ -431,22 +461,14 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
return -1;
s = lock_rtas();
+
+ /* We use the global rtas args buffer */
rtas_args = &rtas.args;
- rtas_args->token = cpu_to_be32(token);
- rtas_args->nargs = cpu_to_be32(nargs);
- rtas_args->nret = cpu_to_be32(nret);
- rtas_args->rets = &(rtas_args->args[nargs]);
va_start(list, outputs);
- for (i = 0; i < nargs; ++i)
- rtas_args->args[i] = cpu_to_be32(va_arg(list, __u32));
+ va_rtas_call_unlocked(rtas_args, token, nargs, nret, list);
va_end(list);
- for (i = 0; i < nret; ++i)
- rtas_args->rets[i] = 0;
-
- enter_rtas(__pa(rtas_args));
-
/* A -1 return code indicates that the last command couldn't
be completed due to a hardware error. */
if (be32_to_cpu(rtas_args->rets[0]) == -1)
--
2.5.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] powerpc/xmon: Use rtas_call_unlocked() in xmon
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
@ 2015-11-24 11:26 ` Michael Ellerman
2015-11-24 11:26 ` [PATCH 3/5] powerpc/pseries: Use rtas_call_unlocked() in pseries hotplug Michael Ellerman
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:26 UTC (permalink / raw)
To: linuxppc-dev
Avoid open coding the logic by using rtas_call_unlocked().
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/xmon/xmon.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 786bf01691c9..ff31e70b81e8 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -320,6 +320,7 @@ static inline void disable_surveillance(void)
#ifdef CONFIG_PPC_PSERIES
/* Since this can't be a module, args should end up below 4GB. */
static struct rtas_args args;
+ int token;
/*
* At this point we have got all the cpus we can into
@@ -328,17 +329,12 @@ static inline void disable_surveillance(void)
* If we did try to take rtas.lock there would be a
* real possibility of deadlock.
*/
- args.token = rtas_token("set-indicator");
- if (args.token == RTAS_UNKNOWN_SERVICE)
+ token = rtas_token("set-indicator");
+ if (token == RTAS_UNKNOWN_SERVICE)
return;
- args.token = cpu_to_be32(args.token);
- args.nargs = cpu_to_be32(3);
- args.nret = cpu_to_be32(1);
- args.rets = &args.args[3];
- args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN);
- args.args[1] = 0;
- args.args[2] = 0;
- enter_rtas(__pa(&args));
+
+ rtas_call_unlocked(&args, token, 3, 1, NULL, SURVEILLANCE_TOKEN, 0, 0);
+
#endif /* CONFIG_PPC_PSERIES */
}
--
2.5.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] powerpc/pseries: Use rtas_call_unlocked() in pseries hotplug
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
2015-11-24 11:26 ` [PATCH 2/5] powerpc/xmon: Use rtas_call_unlocked() in xmon Michael Ellerman
@ 2015-11-24 11:26 ` Michael Ellerman
2015-11-24 11:26 ` [PATCH 4/5] powerpc/rtas: Use rtas_call_unlocked() in call_rtas_display_status() Michael Ellerman
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:26 UTC (permalink / raw)
To: linuxppc-dev
Avoid open coding the logic by using rtas_call_unlocked().
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/platforms/pseries/hotplug-cpu.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 62475440fd45..86d2ecacb237 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -88,13 +88,7 @@ void set_default_offline_state(int cpu)
static void rtas_stop_self(void)
{
- static struct rtas_args args = {
- .nargs = 0,
- .nret = cpu_to_be32(1),
- .rets = &args.args[0],
- };
-
- args.token = cpu_to_be32(rtas_stop_self_token);
+ static struct rtas_args args;
local_irq_disable();
@@ -102,7 +96,8 @@ static void rtas_stop_self(void)
printk("cpu %u (hwid %u) Ready to die...\n",
smp_processor_id(), hard_smp_processor_id());
- enter_rtas(__pa(&args));
+
+ rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL);
panic("Alas, I survived.\n");
}
--
2.5.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] powerpc/rtas: Use rtas_call_unlocked() in call_rtas_display_status()
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
2015-11-24 11:26 ` [PATCH 2/5] powerpc/xmon: Use rtas_call_unlocked() in xmon Michael Ellerman
2015-11-24 11:26 ` [PATCH 3/5] powerpc/pseries: Use rtas_call_unlocked() in pseries hotplug Michael Ellerman
@ 2015-11-24 11:26 ` Michael Ellerman
2015-11-24 11:26 ` [PATCH 5/5] powerpc/rtas: Make enter_rtas() private Michael Ellerman
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:26 UTC (permalink / raw)
To: linuxppc-dev
Although call_rtas_display_status() does actually want to use the
regular RTAS locking, it doesn't want the extra logic that is in
rtas_call(), so currently it open codes the logic.
Instead we can use rtas_call_unlocked(), after taking the RTAS lock.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/rtas.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index fcf2d653a6fe..f4fa137292c4 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -93,21 +93,13 @@ static void unlock_rtas(unsigned long flags)
*/
static void call_rtas_display_status(unsigned char c)
{
- struct rtas_args *args = &rtas.args;
unsigned long s;
if (!rtas.base)
return;
- s = lock_rtas();
-
- args->token = cpu_to_be32(10);
- args->nargs = cpu_to_be32(1);
- args->nret = cpu_to_be32(1);
- args->rets = &(args->args[1]);
- args->args[0] = cpu_to_be32(c);
-
- enter_rtas(__pa(args));
+ s = lock_rtas();
+ rtas_call_unlocked(&rtas.args, 10, 1, 1, NULL, c);
unlock_rtas(s);
}
--
2.5.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] powerpc/rtas: Make enter_rtas() private
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
` (2 preceding siblings ...)
2015-11-24 11:26 ` [PATCH 4/5] powerpc/rtas: Use rtas_call_unlocked() in call_rtas_display_status() Michael Ellerman
@ 2015-11-24 11:26 ` Michael Ellerman
2015-11-24 11:58 ` [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
2015-12-17 11:57 ` [1/5] " Michael Ellerman
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:26 UTC (permalink / raw)
To: linuxppc-dev
There are no longer any users of enter_rtas() outside of rtas.c, so make
it "private", by moving the declaration inside rtas.c. Hopefully this
will encourage people to use one of the wrappers which takes the sharp
edges off the RTAS calling sequence.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/rtas.h | 1 -
arch/powerpc/kernel/rtas.c | 3 +++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 6db1d6977a0d..51400baa8d48 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -334,7 +334,6 @@ extern void (*rtas_flash_term_hook)(int);
extern struct rtas_t rtas;
-extern void enter_rtas(unsigned long);
extern int rtas_token(const char *service);
extern int rtas_service_present(const char *service);
extern int rtas_call(int token, int, int, int *, ...);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f4fa137292c4..28736ff27fea 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -44,6 +44,9 @@
#include <asm/mmu.h>
#include <asm/topology.h>
+/* This is here deliberately so it's only used in this file */
+void enter_rtas(unsigned long);
+
struct rtas_t rtas = {
.lock = __ARCH_SPIN_LOCK_UNLOCKED
};
--
2.5.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked()
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
` (3 preceding siblings ...)
2015-11-24 11:26 ` [PATCH 5/5] powerpc/rtas: Make enter_rtas() private Michael Ellerman
@ 2015-11-24 11:58 ` Michael Ellerman
2015-12-17 11:57 ` [1/5] " Michael Ellerman
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-11-24 11:58 UTC (permalink / raw)
To: linuxppc-dev
On Tue, 2015-11-24 at 22:26 +1100, Michael Ellerman wrote:
> Most users of RTAS (Run-Time Abstraction Services) use rtas_call(),
> which deals with locking as well as endian handling.
>
> However we have two users outside of rtas.c that can't use rtas_call()
> because they have different locking requirements.
>
> The hotplug CPU code can't take the RTAS lock because the CPU would go
> offline with the lock held and no other CPUs would be able to call RTAS
> until the CPU came back online.
>
> The xmon code doesn't want to take the lock because it would risk dead
> locking when we are trying to recover from a crash.
>
> Both sites required multiple patches when we added little endian
> support, proving that programmers can't do endian right.
>
> Although that ship has sailed, we can still clean the code up by
> providing an unlocked version of rtas_call() which avoids the need to
> open code the logic elsewhere.
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
>
> commit 98bd678fc89575d0f4026a3ced3de19d90d1fe72
> Author: Michael Ellerman <mpe@ellerman.id.au>
> Date: Fri May 15 16:40:48 2015 +1000
>
> powerpc/rtas: Add rtas_call_unlocked(), make enter_rtas() private
... wut.
Obviously I fubared the commit message a bit here while rebasing.
cheers
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [1/5] powerpc/rtas: Add rtas_call_unlocked()
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
` (4 preceding siblings ...)
2015-11-24 11:58 ` [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
@ 2015-12-17 11:57 ` Michael Ellerman
5 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2015-12-17 11:57 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev
On Tue, 2015-24-11 at 11:26:08 UTC, Michael Ellerman wrote:
> Most users of RTAS (Run-Time Abstraction Services) use rtas_call(),
> which deals with locking as well as endian handling.
>
> However we have two users outside of rtas.c that can't use rtas_call()
> because they have different locking requirements.
>
> The hotplug CPU code can't take the RTAS lock because the CPU would go
> offline with the lock held and no other CPUs would be able to call RTAS
> until the CPU came back online.
>
> The xmon code doesn't want to take the lock because it would risk dead
> locking when we are trying to recover from a crash.
>
> Both sites required multiple patches when we added little endian
> support, proving that programmers can't do endian right.
>
> Although that ship has sailed, we can still clean the code up by
> providing an unlocked version of rtas_call() which avoids the need to
> open code the logic elsewhere.
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Series applied to powerpc next.
https://git.kernel.org/powerpc/c/209eb4e5cbaba53ab555f3e7b4
cheers
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-12-17 11:57 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-24 11:26 [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
2015-11-24 11:26 ` [PATCH 2/5] powerpc/xmon: Use rtas_call_unlocked() in xmon Michael Ellerman
2015-11-24 11:26 ` [PATCH 3/5] powerpc/pseries: Use rtas_call_unlocked() in pseries hotplug Michael Ellerman
2015-11-24 11:26 ` [PATCH 4/5] powerpc/rtas: Use rtas_call_unlocked() in call_rtas_display_status() Michael Ellerman
2015-11-24 11:26 ` [PATCH 5/5] powerpc/rtas: Make enter_rtas() private Michael Ellerman
2015-11-24 11:58 ` [PATCH 1/5] powerpc/rtas: Add rtas_call_unlocked() Michael Ellerman
2015-12-17 11:57 ` [1/5] " Michael Ellerman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).