Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/powernv: Implement and use opal_flush_console

A new console flushing firmware API was introduced to replace event
polling loops, and implemented in opal-kmsg with affddff69c55e
("powerpc/powernv: Add a kmsg_dumper that flushes console output on
panic"), to flush the console in the panic path.

The OPAL console driver has other situations where interrupts are off
and it needs to flush the console synchronously. These still use a
polling loop.

So move the opal-kmsg flush code to opal_flush_console, and use the
new function in opal-kmsg and opal_put_chars.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Nicholas Piggin and committed by
Michael Ellerman
d2a2262e e00da0f2

+42 -36
+1
arch/powerpc/include/asm/opal.h
··· 305 305 306 306 extern int opal_get_chars(uint32_t vtermno, char *buf, int count); 307 307 extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); 308 + extern int opal_flush_console(uint32_t vtermno); 308 309 309 310 extern void hvc_opal_init_early(void); 310 311
+3 -32
arch/powerpc/platforms/powernv/opal-kmsg.c
··· 12 12 */ 13 13 14 14 #include <linux/kmsg_dump.h> 15 - #include <linux/delay.h> 16 15 17 16 #include <asm/opal.h> 18 17 #include <asm/opal-api.h> ··· 23 24 * may not be completely printed. This function does not actually dump the 24 25 * message, it just ensures that OPAL completely flushes the console buffer. 25 26 */ 26 - static void force_opal_console_flush(struct kmsg_dumper *dumper, 27 + static void kmsg_dump_opal_console_flush(struct kmsg_dumper *dumper, 27 28 enum kmsg_dump_reason reason) 28 29 { 29 - s64 rc; 30 - 31 30 /* 32 31 * Outside of a panic context the pollers will continue to run, 33 32 * so we don't need to do any special flushing. ··· 33 36 if (reason != KMSG_DUMP_PANIC) 34 37 return; 35 38 36 - if (opal_check_token(OPAL_CONSOLE_FLUSH)) { 37 - do { 38 - rc = OPAL_BUSY; 39 - while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { 40 - rc = opal_console_flush(0); 41 - if (rc == OPAL_BUSY_EVENT) { 42 - mdelay(OPAL_BUSY_DELAY_MS); 43 - opal_poll_events(NULL); 44 - } else if (rc == OPAL_BUSY) { 45 - mdelay(OPAL_BUSY_DELAY_MS); 46 - } 47 - } 48 - } while (rc == OPAL_PARTIAL); /* More to flush */ 49 - 50 - } else { 51 - __be64 evt; 52 - 53 - WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n"); 54 - /* 55 - * If OPAL_CONSOLE_FLUSH is not implemented in the firmware, 56 - * the console can still be flushed by calling the polling 57 - * function while it has OPAL_EVENT_CONSOLE_OUTPUT events. 58 - */ 59 - do { 60 - opal_poll_events(&evt); 61 - } while (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT); 62 - } 39 + opal_flush_console(0); 63 40 } 64 41 65 42 static struct kmsg_dumper opal_kmsg_dumper = { 66 - .dump = force_opal_console_flush 43 + .dump = kmsg_dump_opal_console_flush 67 44 }; 68 45 69 46 void __init opal_kmsg_init(void)
+38 -4
arch/powerpc/platforms/powernv/opal.c
··· 350 350 __be64 olen; 351 351 s64 len, rc; 352 352 unsigned long flags; 353 - __be64 evt; 354 353 355 354 if (!opal.entry) 356 355 return -ENODEV; ··· 370 371 /* Closed -> drop characters */ 371 372 if (rc) 372 373 return total_len; 373 - opal_poll_events(NULL); 374 + opal_flush_console(vtermno); 374 375 return -EAGAIN; 375 376 } 376 377 ··· 409 410 * things a bit later to limit that to synchronous path 410 411 * such as the kernel console and xmon/udbg 411 412 */ 413 + opal_flush_console(vtermno); 414 + } 415 + spin_unlock_irqrestore(&opal_write_lock, flags); 416 + 417 + return written; 418 + } 419 + 420 + int opal_flush_console(uint32_t vtermno) 421 + { 422 + s64 rc; 423 + 424 + if (!opal_check_token(OPAL_CONSOLE_FLUSH)) { 425 + __be64 evt; 426 + 427 + WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n"); 428 + /* 429 + * If OPAL_CONSOLE_FLUSH is not implemented in the firmware, 430 + * the console can still be flushed by calling the polling 431 + * function while it has OPAL_EVENT_CONSOLE_OUTPUT events. 432 + */ 412 433 do { 413 434 opal_poll_events(&evt); 414 435 } while (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT); 436 + 437 + return OPAL_SUCCESS; 415 438 } 416 - spin_unlock_irqrestore(&opal_write_lock, flags); 417 - return written; 439 + 440 + do { 441 + rc = OPAL_BUSY; 442 + while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { 443 + rc = opal_console_flush(vtermno); 444 + if (rc == OPAL_BUSY_EVENT) { 445 + mdelay(OPAL_BUSY_DELAY_MS); 446 + opal_poll_events(NULL); 447 + } else if (rc == OPAL_BUSY) { 448 + mdelay(OPAL_BUSY_DELAY_MS); 449 + } 450 + } 451 + } while (rc == OPAL_PARTIAL); /* More to flush */ 452 + 453 + return opal_error_code(rc); 418 454 } 419 455 420 456 static int opal_recover_mce(struct pt_regs *regs,