[PATCH 1/2] parisc: Add unlocked functions for pdc_iodc_getc() and pdc_iodc_print()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The built-in kernel debugger (kgdb) deadlocks if we use spinlocks (which
should protect against concurrent firmware calls) to get keyboard input
or to output to the console.  Since we are in debugger mode anyway, we
can simply avoid using this protection mechanism, which is why this
patch adds unlocked keyboard input/console output functions which will
be used by a follow-up patch.

In addition save some static bytes by reusing pdc_result[] as
iodc_retbuf[] and by reducing the memory footprint of iodc_dbuf[].

Signed-off-by: Helge Deller <deller@xxxxxx>
---
 arch/parisc/include/asm/pdc.h |  2 +
 arch/parisc/kernel/firmware.c | 70 +++++++++++++++++++++--------------
 2 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h
index fcbcf9a96c11..bca1458b7c44 100644
--- a/arch/parisc/include/asm/pdc.h
+++ b/arch/parisc/include/asm/pdc.h
@@ -83,7 +83,9 @@ 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_getc_unlocked(void);
 int pdc_iodc_print(const unsigned char *str, unsigned count);
+int pdc_iodc_print_unlocked(const unsigned char *str, unsigned count);

 void pdc_emergency_unlock(void);
 int pdc_sti_call(unsigned long func, unsigned long flags,
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 6a7e315bcc2e..6c2bfd6d36b2 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -1288,25 +1288,14 @@ void pdc_io_reset_devices(void)

 #endif /* defined(BOOTLOADER) */

-/* locked by pdc_console_lock */
-static int __attribute__((aligned(8)))   iodc_retbuf[32];
-static char __attribute__((aligned(64))) iodc_dbuf[4096];
+/* locked by pdc_lock */
+static char __attribute__((aligned(64))) iodc_dbuf[1024];

-/**
- * pdc_iodc_print - Console print using IODC.
- * @str: the string to output.
- * @count: length of str
- *
- * Note that only these special chars are architected for console IODC io:
- * BEL, BS, CR, and LF. Others are passed through.
- * Since the HP console requires CR+LF to perform a 'newline', we translate
- * "\n" to "\r\n".
- */
-int pdc_iodc_print(const unsigned char *str, unsigned count)
+int pdc_iodc_print_unlocked(const unsigned char *str, unsigned count)
 {
 	unsigned int i;
-	unsigned long flags;

+	count = min(count, sizeof(iodc_dbuf));
 	for (i = 0; i < count;) {
 		switch(str[i]) {
 		case '\n':
@@ -1322,16 +1311,35 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
 	}

 print:
-        spin_lock_irqsave(&pdc_lock, flags);
-        real32_call(PAGE0->mem_cons.iodc_io,
-                    (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
-                    PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
-                    __pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0);
-        spin_unlock_irqrestore(&pdc_lock, flags);
+	real32_call(PAGE0->mem_cons.iodc_io,
+		(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+		PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+		__pa(pdc_result), 0, __pa(iodc_dbuf), i, 0);

 	return i;
 }

+/**
+ * pdc_iodc_print - Console print using IODC.
+ * @str: the string to output.
+ * @count: length of str
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+int pdc_iodc_print(const unsigned char *str, unsigned count)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&pdc_lock, flags);
+	ret = pdc_iodc_print_unlocked(str, count);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+	return ret;
+}
+
 #if !defined(BOOTLOADER)
 /**
  * pdc_iodc_getc - Read a character (non-blocking) from the PDC console.
@@ -1339,26 +1347,23 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
  * Read a character (non-blocking) from the PDC console, returns -1 if
  * key is not present.
  */
-int pdc_iodc_getc(void)
+int pdc_iodc_getc_unlocked(void)
 {
 	int ch;
 	int status;
-	unsigned long flags;

 	/* Bail if no console input device. */
 	if (!PAGE0->mem_kbd.iodc_io)
 		return 0;

 	/* wait for a keyboard (rs232)-input */
-	spin_lock_irqsave(&pdc_lock, flags);
 	real32_call(PAGE0->mem_kbd.iodc_io,
 		    (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
 		    PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
-		    __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+		    __pa(pdc_result), 0, __pa(iodc_dbuf), 1, 0);

 	ch = *iodc_dbuf;
-	status = *iodc_retbuf;
-	spin_unlock_irqrestore(&pdc_lock, flags);
+	status = *pdc_result;

 	if (status == 0)
 	    return -1;
@@ -1366,6 +1371,17 @@ int pdc_iodc_getc(void)
 	return ch;
 }

+int pdc_iodc_getc(void)
+{
+	unsigned long flags;
+	int ch;
+
+	spin_lock_irqsave(&pdc_lock, flags);
+	ch = pdc_iodc_getc_unlocked();
+	spin_unlock_irqrestore(&pdc_lock, flags);
+	return ch;
+}
+
 int pdc_sti_call(unsigned long func, unsigned long flags,
                  unsigned long inptr, unsigned long outputr,
                  unsigned long glob_cfg)
--
2.38.1




[Index of Archives]     [Linux SoC]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux