On 08/03/2022, 14:50:43, Nicholas Piggin wrote: > Use the same calling and rets return convention with the raw rtas > call rather than requiring callers to load and byteswap return > values out of rtas_args. > > Signed-off-by: Nicholas Piggin <npig...@gmail.com>
Despite a minor comment below Reviewed-by: Laurent Dufour <lduf...@linux.ibm.com> > --- > arch/powerpc/include/asm/rtas.h | 4 +- > arch/powerpc/kernel/rtas.c | 53 +++++++++++--------- > arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +- > arch/powerpc/platforms/pseries/ras.c | 7 +-- > arch/powerpc/xmon/xmon.c | 2 +- > 5 files changed, 33 insertions(+), 35 deletions(-) > > diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h > index 82e5b055fa2a..1014ff140cf8 100644 > --- a/arch/powerpc/include/asm/rtas.h > +++ b/arch/powerpc/include/asm/rtas.h > @@ -241,8 +241,8 @@ extern int rtas_token(const char *service); > extern int rtas_service_present(const char *service); > extern int rtas_call(int token, int, int, int *, ...); > int rtas_call_reentrant(int token, int nargs, int nret, int *outputs, ...); > -void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, > - int nret, ...); > +int raw_rtas_call(struct rtas_args *args, int token, > + int nargs, int nret, int *outputs, ...); Minor, would it be better to keep the "unlocked" suffix to advise that the rtas lock is not held here? > extern void __noreturn rtas_restart(char *cmd); > extern void rtas_power_off(void); > extern void __noreturn rtas_halt(void); > diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c > index fece066115f0..751a20669669 100644 > --- a/arch/powerpc/kernel/rtas.c > +++ b/arch/powerpc/kernel/rtas.c > @@ -123,7 +123,7 @@ static void call_rtas_display_status(unsigned char c) > return; > > s = lock_rtas(); > - rtas_call_unlocked(&rtas.args, 10, 1, 1, NULL, c); > + raw_rtas_call(&rtas.args, 10, 1, 1, NULL, c); > unlock_rtas(s); > } > > @@ -434,10 +434,9 @@ 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) > +static int notrace va_raw_rtas_call(struct rtas_args *args, int token, > + int nargs, int nret, int *outputs, > + va_list list) > { > int i; > > @@ -453,21 +452,37 @@ va_rtas_call_unlocked(struct rtas_args *args, int > token, int nargs, int nret, > args->rets[i] = 0; > > do_enter_rtas(__pa(args)); > + > + if (nret > 1 && outputs != NULL) { > + for (i = 0; i < nret-1; ++i) > + outputs[i] = be32_to_cpu(args->rets[i+1]); > + } > + > + return (nret > 0) ? be32_to_cpu(args->rets[0]) : 0; > } > > -void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int > nret, ...) > +/* > + * Like rtas_call but no kmalloc or printk etc in error handling, so > + * error won't go through log_error. No tracing, may be called in real mode. > + * rtas_args must be supplied, and appropriate synchronization for the rtas > + * call being made has to be performed by the caller. > + */ > +int notrace raw_rtas_call(struct rtas_args *args, int token, > + int nargs, int nret, int *outputs, ...) > { > va_list list; > + int ret; > > - va_start(list, nret); > - va_rtas_call_unlocked(args, token, nargs, nret, list); > + va_start(list, outputs); > + ret = va_raw_rtas_call(args, token, nargs, nret, outputs, list); > va_end(list); > + > + return ret; > } > > int rtas_call(int token, int nargs, int nret, int *outputs, ...) > { > va_list list; > - int i; > unsigned long s; > struct rtas_args *rtas_args; > char *buff_copy = NULL; > @@ -482,19 +497,14 @@ int rtas_call(int token, int nargs, int nret, int > *outputs, ...) > rtas_args = &rtas.args; > > va_start(list, outputs); > - va_rtas_call_unlocked(rtas_args, token, nargs, nret, list); > + ret = va_raw_rtas_call(rtas_args, token, nargs, nret, outputs, list); > va_end(list); > > /* 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) > + if (ret == -1) > buff_copy = __fetch_rtas_last_error(NULL); > > - if (nret > 1 && outputs != NULL) > - for (i = 0; i < nret-1; ++i) > - outputs[i] = be32_to_cpu(rtas_args->rets[i+1]); > - ret = (nret > 0)? be32_to_cpu(rtas_args->rets[0]): 0; > - > unlock_rtas(s); > > if (buff_copy) { > @@ -950,7 +960,7 @@ int rtas_call_reentrant(int token, int nargs, int nret, > int *outputs, ...) > va_list list; > struct rtas_args *args; > unsigned long flags; > - int i, ret = 0; > + int ret; > > if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) > return -1; > @@ -962,16 +972,9 @@ int rtas_call_reentrant(int token, int nargs, int nret, > int *outputs, ...) > args = local_paca->rtas_args_reentrant; > > va_start(list, outputs); > - va_rtas_call_unlocked(args, token, nargs, nret, list); > + ret = va_raw_rtas_call(args, token, nargs, nret, outputs, list); > va_end(list); > > - if (nret > 1 && outputs) > - for (i = 0; i < nret - 1; ++i) > - outputs[i] = be32_to_cpu(args->rets[i + 1]); > - > - if (nret > 0) > - ret = be32_to_cpu(args->rets[0]); > - > local_irq_restore(flags); > preempt_enable(); > > diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c > b/arch/powerpc/platforms/pseries/hotplug-cpu.c > index b81fc846d99c..17c05650b6b9 100644 > --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c > +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c > @@ -53,7 +53,7 @@ static void rtas_stop_self(void) > > BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE); > > - rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL); > + raw_rtas_call(&args, rtas_stop_self_token, 0, 1, NULL); > > panic("Alas, I survived.\n"); > } > diff --git a/arch/powerpc/platforms/pseries/ras.c > b/arch/powerpc/platforms/pseries/ras.c > index 74c9b1b5bc66..b009ed7de1ee 100644 > --- a/arch/powerpc/platforms/pseries/ras.c > +++ b/arch/powerpc/platforms/pseries/ras.c > @@ -465,12 +465,7 @@ static void fwnmi_release_errinfo(void) > struct rtas_args rtas_args; > int ret; > > - /* > - * On pseries, the machine check stack is limited to under 4GB, so > - * args can be on-stack. > - */ > - rtas_call_unlocked(&rtas_args, ibm_nmi_interlock_token, 0, 1, NULL); > - ret = be32_to_cpu(rtas_args.rets[0]); > + ret = raw_rtas_call(&rtas_args, ibm_nmi_interlock_token, 0, 1, NULL); > if (ret != 0) > printk(KERN_ERR "FWNMI: nmi-interlock failed: %d\n", ret); > } > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index fd72753e8ad5..6f53e8bccc33 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -410,7 +410,7 @@ static inline void disable_surveillance(void) > if (set_indicator_token == RTAS_UNKNOWN_SERVICE) > return; > > - rtas_call_unlocked(&args, set_indicator_token, 3, 1, NULL, > + raw_rtas_call(&args, set_indicator_token, 3, 1, NULL, > SURVEILLANCE_TOKEN, 0, 0); > > #endif /* CONFIG_PPC_PSERIES */