[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>

+35 -13
+17 -10
arch/parisc/kernel/firmware.c
··· 1080 spin_unlock_irqrestore(&pdc_lock, flags); 1081 } 1082 1083 1084 /** 1085 * pdc_iodc_print - Console print using IODC. ··· 1094 * Since the HP console requires CR+LF to perform a 'newline', we translate 1095 * "\n" to "\r\n". 1096 */ 1097 - int pdc_iodc_print(unsigned char *str, unsigned count) 1098 { 1099 - /* XXX Should we spinlock posx usage */ 1100 static int posx; /* for simple TAB-Simulation... */ 1101 - int __attribute__((aligned(8))) iodc_retbuf[32]; 1102 - char __attribute__((aligned(64))) iodc_dbuf[4096]; 1103 unsigned int i; 1104 unsigned long flags; 1105 1106 - memset(iodc_dbuf, 0, 4096); 1107 - for (i = 0; i < count && i < 2048;) { 1108 switch(str[i]) { 1109 case '\n': 1110 iodc_dbuf[i+0] = '\r'; 1111 iodc_dbuf[i+1] = '\n'; 1112 i += 2; 1113 posx = 0; 1114 - break; 1115 case '\t': 1116 while (posx & 7) { 1117 iodc_dbuf[i] = ' '; ··· 1123 } 1124 } 1125 1126 spin_lock_irqsave(&pdc_lock, flags); 1127 real32_call(PAGE0->mem_cons.iodc_io, 1128 (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, ··· 1151 */ 1152 int pdc_iodc_getc(void) 1153 { 1154 - unsigned long flags; 1155 - static int __attribute__((aligned(8))) iodc_retbuf[32]; 1156 - static char __attribute__((aligned(64))) iodc_dbuf[4096]; 1157 int ch; 1158 int status; 1159 1160 /* Bail if no console input device. */ 1161 if (!PAGE0->mem_kbd.iodc_io)
··· 1080 spin_unlock_irqrestore(&pdc_lock, flags); 1081 } 1082 1083 + /* locked by pdc_console_lock */ 1084 + static int __attribute__((aligned(8))) iodc_retbuf[32]; 1085 + static char __attribute__((aligned(64))) iodc_dbuf[4096]; 1086 1087 /** 1088 * pdc_iodc_print - Console print using IODC. ··· 1091 * Since the HP console requires CR+LF to perform a 'newline', we translate 1092 * "\n" to "\r\n". 1093 */ 1094 + int pdc_iodc_print(const unsigned char *str, unsigned count) 1095 { 1096 static int posx; /* for simple TAB-Simulation... */ 1097 unsigned int i; 1098 unsigned long flags; 1099 1100 + for (i = 0; i < count && i < 79;) { 1101 switch(str[i]) { 1102 case '\n': 1103 iodc_dbuf[i+0] = '\r'; 1104 iodc_dbuf[i+1] = '\n'; 1105 i += 2; 1106 posx = 0; 1107 + goto print; 1108 case '\t': 1109 while (posx & 7) { 1110 iodc_dbuf[i] = ' '; ··· 1124 } 1125 } 1126 1127 + /* if we're at the end of line, and not already inserting a newline, 1128 + * insert one anyway. iodc console doesn't claim to support >79 char 1129 + * lines. don't account for this in the return value. 1130 + */ 1131 + if (i == 79 && iodc_dbuf[i-1] != '\n') { 1132 + iodc_dbuf[i+0] = '\r'; 1133 + iodc_dbuf[i+1] = '\n'; 1134 + } 1135 + 1136 + print: 1137 spin_lock_irqsave(&pdc_lock, flags); 1138 real32_call(PAGE0->mem_cons.iodc_io, 1139 (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, ··· 1142 */ 1143 int pdc_iodc_getc(void) 1144 { 1145 int ch; 1146 int status; 1147 + unsigned long flags; 1148 1149 /* Bail if no console input device. */ 1150 if (!PAGE0->mem_kbd.iodc_io)
+17 -2
arch/parisc/kernel/pdc_cons.c
··· 52 #include <linux/tty.h> 53 #include <asm/pdc.h> /* for iodc_call() proto and friends */ 54 55 56 static void pdc_console_write(struct console *co, const char *s, unsigned count) 57 { 58 - pdc_iodc_print(s, count); 59 } 60 61 int pdc_console_poll_key(struct console *co) 62 { 63 - return pdc_iodc_getc(); 64 } 65 66 static int pdc_console_setup(struct console *co, char *options)
··· 52 #include <linux/tty.h> 53 #include <asm/pdc.h> /* for iodc_call() proto and friends */ 54 55 + static spinlock_t pdc_console_lock = SPIN_LOCK_UNLOCKED; 56 57 static void pdc_console_write(struct console *co, const char *s, unsigned count) 58 { 59 + int i = 0; 60 + unsigned long flags; 61 + 62 + spin_lock_irqsave(&pdc_console_lock, flags); 63 + do { 64 + i += pdc_iodc_print(s + i, count - i); 65 + } while (i < count); 66 + spin_unlock_irqrestore(&pdc_console_lock, flags); 67 } 68 69 int pdc_console_poll_key(struct console *co) 70 { 71 + int c; 72 + unsigned long flags; 73 + 74 + spin_lock_irqsave(&pdc_console_lock, flags); 75 + c = pdc_iodc_getc(); 76 + spin_unlock_irqrestore(&pdc_console_lock, flags); 77 + 78 + return c; 79 } 80 81 static int pdc_console_setup(struct console *co, char *options)
+1 -1
include/asm-parisc/pdc.h
··· 645 void pdc_io_reset(void); 646 void pdc_io_reset_devices(void); 647 int pdc_iodc_getc(void); 648 - int pdc_iodc_print(unsigned char *str, unsigned count); 649 650 void pdc_emergency_unlock(void); 651 int pdc_sti_call(unsigned long func, unsigned long flags,
··· 645 void pdc_io_reset(void); 646 void pdc_io_reset_devices(void); 647 int pdc_iodc_getc(void); 648 + int pdc_iodc_print(const unsigned char *str, unsigned count); 649 650 void pdc_emergency_unlock(void); 651 int pdc_sti_call(unsigned long func, unsigned long flags,