Skip to content

Commit 027c3d3

Browse files
committed
parisc: Convert PDC console to an early console
Rewrite the PDC console to become an early console. Beside the fact that now boot information is visible until another (text- or graphics) console takes over, this benefits as well machines with a yet-unsupported STI console and kgdb. Signed-off-by: Helge Deller <[email protected]>
1 parent b148766 commit 027c3d3

File tree

6 files changed

+32
-249
lines changed

6 files changed

+32
-249
lines changed

arch/parisc/include/asm/pdc.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ extern unsigned long parisc_pat_pdc_cap; /* PDC capabilities (PAT) */
1919
#define PDC_TYPE_SYSTEM_MAP 1 /* 32-bit, but supports PDC_SYSTEM_MAP */
2020
#define PDC_TYPE_SNAKE 2 /* Doesn't support SYSTEM_MAP */
2121

22-
void pdc_console_init(void); /* in pdc_console.c */
23-
void pdc_console_restart(void);
24-
2522
void setup_pdc(void); /* in inventory.c */
2623

2724
/* wrapper-functions from pdc.c */

arch/parisc/kernel/pdc_cons.c

Lines changed: 26 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,18 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22
/*
3-
* PDC Console support - ie use firmware to dump text via boot console
3+
* PDC early console support - use PDC firmware to dump text via boot console
44
*
5-
* Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
6-
* Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
7-
* Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
8-
* Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
9-
* Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
10-
* Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
11-
* Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
12-
* Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
13-
* Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
14-
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
15-
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
16-
* Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
5+
* Copyright (C) 2001-2022 Helge Deller <[email protected]>
176
*/
187

19-
/*
20-
* The PDC console is a simple console, which can be used for debugging
21-
* boot related problems on HP PA-RISC machines. It is also useful when no
22-
* other console works.
23-
*
24-
* This code uses the ROM (=PDC) based functions to read and write characters
25-
* from and to PDC's boot path.
26-
*/
27-
28-
/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
29-
* On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
30-
#define EARLY_BOOTUP_DEBUG
31-
32-
33-
#include <linux/kernel.h>
348
#include <linux/console.h>
35-
#include <linux/string.h>
369
#include <linux/init.h>
37-
#include <linux/major.h>
38-
#include <linux/tty.h>
10+
#include <linux/serial_core.h>
11+
#include <linux/kgdb.h>
3912
#include <asm/page.h> /* for PAGE0 */
4013
#include <asm/pdc.h> /* for iodc_call() proto and friends */
4114

4215
static DEFINE_SPINLOCK(pdc_console_lock);
43-
static struct console pdc_cons;
4416

4517
static void pdc_console_write(struct console *co, const char *s, unsigned count)
4618
{
@@ -54,7 +26,8 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count)
5426
spin_unlock_irqrestore(&pdc_console_lock, flags);
5527
}
5628

57-
int pdc_console_poll_key(struct console *co)
29+
#ifdef CONFIG_KGDB
30+
static int kgdb_pdc_read_char(void)
5831
{
5932
int c;
6033
unsigned long flags;
@@ -63,201 +36,40 @@ int pdc_console_poll_key(struct console *co)
6336
c = pdc_iodc_getc();
6437
spin_unlock_irqrestore(&pdc_console_lock, flags);
6538

66-
return c;
67-
}
68-
69-
static int pdc_console_setup(struct console *co, char *options)
70-
{
71-
return 0;
72-
}
73-
74-
#if defined(CONFIG_PDC_CONSOLE)
75-
#include <linux/vt_kern.h>
76-
#include <linux/tty_flip.h>
77-
78-
#define PDC_CONS_POLL_DELAY (30 * HZ / 1000)
79-
80-
static void pdc_console_poll(struct timer_list *unused);
81-
static DEFINE_TIMER(pdc_console_timer, pdc_console_poll);
82-
static struct tty_port tty_port;
83-
84-
static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
85-
{
86-
tty_port_tty_set(&tty_port, tty);
87-
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
88-
89-
return 0;
39+
return (c <= 0) ? NO_POLL_CHAR : c;
9040
}
9141

92-
static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
42+
static void kgdb_pdc_write_char(u8 chr)
9343
{
94-
if (tty->count == 1) {
95-
del_timer_sync(&pdc_console_timer);
96-
tty_port_tty_set(&tty_port, NULL);
97-
}
44+
if (PAGE0->mem_cons.cl_class != CL_DUPLEX)
45+
pdc_console_write(NULL, &chr, 1);
9846
}
9947

100-
static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
101-
{
102-
pdc_console_write(NULL, buf, count);
103-
return count;
104-
}
105-
106-
static unsigned int pdc_console_tty_write_room(struct tty_struct *tty)
107-
{
108-
return 32768; /* no limit, no buffer used */
109-
}
110-
111-
static const struct tty_operations pdc_console_tty_ops = {
112-
.open = pdc_console_tty_open,
113-
.close = pdc_console_tty_close,
114-
.write = pdc_console_tty_write,
115-
.write_room = pdc_console_tty_write_room,
48+
static struct kgdb_io kgdb_pdc_io_ops = {
49+
.name = "kgdb_pdc",
50+
.read_char = kgdb_pdc_read_char,
51+
.write_char = kgdb_pdc_write_char,
11652
};
117-
118-
static void pdc_console_poll(struct timer_list *unused)
119-
{
120-
int data, count = 0;
121-
122-
while (1) {
123-
data = pdc_console_poll_key(NULL);
124-
if (data == -1)
125-
break;
126-
tty_insert_flip_char(&tty_port, data & 0xFF, TTY_NORMAL);
127-
count ++;
128-
}
129-
130-
if (count)
131-
tty_flip_buffer_push(&tty_port);
132-
133-
if (pdc_cons.flags & CON_ENABLED)
134-
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
135-
}
136-
137-
static struct tty_driver *pdc_console_tty_driver;
138-
139-
static int __init pdc_console_tty_driver_init(void)
140-
{
141-
struct tty_driver *driver;
142-
int err;
143-
144-
/* Check if the console driver is still registered.
145-
* It is unregistered if the pdc console was not selected as the
146-
* primary console. */
147-
148-
struct console *tmp;
149-
150-
console_lock();
151-
for_each_console(tmp)
152-
if (tmp == &pdc_cons)
153-
break;
154-
console_unlock();
155-
156-
if (!tmp) {
157-
printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
158-
return -ENODEV;
159-
}
160-
161-
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
162-
pdc_cons.flags &= ~CON_BOOT;
163-
164-
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
165-
TTY_DRIVER_RESET_TERMIOS);
166-
if (IS_ERR(driver))
167-
return PTR_ERR(driver);
168-
169-
tty_port_init(&tty_port);
170-
171-
driver->driver_name = "pdc_cons";
172-
driver->name = "ttyB";
173-
driver->major = MUX_MAJOR;
174-
driver->minor_start = 0;
175-
driver->type = TTY_DRIVER_TYPE_SYSTEM;
176-
driver->init_termios = tty_std_termios;
177-
tty_set_operations(driver, &pdc_console_tty_ops);
178-
tty_port_link_device(&tty_port, driver, 0);
179-
180-
err = tty_register_driver(driver);
181-
if (err) {
182-
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
183-
tty_port_destroy(&tty_port);
184-
tty_driver_kref_put(driver);
185-
return err;
186-
}
187-
188-
pdc_console_tty_driver = driver;
189-
190-
return 0;
191-
}
192-
device_initcall(pdc_console_tty_driver_init);
193-
194-
static struct tty_driver * pdc_console_device (struct console *c, int *index)
195-
{
196-
*index = c->index;
197-
return pdc_console_tty_driver;
198-
}
199-
#else
200-
#define pdc_console_device NULL
20153
#endif
20254

203-
static struct console pdc_cons = {
204-
.name = "ttyB",
205-
.write = pdc_console_write,
206-
.device = pdc_console_device,
207-
.setup = pdc_console_setup,
208-
.flags = CON_BOOT | CON_PRINTBUFFER,
209-
.index = -1,
210-
};
211-
212-
static int pdc_console_initialized;
213-
214-
static void pdc_console_init_force(void)
55+
static int __init pdc_earlycon_setup(struct earlycon_device *device,
56+
const char *opt)
21557
{
216-
if (pdc_console_initialized)
217-
return;
218-
++pdc_console_initialized;
219-
58+
struct console *earlycon_console;
59+
22060
/* If the console is duplex then copy the COUT parameters to CIN. */
22161
if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
22262
memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
22363

224-
/* register the pdc console */
225-
register_console(&pdc_cons);
226-
}
64+
earlycon_console = device->con;
65+
earlycon_console->write = pdc_console_write;
66+
device->port.iotype = UPIO_MEM32BE;
22767

228-
void __init pdc_console_init(void)
229-
{
230-
#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
231-
pdc_console_init_force();
68+
#ifdef CONFIG_KGDB
69+
kgdb_register_io_module(&kgdb_pdc_io_ops);
23270
#endif
233-
#ifdef EARLY_BOOTUP_DEBUG
234-
printk(KERN_INFO "Initialized PDC Console for debugging.\n");
235-
#endif
236-
}
237-
238-
239-
/*
240-
* Used for emergencies. Currently only used if an HPMC occurs. If an
241-
* HPMC occurs, it is possible that the current console may not be
242-
* properly initialised after the PDC IO reset. This routine unregisters
243-
* all of the current consoles, reinitializes the pdc console and
244-
* registers it.
245-
*/
246-
247-
void pdc_console_restart(void)
248-
{
249-
struct console *console;
250-
251-
if (pdc_console_initialized)
252-
return;
25371

254-
/* If we've already seen the output, don't bother to print it again */
255-
if (console_drivers != NULL)
256-
pdc_cons.flags &= ~CON_PRINTBUFFER;
257-
258-
while ((console = console_drivers) != NULL)
259-
unregister_console(console_drivers);
260-
261-
/* force registering the pdc console */
262-
pdc_console_init_force();
72+
return 0;
26373
}
74+
75+
EARLYCON_DECLARE(pdc, pdc_earlycon_setup);

arch/parisc/kernel/setup.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ void __init setup_cmdline(char **cmdline_p)
7070
strlcat(p, "tty0", COMMAND_LINE_SIZE);
7171
}
7272

73+
/* default to use early console */
74+
if (!strstr(p, "earlycon"))
75+
strlcat(p, " earlycon=pdc", COMMAND_LINE_SIZE);
76+
7377
#ifdef CONFIG_BLK_DEV_INITRD
7478
if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
7579
{
@@ -139,8 +143,6 @@ void __init setup_arch(char **cmdline_p)
139143
if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
140144
panic("KERNEL_INITIAL_ORDER too small!");
141145

142-
pdc_console_init();
143-
144146
#ifdef CONFIG_64BIT
145147
if(parisc_narrow_firmware) {
146148
printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");

arch/parisc/kernel/traps.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
239239
/* unlock the pdc lock if necessary */
240240
pdc_emergency_unlock();
241241

242-
/* maybe the kernel hasn't booted very far yet and hasn't been able
243-
* to initialize the serial or STI console. In that case we should
244-
* re-enable the pdc console, so that the user will be able to
245-
* identify the problem. */
246-
if (!console_drivers)
247-
pdc_console_restart();
248-
249242
if (err)
250243
printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
251244
current->comm, task_pid_nr(current), str, err);
@@ -429,10 +422,6 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
429422
/* unlock the pdc lock if necessary */
430423
pdc_emergency_unlock();
431424

432-
/* restart pdc console if necessary */
433-
if (!console_drivers)
434-
pdc_console_restart();
435-
436425
/* Not all paths will gutter the processor... */
437426
switch(code){
438427

@@ -482,9 +471,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
482471
unsigned long fault_space = 0;
483472
int si_code;
484473

485-
if (code == 1)
486-
pdc_console_restart(); /* switch back to pdc if HPMC */
487-
else if (!irqs_disabled_flags(regs->gr[0]))
474+
if (!irqs_disabled_flags(regs->gr[0]))
488475
local_irq_enable();
489476

490477
/* Security check:

drivers/tty/serial/Kconfig

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -602,21 +602,6 @@ config SERIAL_MUX_CONSOLE
602602
select SERIAL_CORE_CONSOLE
603603
default y
604604

605-
config PDC_CONSOLE
606-
bool "PDC software console support"
607-
depends on PARISC && !SERIAL_MUX && VT
608-
help
609-
Saying Y here will enable the software based PDC console to be
610-
used as the system console. This is useful for machines in
611-
which the hardware based console has not been written yet. The
612-
following steps must be completed to use the PDC console:
613-
614-
1. create the device entry (mknod /dev/ttyB0 c 11 0)
615-
2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
616-
3. Add device ttyB0 to /etc/securetty (if you want to log on as
617-
root on this console.)
618-
4. Change the kernel command console parameter to: console=ttyB0
619-
620605
config SERIAL_SUNSAB
621606
tristate "Sun Siemens SAB82532 serial support"
622607
depends on SPARC && PCI

lib/Kconfig.kgdb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ config KDB_DEFAULT_ENABLE
121121

122122
config KDB_KEYBOARD
123123
bool "KGDB_KDB: keyboard as input device"
124-
depends on VT && KGDB_KDB
124+
depends on VT && KGDB_KDB && !PARISC
125125
default n
126126
help
127127
KDB can use a PS/2 type keyboard for an input device

0 commit comments

Comments
 (0)