diff options
-rw-r--r-- | arch/powerpc/kernel/rtas-rtc.c | 30 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 85 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_flash.c | 25 | ||||
-rw-r--r-- | include/asm-powerpc/rtas.h | 8 |
4 files changed, 57 insertions, 91 deletions
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 34d073fb6091..77578c093dda 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -14,19 +14,20 @@ | |||
14 | unsigned long __init rtas_get_boot_time(void) | 14 | unsigned long __init rtas_get_boot_time(void) |
15 | { | 15 | { |
16 | int ret[8]; | 16 | int ret[8]; |
17 | int error, wait_time; | 17 | int error; |
18 | unsigned int wait_time; | ||
18 | u64 max_wait_tb; | 19 | u64 max_wait_tb; |
19 | 20 | ||
20 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | 21 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; |
21 | do { | 22 | do { |
22 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | 23 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); |
23 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 24 | |
24 | wait_time = rtas_extended_busy_delay_time(error); | 25 | wait_time = rtas_busy_delay_time(error); |
26 | if (wait_time) { | ||
25 | /* This is boot time so we spin. */ | 27 | /* This is boot time so we spin. */ |
26 | udelay(wait_time*1000); | 28 | udelay(wait_time*1000); |
27 | error = RTAS_CLOCK_BUSY; | ||
28 | } | 29 | } |
29 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 30 | } while (wait_time && (get_tb() < max_wait_tb)); |
30 | 31 | ||
31 | if (error != 0 && printk_ratelimit()) { | 32 | if (error != 0 && printk_ratelimit()) { |
32 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | 33 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", |
@@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time(void) | |||
44 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | 45 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) |
45 | { | 46 | { |
46 | int ret[8]; | 47 | int ret[8]; |
47 | int error, wait_time; | 48 | int error; |
49 | unsigned int wait_time; | ||
48 | u64 max_wait_tb; | 50 | u64 max_wait_tb; |
49 | 51 | ||
50 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | 52 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; |
51 | do { | 53 | do { |
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | 54 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); |
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 55 | |
56 | wait_time = rtas_busy_delay_time(error); | ||
57 | if (wait_time) { | ||
54 | if (in_interrupt() && printk_ratelimit()) { | 58 | if (in_interrupt() && printk_ratelimit()) { |
55 | memset(rtc_tm, 0, sizeof(struct rtc_time)); | 59 | memset(rtc_tm, 0, sizeof(struct rtc_time)); |
56 | printk(KERN_WARNING "error: reading clock" | 60 | printk(KERN_WARNING "error: reading clock" |
57 | " would delay interrupt\n"); | 61 | " would delay interrupt\n"); |
58 | return; /* delay not allowed */ | 62 | return; /* delay not allowed */ |
59 | } | 63 | } |
60 | wait_time = rtas_extended_busy_delay_time(error); | ||
61 | msleep(wait_time); | 64 | msleep(wait_time); |
62 | error = RTAS_CLOCK_BUSY; | ||
63 | } | 65 | } |
64 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 66 | } while (wait_time && (get_tb() < max_wait_tb)); |
65 | 67 | ||
66 | if (error != 0 && printk_ratelimit()) { | 68 | if (error != 0 && printk_ratelimit()) { |
67 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | 69 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", |
@@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *tm) | |||
88 | tm->tm_year + 1900, tm->tm_mon + 1, | 90 | tm->tm_year + 1900, tm->tm_mon + 1, |
89 | tm->tm_mday, tm->tm_hour, tm->tm_min, | 91 | tm->tm_mday, tm->tm_hour, tm->tm_min, |
90 | tm->tm_sec, 0); | 92 | tm->tm_sec, 0); |
91 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 93 | |
94 | wait_time = rtas_busy_delay_time(error); | ||
95 | if (wait_time) { | ||
92 | if (in_interrupt()) | 96 | if (in_interrupt()) |
93 | return 1; /* probably decrementer */ | 97 | return 1; /* probably decrementer */ |
94 | wait_time = rtas_extended_busy_delay_time(error); | ||
95 | msleep(wait_time); | 98 | msleep(wait_time); |
96 | error = RTAS_CLOCK_BUSY; | ||
97 | } | 99 | } |
98 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 100 | } while (wait_time && (get_tb() < max_wait_tb)); |
99 | 101 | ||
100 | if (error != 0 && printk_ratelimit()) | 102 | if (error != 0 && printk_ratelimit()) |
101 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | 103 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 0112318213ab..13496f319855 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -370,24 +370,36 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
370 | return ret; | 370 | return ret; |
371 | } | 371 | } |
372 | 372 | ||
373 | /* Given an RTAS status code of 990n compute the hinted delay of 10^n | 373 | /* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status |
374 | * (last digit) milliseconds. For now we bound at n=5 (100 sec). | 374 | * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. |
375 | */ | 375 | */ |
376 | unsigned int rtas_extended_busy_delay_time(int status) | 376 | unsigned int rtas_busy_delay_time(int status) |
377 | { | 377 | { |
378 | int order = status - 9900; | 378 | int order; |
379 | unsigned long ms; | 379 | unsigned int ms = 0; |
380 | |||
381 | if (status == RTAS_BUSY) { | ||
382 | ms = 1; | ||
383 | } else if (status >= 9900 && status <= 9905) { | ||
384 | order = status - 9900; | ||
385 | for (ms = 1; order > 0; order--) | ||
386 | ms *= 10; | ||
387 | } | ||
380 | 388 | ||
381 | if (order < 0) | 389 | return ms; |
382 | order = 0; /* RTC depends on this for -2 clock busy */ | 390 | } |
383 | else if (order > 5) | ||
384 | order = 5; /* bound */ | ||
385 | 391 | ||
386 | /* Use microseconds for reasonable accuracy */ | 392 | /* For an RTAS busy status code, perform the hinted delay. */ |
387 | for (ms = 1; order > 0; order--) | 393 | unsigned int rtas_busy_delay(int status) |
388 | ms *= 10; | 394 | { |
395 | unsigned int ms; | ||
389 | 396 | ||
390 | return ms; | 397 | might_sleep(); |
398 | ms = rtas_busy_delay_time(status); | ||
399 | if (ms) | ||
400 | msleep(ms); | ||
401 | |||
402 | return ms; | ||
391 | } | 403 | } |
392 | 404 | ||
393 | int rtas_error_rc(int rtas_rc) | 405 | int rtas_error_rc(int rtas_rc) |
@@ -438,22 +450,14 @@ int rtas_get_power_level(int powerdomain, int *level) | |||
438 | int rtas_set_power_level(int powerdomain, int level, int *setlevel) | 450 | int rtas_set_power_level(int powerdomain, int level, int *setlevel) |
439 | { | 451 | { |
440 | int token = rtas_token("set-power-level"); | 452 | int token = rtas_token("set-power-level"); |
441 | unsigned int wait_time; | ||
442 | int rc; | 453 | int rc; |
443 | 454 | ||
444 | if (token == RTAS_UNKNOWN_SERVICE) | 455 | if (token == RTAS_UNKNOWN_SERVICE) |
445 | return -ENOENT; | 456 | return -ENOENT; |
446 | 457 | ||
447 | while (1) { | 458 | do { |
448 | rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); | 459 | rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); |
449 | if (rc == RTAS_BUSY) | 460 | } while (rtas_busy_delay(rc)); |
450 | udelay(1); | ||
451 | else if (rtas_is_extended_busy(rc)) { | ||
452 | wait_time = rtas_extended_busy_delay_time(rc); | ||
453 | udelay(wait_time * 1000); | ||
454 | } else | ||
455 | break; | ||
456 | } | ||
457 | 461 | ||
458 | if (rc < 0) | 462 | if (rc < 0) |
459 | return rtas_error_rc(rc); | 463 | return rtas_error_rc(rc); |
@@ -463,22 +467,14 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel) | |||
463 | int rtas_get_sensor(int sensor, int index, int *state) | 467 | int rtas_get_sensor(int sensor, int index, int *state) |
464 | { | 468 | { |
465 | int token = rtas_token("get-sensor-state"); | 469 | int token = rtas_token("get-sensor-state"); |
466 | unsigned int wait_time; | ||
467 | int rc; | 470 | int rc; |
468 | 471 | ||
469 | if (token == RTAS_UNKNOWN_SERVICE) | 472 | if (token == RTAS_UNKNOWN_SERVICE) |
470 | return -ENOENT; | 473 | return -ENOENT; |
471 | 474 | ||
472 | while (1) { | 475 | do { |
473 | rc = rtas_call(token, 2, 2, state, sensor, index); | 476 | rc = rtas_call(token, 2, 2, state, sensor, index); |
474 | if (rc == RTAS_BUSY) | 477 | } while (rtas_busy_delay(rc)); |
475 | udelay(1); | ||
476 | else if (rtas_is_extended_busy(rc)) { | ||
477 | wait_time = rtas_extended_busy_delay_time(rc); | ||
478 | udelay(wait_time * 1000); | ||
479 | } else | ||
480 | break; | ||
481 | } | ||
482 | 478 | ||
483 | if (rc < 0) | 479 | if (rc < 0) |
484 | return rtas_error_rc(rc); | 480 | return rtas_error_rc(rc); |
@@ -488,23 +484,14 @@ int rtas_get_sensor(int sensor, int index, int *state) | |||
488 | int rtas_set_indicator(int indicator, int index, int new_value) | 484 | int rtas_set_indicator(int indicator, int index, int new_value) |
489 | { | 485 | { |
490 | int token = rtas_token("set-indicator"); | 486 | int token = rtas_token("set-indicator"); |
491 | unsigned int wait_time; | ||
492 | int rc; | 487 | int rc; |
493 | 488 | ||
494 | if (token == RTAS_UNKNOWN_SERVICE) | 489 | if (token == RTAS_UNKNOWN_SERVICE) |
495 | return -ENOENT; | 490 | return -ENOENT; |
496 | 491 | ||
497 | while (1) { | 492 | do { |
498 | rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); | 493 | rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); |
499 | if (rc == RTAS_BUSY) | 494 | } while (rtas_busy_delay(rc)); |
500 | udelay(1); | ||
501 | else if (rtas_is_extended_busy(rc)) { | ||
502 | wait_time = rtas_extended_busy_delay_time(rc); | ||
503 | udelay(wait_time * 1000); | ||
504 | } | ||
505 | else | ||
506 | break; | ||
507 | } | ||
508 | 495 | ||
509 | if (rc < 0) | 496 | if (rc < 0) |
510 | return rtas_error_rc(rc); | 497 | return rtas_error_rc(rc); |
@@ -555,13 +542,11 @@ void rtas_os_term(char *str) | |||
555 | do { | 542 | do { |
556 | status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, | 543 | status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, |
557 | __pa(rtas_os_term_buf)); | 544 | __pa(rtas_os_term_buf)); |
545 | } while (rtas_busy_delay(status)); | ||
558 | 546 | ||
559 | if (status == RTAS_BUSY) | 547 | if (status != 0) |
560 | udelay(1); | 548 | printk(KERN_EMERG "ibm,os-term call failed %d\n", |
561 | else if (status != 0) | ||
562 | printk(KERN_EMERG "ibm,os-term call failed %d\n", | ||
563 | status); | 549 | status); |
564 | } while (status == RTAS_BUSY); | ||
565 | } | 550 | } |
566 | 551 | ||
567 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | 552 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; |
@@ -789,7 +774,7 @@ EXPORT_SYMBOL(rtas_token); | |||
789 | EXPORT_SYMBOL(rtas_call); | 774 | EXPORT_SYMBOL(rtas_call); |
790 | EXPORT_SYMBOL(rtas_data_buf); | 775 | EXPORT_SYMBOL(rtas_data_buf); |
791 | EXPORT_SYMBOL(rtas_data_buf_lock); | 776 | EXPORT_SYMBOL(rtas_data_buf_lock); |
792 | EXPORT_SYMBOL(rtas_extended_busy_delay_time); | 777 | EXPORT_SYMBOL(rtas_busy_delay_time); |
793 | EXPORT_SYMBOL(rtas_get_sensor); | 778 | EXPORT_SYMBOL(rtas_get_sensor); |
794 | EXPORT_SYMBOL(rtas_get_power_level); | 779 | EXPORT_SYMBOL(rtas_get_power_level); |
795 | EXPORT_SYMBOL(rtas_set_power_level); | 780 | EXPORT_SYMBOL(rtas_set_power_level); |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index aaf384c3f04a..1442b63a75da 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -365,20 +365,12 @@ static int rtas_excl_release(struct inode *inode, struct file *file) | |||
365 | 365 | ||
366 | static void manage_flash(struct rtas_manage_flash_t *args_buf) | 366 | static void manage_flash(struct rtas_manage_flash_t *args_buf) |
367 | { | 367 | { |
368 | unsigned int wait_time; | ||
369 | s32 rc; | 368 | s32 rc; |
370 | 369 | ||
371 | while (1) { | 370 | do { |
372 | rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, | 371 | rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, |
373 | 1, NULL, args_buf->op); | 372 | 1, NULL, args_buf->op); |
374 | if (rc == RTAS_RC_BUSY) | 373 | } while (rtas_busy_delay(rc)); |
375 | udelay(1); | ||
376 | else if (rtas_is_extended_busy(rc)) { | ||
377 | wait_time = rtas_extended_busy_delay_time(rc); | ||
378 | udelay(wait_time * 1000); | ||
379 | } else | ||
380 | break; | ||
381 | } | ||
382 | 374 | ||
383 | args_buf->status = rc; | 375 | args_buf->status = rc; |
384 | } | 376 | } |
@@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf, | |||
451 | static void validate_flash(struct rtas_validate_flash_t *args_buf) | 443 | static void validate_flash(struct rtas_validate_flash_t *args_buf) |
452 | { | 444 | { |
453 | int token = rtas_token("ibm,validate-flash-image"); | 445 | int token = rtas_token("ibm,validate-flash-image"); |
454 | unsigned int wait_time; | ||
455 | int update_results; | 446 | int update_results; |
456 | s32 rc; | 447 | s32 rc; |
457 | 448 | ||
458 | rc = 0; | 449 | rc = 0; |
459 | while(1) { | 450 | do { |
460 | spin_lock(&rtas_data_buf_lock); | 451 | spin_lock(&rtas_data_buf_lock); |
461 | memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); | 452 | memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); |
462 | rc = rtas_call(token, 2, 2, &update_results, | 453 | rc = rtas_call(token, 2, 2, &update_results, |
463 | (u32) __pa(rtas_data_buf), args_buf->buf_size); | 454 | (u32) __pa(rtas_data_buf), args_buf->buf_size); |
464 | memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); | 455 | memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); |
465 | spin_unlock(&rtas_data_buf_lock); | 456 | spin_unlock(&rtas_data_buf_lock); |
466 | 457 | } while (rtas_busy_delay(rc)); | |
467 | if (rc == RTAS_RC_BUSY) | ||
468 | udelay(1); | ||
469 | else if (rtas_is_extended_busy(rc)) { | ||
470 | wait_time = rtas_extended_busy_delay_time(rc); | ||
471 | udelay(wait_time * 1000); | ||
472 | } else | ||
473 | break; | ||
474 | } | ||
475 | 458 | ||
476 | args_buf->status = rc; | 459 | args_buf->status = rc; |
477 | args_buf->update_results = update_results; | 460 | args_buf->update_results = update_results; |
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index f43c6835e62a..a3b4e55569c7 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h | |||
@@ -177,12 +177,8 @@ extern unsigned long rtas_get_boot_time(void); | |||
177 | extern void rtas_get_rtc_time(struct rtc_time *rtc_time); | 177 | extern void rtas_get_rtc_time(struct rtc_time *rtc_time); |
178 | extern int rtas_set_rtc_time(struct rtc_time *rtc_time); | 178 | extern int rtas_set_rtc_time(struct rtc_time *rtc_time); |
179 | 179 | ||
180 | /* Given an RTAS status code of 9900..9905 compute the hinted delay */ | 180 | extern unsigned int rtas_busy_delay_time(int status); |
181 | unsigned int rtas_extended_busy_delay_time(int status); | 181 | extern unsigned int rtas_busy_delay(int status); |
182 | static inline int rtas_is_extended_busy(int status) | ||
183 | { | ||
184 | return status >= 9900 && status <= 9909; | ||
185 | } | ||
186 | 182 | ||
187 | extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); | 183 | extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); |
188 | 184 | ||