X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fkernel%2Frtas.c;h=0112318213ab5aada8c00e5ec6877c801501ccd3;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=77f1e06d208d2984bf0b12d79f2d6733c8c53b5f;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 77f1e06d2..011231821 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -38,19 +38,16 @@ struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED }; -EXPORT_SYMBOL(rtas); struct rtas_suspend_me_data { long waiting; struct rtas_args *args; }; -DEFINE_SPINLOCK(rtas_data_buf_lock); -EXPORT_SYMBOL(rtas_data_buf_lock); +EXPORT_SYMBOL(rtas); +DEFINE_SPINLOCK(rtas_data_buf_lock); char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; -EXPORT_SYMBOL(rtas_data_buf); - unsigned long rtas_rmo_buf; /* @@ -109,71 +106,11 @@ static void call_rtas_display_status_delay(char c) } } -void __init udbg_init_rtas_panel(void) +void __init udbg_init_rtas(void) { udbg_putc = call_rtas_display_status_delay; } -#ifdef CONFIG_UDBG_RTAS_CONSOLE - -/* If you think you're dying before early_init_dt_scan_rtas() does its - * work, you can hard code the token values for your firmware here and - * hardcode rtas.base/entry etc. - */ -static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE; -static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE; - -static void udbg_rtascon_putc(char c) -{ - int tries; - - if (!rtas.base) - return; - - /* Add CRs before LFs */ - if (c == '\n') - udbg_rtascon_putc('\r'); - - /* if there is more than one character to be displayed, wait a bit */ - for (tries = 0; tries < 16; tries++) { - if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0) - break; - udelay(1000); - } -} - -static int udbg_rtascon_getc_poll(void) -{ - int c; - - if (!rtas.base) - return -1; - - if (rtas_call(rtas_getchar_token, 0, 2, &c)) - return -1; - - return c; -} - -static int udbg_rtascon_getc(void) -{ - int c; - - while ((c = udbg_rtascon_getc_poll()) == -1) - ; - - return c; -} - - -void __init udbg_init_rtas_console(void) -{ - udbg_putc = udbg_rtascon_putc; - udbg_getc = udbg_rtascon_getc; - udbg_getc_poll = udbg_rtascon_getc_poll; -} -#endif /* CONFIG_UDBG_RTAS_CONSOLE */ - void rtas_progress(char *s, unsigned short hex) { struct device_node *root; @@ -299,7 +236,6 @@ int rtas_token(const char *service) tokp = (int *) get_property(rtas.dev, service, NULL); return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } -EXPORT_SYMBOL(rtas_token); #ifdef CONFIG_RTAS_ERROR_LOGGING /* @@ -392,7 +328,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) char *buff_copy = NULL; int ret; - if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) + if (token == RTAS_UNKNOWN_SERVICE) return -1; /* Gotta do something different here, use global lock for now... */ @@ -433,41 +369,26 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) } return ret; } -EXPORT_SYMBOL(rtas_call); -/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status - * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. +/* Given an RTAS status code of 990n compute the hinted delay of 10^n + * (last digit) milliseconds. For now we bound at n=5 (100 sec). */ -unsigned int rtas_busy_delay_time(int status) +unsigned int rtas_extended_busy_delay_time(int status) { - int order; - unsigned int ms = 0; - - if (status == RTAS_BUSY) { - ms = 1; - } else if (status >= 9900 && status <= 9905) { - order = status - 9900; - for (ms = 1; order > 0; order--) - ms *= 10; - } - - return ms; -} -EXPORT_SYMBOL(rtas_busy_delay_time); + int order = status - 9900; + unsigned long ms; -/* For an RTAS busy status code, perform the hinted delay. */ -unsigned int rtas_busy_delay(int status) -{ - unsigned int ms; + if (order < 0) + order = 0; /* RTC depends on this for -2 clock busy */ + else if (order > 5) + order = 5; /* bound */ - might_sleep(); - ms = rtas_busy_delay_time(status); - if (ms) - msleep(ms); + /* Use microseconds for reasonable accuracy */ + for (ms = 1; order > 0; order--) + ms *= 10; - return ms; + return ms; } -EXPORT_SYMBOL(rtas_busy_delay); int rtas_error_rc(int rtas_rc) { @@ -513,80 +434,80 @@ int rtas_get_power_level(int powerdomain, int *level) return rtas_error_rc(rc); return rc; } -EXPORT_SYMBOL(rtas_get_power_level); int rtas_set_power_level(int powerdomain, int level, int *setlevel) { int token = rtas_token("set-power-level"); + unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - do { + while (1) { rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); - } while (rtas_busy_delay(rc)); + if (rc == RTAS_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } if (rc < 0) return rtas_error_rc(rc); return rc; } -EXPORT_SYMBOL(rtas_set_power_level); int rtas_get_sensor(int sensor, int index, int *state) { int token = rtas_token("get-sensor-state"); + unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - do { + while (1) { rc = rtas_call(token, 2, 2, state, sensor, index); - } while (rtas_busy_delay(rc)); + if (rc == RTAS_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } if (rc < 0) return rtas_error_rc(rc); return rc; } -EXPORT_SYMBOL(rtas_get_sensor); int rtas_set_indicator(int indicator, int index, int new_value) { int token = rtas_token("set-indicator"); + unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - do { + while (1) { rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); - } while (rtas_busy_delay(rc)); - - if (rc < 0) - return rtas_error_rc(rc); - return rc; -} -EXPORT_SYMBOL(rtas_set_indicator); - -/* - * Ignoring RTAS extended delay - */ -int rtas_set_indicator_fast(int indicator, int index, int new_value) -{ - int rc; - int token = rtas_token("set-indicator"); - - if (token == RTAS_UNKNOWN_SERVICE) - return -ENOENT; - - rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); - - WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905)); + if (rc == RTAS_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } + else + break; + } if (rc < 0) return rtas_error_rc(rc); - return rc; } @@ -634,11 +555,13 @@ void rtas_os_term(char *str) do { status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, __pa(rtas_os_term_buf)); - } while (rtas_busy_delay(status)); - if (status != 0) - printk(KERN_EMERG "ibm,os-term call failed %d\n", + if (status == RTAS_BUSY) + udelay(1); + else if (status != 0) + printk(KERN_EMERG "ibm,os-term call failed %d\n", status); + } while (status == RTAS_BUSY); } static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; @@ -685,31 +608,9 @@ out: static int rtas_ibm_suspend_me(struct rtas_args *args) { int i; - long state; - long rc; - unsigned long dummy; struct rtas_suspend_me_data data; - /* Make sure the state is valid */ - rc = plpar_hcall(H_VASI_STATE, - ((u64)args->args[0] << 32) | args->args[1], - 0, 0, 0, - &state, &dummy, &dummy); - - if (rc) { - printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); - return rc; - } else if (state == H_VASI_ENABLED) { - args->args[args->nargs] = RTAS_NOT_SUSPENDABLE; - return 0; - } else if (state != H_VASI_SUSPENDING) { - printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", - state); - args->args[args->nargs] = -1; - return 0; - } - data.waiting = 1; data.args = args; @@ -883,34 +784,13 @@ void __init rtas_initialize(void) #endif } -int __init early_init_dt_scan_rtas(unsigned long node, - const char *uname, int depth, void *data) -{ - u32 *basep, *entryp, *sizep; - - if (depth != 1 || strcmp(uname, "rtas") != 0) - return 0; - - basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); - sizep = of_get_flat_dt_prop(node, "rtas-size", NULL); - - if (basep && entryp && sizep) { - rtas.base = *basep; - rtas.entry = *entryp; - rtas.size = *sizep; - } - -#ifdef CONFIG_UDBG_RTAS_CONSOLE - basep = of_get_flat_dt_prop(node, "put-term-char", NULL); - if (basep) - rtas_putchar_token = *basep; - - basep = of_get_flat_dt_prop(node, "get-term-char", NULL); - if (basep) - rtas_getchar_token = *basep; -#endif - /* break now */ - return 1; -} +EXPORT_SYMBOL(rtas_token); +EXPORT_SYMBOL(rtas_call); +EXPORT_SYMBOL(rtas_data_buf); +EXPORT_SYMBOL(rtas_data_buf_lock); +EXPORT_SYMBOL(rtas_extended_busy_delay_time); +EXPORT_SYMBOL(rtas_get_sensor); +EXPORT_SYMBOL(rtas_get_power_level); +EXPORT_SYMBOL(rtas_set_power_level); +EXPORT_SYMBOL(rtas_set_indicator);