Skip to content

Commit

Permalink
tty/serial/core: Introduce poll_init callback
Browse files Browse the repository at this point in the history
It was noticed that polling drivers (like KGDB) are not able to use
serial ports if the ports were not previously initialized via console.
I.e.  when booting with console=ttyAMA0 kgdboc=ttyAMA0, everything works
fine, but with console=ttyFOO kgdboc=ttyAMA0, the kgdboc doesn't work.

This is because we don't initialize the hardware. Calling ->startup() is
not an option, because drivers request interrupts there, and drivers
fail to handle situations when tty isn't opened with interrupts enabled.

So, we have to implement a new callback (actually, tty_ops already have
a similar callback), which does everything needed to initialize just the
hardware.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Anton Vorontsov authored and Greg Kroah-Hartman committed Sep 26, 2012
1 parent 729043e commit c7f3e70
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 0 deletions.
17 changes: 17 additions & 0 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,7 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
int bits = 8;
int parity = 'n';
int flow = 'n';
int ret;

if (!state || !state->uart_port)
return -1;
Expand All @@ -2137,6 +2138,22 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
if (!(port->ops->poll_get_char && port->ops->poll_put_char))
return -1;

if (port->ops->poll_init) {
struct tty_port *tport = &state->port;

ret = 0;
mutex_lock(&tport->mutex);
/*
* We don't set ASYNCB_INITIALIZED as we only initialized the
* hw, e.g. state->xmit is still uninitialized.
*/
if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
ret = port->ops->poll_init(port);
mutex_unlock(&tport->mutex);
if (ret)
return ret;
}

if (options) {
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(port, NULL, baud, parity, bits, flow);
Expand Down
1 change: 1 addition & 0 deletions include/linux/serial_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ struct uart_ops {
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif
Expand Down

0 comments on commit c7f3e70

Please sign in to comment.