mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-21 21:02:24 +00:00
[PARISC] pdc_console: fix bizarre panic on boot
Commit 721fdf34167580ff98263c74cead8871d76936e6 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
@ -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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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)
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
#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);
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user