[PARISC] pdc_console: fix bizarre panic on boot
Commit 721fdf3416
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: Kyle McMartin <kyle@parisc-linux.org>
This commit is contained in:
parent
d0347b49c9
commit
ef1afd4d79
3 changed files with 35 additions and 13 deletions
|
@ -1080,6 +1080,9 @@ void pdc_io_reset_devices(void)
|
|||
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.
|
||||
|
@ -1091,24 +1094,20 @@ void pdc_io_reset_devices(void)
|
|||
* Since the HP console requires CR+LF to perform a 'newline', we translate
|
||||
* "\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... */
|
||||
int __attribute__((aligned(8))) iodc_retbuf[32];
|
||||
char __attribute__((aligned(64))) iodc_dbuf[4096];
|
||||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
memset(iodc_dbuf, 0, 4096);
|
||||
for (i = 0; i < count && i < 2048;) {
|
||||
for (i = 0; i < count && i < 79;) {
|
||||
switch(str[i]) {
|
||||
case '\n':
|
||||
iodc_dbuf[i+0] = '\r';
|
||||
iodc_dbuf[i+1] = '\n';
|
||||
i += 2;
|
||||
posx = 0;
|
||||
break;
|
||||
goto print;
|
||||
case '\t':
|
||||
while (posx & 7) {
|
||||
iodc_dbuf[i] = ' ';
|
||||
|
@ -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);
|
||||
real32_call(PAGE0->mem_cons.iodc_io,
|
||||
(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
|
||||
|
@ -1142,11 +1151,9 @@ int pdc_iodc_print(unsigned char *str, unsigned count)
|
|||
*/
|
||||
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 status;
|
||||
unsigned long flags;
|
||||
|
||||
/* Bail if no console input device. */
|
||||
if (!PAGE0->mem_kbd.iodc_io)
|
||||
|
|
|
@ -52,15 +52,30 @@
|
|||
#include <linux/tty.h>
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -645,7 +645,7 @@ int pdc_soft_power_button(int sw_control);
|
|||
void pdc_io_reset(void);
|
||||
void pdc_io_reset_devices(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);
|
||||
int pdc_sti_call(unsigned long func, unsigned long flags,
|
||||
|
|
Loading…
Reference in a new issue