Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef1afd4d authored by Kyle McMartin's avatar Kyle McMartin
Browse files

[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
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -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)
+17 −2
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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,