Commit ef1afd4d authored by Kyle McMartin's avatar Kyle McMartin

[PARISC] pdc_console: fix bizarre panic on boot

Commit 721fdf34 introduced a subtle bug
by accidently removing the "static" from iodc_dbuf. This resulted in, what
appeared to be, a trap without *current set to a task. Probably the result of
a trap in real mode while calling firmware.

Also do other misc clean ups. Since the only input from firmware is non
blocking, share iodc_dbuf between input and output, and spinlock the
only callers.
Signed-off-by: default avatarKyle McMartin <kyle@parisc-linux.org>
parent d0347b49
...@@ -1080,6 +1080,9 @@ void pdc_io_reset_devices(void) ...@@ -1080,6 +1080,9 @@ void pdc_io_reset_devices(void)
spin_unlock_irqrestore(&pdc_lock, flags); spin_unlock_irqrestore(&pdc_lock, flags);
} }
/* locked by pdc_console_lock */
static int __attribute__((aligned(8))) iodc_retbuf[32];
static char __attribute__((aligned(64))) iodc_dbuf[4096];
/** /**
* pdc_iodc_print - Console print using IODC. * pdc_iodc_print - Console print using IODC.
...@@ -1091,24 +1094,20 @@ void pdc_io_reset_devices(void) ...@@ -1091,24 +1094,20 @@ void pdc_io_reset_devices(void)
* Since the HP console requires CR+LF to perform a 'newline', we translate * Since the HP console requires CR+LF to perform a 'newline', we translate
* "\n" to "\r\n". * "\n" to "\r\n".
*/ */
int pdc_iodc_print(unsigned char *str, unsigned count) int pdc_iodc_print(const unsigned char *str, unsigned count)
{ {
/* XXX Should we spinlock posx usage */
static int posx; /* for simple TAB-Simulation... */ static int posx; /* for simple TAB-Simulation... */
int __attribute__((aligned(8))) iodc_retbuf[32];
char __attribute__((aligned(64))) iodc_dbuf[4096];
unsigned int i; unsigned int i;
unsigned long flags; unsigned long flags;
memset(iodc_dbuf, 0, 4096); for (i = 0; i < count && i < 79;) {
for (i = 0; i < count && i < 2048;) {
switch(str[i]) { switch(str[i]) {
case '\n': case '\n':
iodc_dbuf[i+0] = '\r'; iodc_dbuf[i+0] = '\r';
iodc_dbuf[i+1] = '\n'; iodc_dbuf[i+1] = '\n';
i += 2; i += 2;
posx = 0; posx = 0;
break; goto print;
case '\t': case '\t':
while (posx & 7) { while (posx & 7) {
iodc_dbuf[i] = ' '; iodc_dbuf[i] = ' ';
...@@ -1124,6 +1123,16 @@ int pdc_iodc_print(unsigned char *str, unsigned count) ...@@ -1124,6 +1123,16 @@ int pdc_iodc_print(unsigned char *str, unsigned count)
} }
} }
/* if we're at the end of line, and not already inserting a newline,
* insert one anyway. iodc console doesn't claim to support >79 char
* lines. don't account for this in the return value.
*/
if (i == 79 && iodc_dbuf[i-1] != '\n') {
iodc_dbuf[i+0] = '\r';
iodc_dbuf[i+1] = '\n';
}
print:
spin_lock_irqsave(&pdc_lock, flags); spin_lock_irqsave(&pdc_lock, flags);
real32_call(PAGE0->mem_cons.iodc_io, real32_call(PAGE0->mem_cons.iodc_io,
(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
...@@ -1142,11 +1151,9 @@ int pdc_iodc_print(unsigned char *str, unsigned count) ...@@ -1142,11 +1151,9 @@ int pdc_iodc_print(unsigned char *str, unsigned count)
*/ */
int pdc_iodc_getc(void) int pdc_iodc_getc(void)
{ {
unsigned long flags;
static int __attribute__((aligned(8))) iodc_retbuf[32];
static char __attribute__((aligned(64))) iodc_dbuf[4096];
int ch; int ch;
int status; int status;
unsigned long flags;
/* Bail if no console input device. */ /* Bail if no console input device. */
if (!PAGE0->mem_kbd.iodc_io) if (!PAGE0->mem_kbd.iodc_io)
......
...@@ -52,15 +52,30 @@ ...@@ -52,15 +52,30 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <asm/pdc.h> /* for iodc_call() proto and friends */ #include <asm/pdc.h> /* for iodc_call() proto and friends */
static spinlock_t pdc_console_lock = SPIN_LOCK_UNLOCKED;
static void pdc_console_write(struct console *co, const char *s, unsigned count) static void pdc_console_write(struct console *co, const char *s, unsigned count)
{ {
pdc_iodc_print(s, count); int i = 0;
unsigned long flags;
spin_lock_irqsave(&pdc_console_lock, flags);
do {
i += pdc_iodc_print(s + i, count - i);
} while (i < count);
spin_unlock_irqrestore(&pdc_console_lock, flags);
} }
int pdc_console_poll_key(struct console *co) int pdc_console_poll_key(struct console *co)
{ {
return pdc_iodc_getc(); int c;
unsigned long flags;
spin_lock_irqsave(&pdc_console_lock, flags);
c = pdc_iodc_getc();
spin_unlock_irqrestore(&pdc_console_lock, flags);
return c;
} }
static int pdc_console_setup(struct console *co, char *options) static int pdc_console_setup(struct console *co, char *options)
......
...@@ -645,7 +645,7 @@ int pdc_soft_power_button(int sw_control); ...@@ -645,7 +645,7 @@ int pdc_soft_power_button(int sw_control);
void pdc_io_reset(void); void pdc_io_reset(void);
void pdc_io_reset_devices(void); void pdc_io_reset_devices(void);
int pdc_iodc_getc(void); int pdc_iodc_getc(void);
int pdc_iodc_print(unsigned char *str, unsigned count); int pdc_iodc_print(const unsigned char *str, unsigned count);
void pdc_emergency_unlock(void); void pdc_emergency_unlock(void);
int pdc_sti_call(unsigned long func, unsigned long flags, int pdc_sti_call(unsigned long func, unsigned long flags,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment