Revert "tty/serial: Add kgdb_nmi driver"

This reverts commit 0c57dfcc6c.

The functionality was supoosed to be used by a later patch in the
series that never landed [1]. Drop it.

NOTE: part of functionality was already reverted by commit
39d0be8743 ("serial: kgdb_nmi: Remove unused knock code"). Also note
that this revert is not a clean revert given code changes that have
happened in the meantime.

It's obvious that nobody is using this code since the two exposed
functions (kgdb_register_nmi_console() and
kgdb_unregister_nmi_console()) are both no-ops if
"arch_kgdb_ops.enable_nmi" is not defined. No architectures define it.

[1] https://lore.kernel.org/lkml/1348522080-32629-9-git-send-email-anton.vorontsov@linaro.org/

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: URL [1]
Link: https://lore.kernel.org/r/20250129082535.1.Ia095eac1ae357f87d23e7af2206741f5d40788f1@changeid
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Douglas Anderson 2025-01-29 08:25:50 -08:00 committed by Greg Kroah-Hartman
parent c213375e32
commit c08b0f2c31
5 changed files with 0 additions and 316 deletions

View File

@ -179,25 +179,6 @@ config SERIAL_ATMEL_TTYAT
Say Y if you have an external 8250/16C550 UART. If unsure, say N.
config SERIAL_KGDB_NMI
bool "Serial console over KGDB NMI debugger port"
depends on KGDB_SERIAL_CONSOLE
help
This special driver allows you to temporary use NMI debugger port
as a normal console (assuming that the port is attached to KGDB).
Unlike KDB's disable_nmi command, with this driver you are always
able to go back to the debugger using KGDB escape sequence ($3#33).
This is because this console driver processes the input in NMI
context, and thus is able to intercept the magic sequence.
Note that since the console interprets input and uses polling
communication methods, for things like PPP you still must fully
detach debugger port from the KGDB NMI (i.e. disable_nmi), and
use raw console.
If unsure, say N.
config SERIAL_MESON
tristate "Meson serial port support"
depends on ARCH_MESON || COMPILE_TEST

View File

@ -96,6 +96,5 @@ obj-$(CONFIG_SERIAL_ZS) += zs.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_NUVOTON_MA35D1) += ma35d1_serial.o

View File

@ -1,280 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* KGDB NMI serial console
*
* Copyright 2010 Google, Inc.
* Arve Hjønnevåg <arve@android.com>
* Colin Cross <ccross@android.com>
* Copyright 2012 Linaro Ltd.
* Anton Vorontsov <anton.vorontsov@linaro.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/compiler.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/atomic.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/tick.h>
#include <linux/kfifo.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0);
static int kgdb_nmi_console_setup(struct console *co, char *options)
{
arch_kgdb_ops.enable_nmi(1);
/* The NMI console uses the dbg_io_ops to issue console messages. To
* avoid duplicate messages during kdb sessions we must inform kdb's
* I/O utilities that messages sent to the console will automatically
* be displayed on the dbg_io.
*/
dbg_io_ops->cons = co;
return 0;
}
static void kgdb_nmi_console_write(struct console *co, const char *s, uint c)
{
int i;
for (i = 0; i < c; i++)
dbg_io_ops->write_char(s[i]);
}
static struct tty_driver *kgdb_nmi_tty_driver;
static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx)
{
*idx = co->index;
return kgdb_nmi_tty_driver;
}
static struct console kgdb_nmi_console = {
.name = "ttyNMI",
.setup = kgdb_nmi_console_setup,
.write = kgdb_nmi_console_write,
.device = kgdb_nmi_console_device,
.flags = CON_PRINTBUFFER | CON_ANYTIME,
.index = -1,
};
/*
* This is usually the maximum rate on debug ports. We make fifo large enough
* to make copy-pasting to the terminal usable.
*/
#define KGDB_NMI_BAUD 115200
#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ)
struct kgdb_nmi_tty_priv {
struct tty_port port;
struct timer_list timer;
STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo;
};
static struct tty_port *kgdb_nmi_port;
/*
* The tasklet is cheap, it does not cause wakeups when reschedules itself,
* instead it waits for the next tick.
*/
static void kgdb_nmi_tty_receiver(struct timer_list *t)
{
struct kgdb_nmi_tty_priv *priv = from_timer(priv, t, timer);
char ch;
priv->timer.expires = jiffies + (HZ/100);
add_timer(&priv->timer);
if (likely(!atomic_read(&kgdb_nmi_num_readers) ||
!kfifo_len(&priv->fifo)))
return;
while (kfifo_out(&priv->fifo, &ch, 1))
tty_insert_flip_char(&priv->port, ch, TTY_NORMAL);
tty_flip_buffer_push(&priv->port);
}
static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty)
{
struct kgdb_nmi_tty_priv *priv =
container_of(port, struct kgdb_nmi_tty_priv, port);
kgdb_nmi_port = port;
priv->timer.expires = jiffies + (HZ/100);
add_timer(&priv->timer);
return 0;
}
static void kgdb_nmi_tty_shutdown(struct tty_port *port)
{
struct kgdb_nmi_tty_priv *priv =
container_of(port, struct kgdb_nmi_tty_priv, port);
del_timer(&priv->timer);
kgdb_nmi_port = NULL;
}
static const struct tty_port_operations kgdb_nmi_tty_port_ops = {
.activate = kgdb_nmi_tty_activate,
.shutdown = kgdb_nmi_tty_shutdown,
};
static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
{
struct kgdb_nmi_tty_priv *priv;
int ret;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
INIT_KFIFO(priv->fifo);
timer_setup(&priv->timer, kgdb_nmi_tty_receiver, 0);
tty_port_init(&priv->port);
priv->port.ops = &kgdb_nmi_tty_port_ops;
tty->driver_data = priv;
ret = tty_port_install(&priv->port, drv, tty);
if (ret) {
pr_err("%s: can't install tty port: %d\n", __func__, ret);
goto err;
}
return 0;
err:
tty_port_destroy(&priv->port);
kfree(priv);
return ret;
}
static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
tty->driver_data = NULL;
tty_port_destroy(&priv->port);
kfree(priv);
}
static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
unsigned int mode = file->f_flags & O_ACCMODE;
int ret;
ret = tty_port_open(&priv->port, tty, file);
if (!ret && (mode == O_RDONLY || mode == O_RDWR))
atomic_inc(&kgdb_nmi_num_readers);
return ret;
}
static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
unsigned int mode = file->f_flags & O_ACCMODE;
if (mode == O_RDONLY || mode == O_RDWR)
atomic_dec(&kgdb_nmi_num_readers);
tty_port_close(&priv->port, tty, file);
}
static void kgdb_nmi_tty_hangup(struct tty_struct *tty)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
tty_port_hangup(&priv->port);
}
static unsigned int kgdb_nmi_tty_write_room(struct tty_struct *tty)
{
/* Actually, we can handle any amount as we use polled writes. */
return 2048;
}
static ssize_t kgdb_nmi_tty_write(struct tty_struct *tty, const u8 *buf,
size_t c)
{
int i;
for (i = 0; i < c; i++)
dbg_io_ops->write_char(buf[i]);
return c;
}
static const struct tty_operations kgdb_nmi_tty_ops = {
.open = kgdb_nmi_tty_open,
.close = kgdb_nmi_tty_close,
.install = kgdb_nmi_tty_install,
.cleanup = kgdb_nmi_tty_cleanup,
.hangup = kgdb_nmi_tty_hangup,
.write_room = kgdb_nmi_tty_write_room,
.write = kgdb_nmi_tty_write,
};
int kgdb_register_nmi_console(void)
{
int ret;
if (!arch_kgdb_ops.enable_nmi)
return 0;
kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(kgdb_nmi_tty_driver)) {
pr_err("%s: cannot allocate tty\n", __func__);
return PTR_ERR(kgdb_nmi_tty_driver);
}
kgdb_nmi_tty_driver->driver_name = "ttyNMI";
kgdb_nmi_tty_driver->name = "ttyNMI";
kgdb_nmi_tty_driver->num = 1;
kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
kgdb_nmi_tty_driver->init_termios = tty_std_termios;
tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
KGDB_NMI_BAUD, KGDB_NMI_BAUD);
tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops);
ret = tty_register_driver(kgdb_nmi_tty_driver);
if (ret) {
pr_err("%s: can't register tty driver: %d\n", __func__, ret);
goto err_drv_reg;
}
register_console(&kgdb_nmi_console);
return 0;
err_drv_reg:
tty_driver_kref_put(kgdb_nmi_tty_driver);
return ret;
}
EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
int kgdb_unregister_nmi_console(void)
{
int ret;
if (!arch_kgdb_ops.enable_nmi)
return 0;
arch_kgdb_ops.enable_nmi(0);
ret = unregister_console(&kgdb_nmi_console);
if (ret)
return ret;
tty_unregister_driver(kgdb_nmi_tty_driver);
tty_driver_kref_put(kgdb_nmi_tty_driver);
return 0;
}
EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console);

View File

@ -186,8 +186,6 @@ static void cleanup_kgdboc(void)
if (configured != 1)
return;
if (kgdb_unregister_nmi_console())
return;
kgdboc_unregister_kbd();
kgdb_unregister_io_module(&kgdboc_io_ops);
}
@ -250,16 +248,10 @@ static int configure_kgdboc(void)
if (err)
goto noconfig;
err = kgdb_register_nmi_console();
if (err)
goto nmi_con_failed;
configured = 1;
return 0;
nmi_con_failed:
kgdb_unregister_io_module(&kgdboc_io_ops);
noconfig:
kgdboc_unregister_kbd();
configured = 0;

View File

@ -306,14 +306,6 @@ extern const struct kgdb_arch arch_kgdb_ops;
extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs);
#ifdef CONFIG_SERIAL_KGDB_NMI
extern int kgdb_register_nmi_console(void);
extern int kgdb_unregister_nmi_console(void);
#else
static inline int kgdb_register_nmi_console(void) { return 0; }
static inline int kgdb_unregister_nmi_console(void) { return 0; }
#endif
extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
extern struct kgdb_io *dbg_io_ops;