diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/rtas.h | 2 | ||||
-rw-r--r-- | 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); | |||
338 | extern int rtas_token(const char *service); | 338 | extern int rtas_token(const char *service); |
339 | extern int rtas_service_present(const char *service); | 339 | extern int rtas_service_present(const char *service); |
340 | extern int rtas_call(int token, int, int, int *, ...); | 340 | extern int rtas_call(int token, int, int, int *, ...); |
341 | void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, | ||
342 | int nret, ...); | ||
341 | extern void rtas_restart(char *cmd); | 343 | extern void rtas_restart(char *cmd); |
342 | extern void rtas_power_off(void); | 344 | extern void rtas_power_off(void); |
343 | extern void rtas_halt(void); | 345 | 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) | |||
418 | #define get_errorlog_buffer() NULL | 418 | #define get_errorlog_buffer() NULL |
419 | #endif | 419 | #endif |
420 | 420 | ||
421 | |||
422 | static void | ||
423 | va_rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, | ||
424 | va_list list) | ||
425 | { | ||
426 | int i; | ||
427 | |||
428 | args->token = cpu_to_be32(token); | ||
429 | args->nargs = cpu_to_be32(nargs); | ||
430 | args->nret = cpu_to_be32(nret); | ||
431 | args->rets = &(args->args[nargs]); | ||
432 | |||
433 | for (i = 0; i < nargs; ++i) | ||
434 | args->args[i] = cpu_to_be32(va_arg(list, __u32)); | ||
435 | |||
436 | for (i = 0; i < nret; ++i) | ||
437 | args->rets[i] = 0; | ||
438 | |||
439 | enter_rtas(__pa(args)); | ||
440 | } | ||
441 | |||
442 | void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, ...) | ||
443 | { | ||
444 | va_list list; | ||
445 | |||
446 | va_start(list, nret); | ||
447 | va_rtas_call_unlocked(args, token, nargs, nret, list); | ||
448 | va_end(list); | ||
449 | } | ||
450 | |||
421 | int rtas_call(int token, int nargs, int nret, int *outputs, ...) | 451 | int rtas_call(int token, int nargs, int nret, int *outputs, ...) |
422 | { | 452 | { |
423 | va_list list; | 453 | va_list list; |
@@ -431,22 +461,14 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
431 | return -1; | 461 | return -1; |
432 | 462 | ||
433 | s = lock_rtas(); | 463 | s = lock_rtas(); |
464 | |||
465 | /* We use the global rtas args buffer */ | ||
434 | rtas_args = &rtas.args; | 466 | rtas_args = &rtas.args; |
435 | 467 | ||
436 | rtas_args->token = cpu_to_be32(token); | ||
437 | rtas_args->nargs = cpu_to_be32(nargs); | ||
438 | rtas_args->nret = cpu_to_be32(nret); | ||
439 | rtas_args->rets = &(rtas_args->args[nargs]); | ||
440 | va_start(list, outputs); | 468 | va_start(list, outputs); |
441 | for (i = 0; i < nargs; ++i) | 469 | va_rtas_call_unlocked(rtas_args, token, nargs, nret, list); |
442 | rtas_args->args[i] = cpu_to_be32(va_arg(list, __u32)); | ||
443 | va_end(list); | 470 | va_end(list); |
444 | 471 | ||
445 | for (i = 0; i < nret; ++i) | ||
446 | rtas_args->rets[i] = 0; | ||
447 | |||
448 | enter_rtas(__pa(rtas_args)); | ||
449 | |||
450 | /* A -1 return code indicates that the last command couldn't | 472 | /* A -1 return code indicates that the last command couldn't |
451 | be completed due to a hardware error. */ | 473 | be completed due to a hardware error. */ |
452 | if (be32_to_cpu(rtas_args->rets[0]) == -1) | 474 | if (be32_to_cpu(rtas_args->rets[0]) == -1) |