Commit 9d86719f authored by Tony Lindgren's avatar Tony Lindgren Committed by Greg Kroah-Hartman

serial: 8250: Allow using ports higher than SERIAL_8250_RUNTIME_UARTS

We already allocate CONFIG_SERIAL_8250_NR_UARTS, but only allow using
CONFIG_SERIAL_8250_RUNTIME_UARTS uarts unless nr_uarts module params
is set. This causes issues for using distro kernels on SoCs with a
large number of serial ports.

Let's allow up to CONFIG_SERIAL_8250_NR_UARTS instead. To do this, we init
the ports as needed if the initial uarts was too low. This way there's no
need to set the value for CONFIG_SERIAL_8250_RUNTIME_UARTS to some SoC
specific higher value. Typically the default value of 4 can be used as
set for legacy reasons.

Note that limiting the number of intial uarts still works as before
unless a serial console on a higher port is specified. In this case we
will increase the nr_ports up to the console port specified.
Suggested-by: default avatarAndrew Davis <afd@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Link: https://lore.kernel.org/r/20230508111903.39339-1-tony@atomide.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent db86bb6e
...@@ -488,28 +488,20 @@ static inline void serial8250_apply_quirks(struct uart_8250_port *up) ...@@ -488,28 +488,20 @@ static inline void serial8250_apply_quirks(struct uart_8250_port *up)
up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0;
} }
static void __init serial8250_isa_init_ports(void) static struct uart_8250_port *serial8250_setup_port(int index)
{ {
struct uart_8250_port *up; struct uart_8250_port *up;
static int first = 1;
int i, irqflag = 0;
if (!first) if (index >= UART_NR)
return; return NULL;
first = 0;
if (nr_uarts > UART_NR) up = &serial8250_ports[index];
nr_uarts = UART_NR; up->port.line = index;
for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
struct uart_port *port = &up->port;
port->line = i;
serial8250_init_port(up); serial8250_init_port(up);
if (!base_ops) if (!base_ops)
base_ops = port->ops; base_ops = up->port.ops;
port->ops = &univ8250_port_ops; up->port.ops = &univ8250_port_ops;
timer_setup(&up->timer, serial8250_timeout, 0); timer_setup(&up->timer, serial8250_timeout, 0);
...@@ -517,10 +509,33 @@ static void __init serial8250_isa_init_ports(void) ...@@ -517,10 +509,33 @@ static void __init serial8250_isa_init_ports(void)
if (IS_ENABLED(CONFIG_ALPHA_JENSEN) || if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
(IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen())) (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
port->set_mctrl = alpha_jensen_set_mctrl; up->port.set_mctrl = alpha_jensen_set_mctrl;
serial8250_set_defaults(up); serial8250_set_defaults(up);
}
return up;
}
static void __init serial8250_isa_init_ports(void)
{
struct uart_8250_port *up;
static int first = 1;
int i, irqflag = 0;
if (!first)
return;
first = 0;
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
/*
* Set up initial isa ports based on nr_uart module param, or else
* default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
* need to increase nr_uarts when setting up the initial isa ports.
*/
for (i = 0; i < nr_uarts; i++)
serial8250_setup_port(i);
/* chain base port ops to support Remote Supervisor Adapter */ /* chain base port ops to support Remote Supervisor Adapter */
univ8250_port_ops = *base_ops; univ8250_port_ops = *base_ops;
...@@ -586,16 +601,29 @@ static void univ8250_console_write(struct console *co, const char *s, ...@@ -586,16 +601,29 @@ static void univ8250_console_write(struct console *co, const char *s,
static int univ8250_console_setup(struct console *co, char *options) static int univ8250_console_setup(struct console *co, char *options)
{ {
struct uart_8250_port *up;
struct uart_port *port; struct uart_port *port;
int retval; int retval, i;
/* /*
* Check whether an invalid uart number has been specified, and * Check whether an invalid uart number has been specified, and
* if so, search for the first available port that does have * if so, search for the first available port that does have
* console support. * console support.
*/ */
if (co->index >= nr_uarts) if (co->index >= UART_NR)
co->index = 0; co->index = 0;
/*
* If the console is past the initial isa ports, init more ports up to
* co->index as needed and increment nr_uarts accordingly.
*/
for (i = nr_uarts; i <= co->index; i++) {
up = serial8250_setup_port(i);
if (!up)
return -ENODEV;
nr_uarts++;
}
port = &serial8250_ports[co->index].port; port = &serial8250_ports[co->index].port;
/* link port to console */ /* link port to console */
port->cons = co; port->cons = co;
...@@ -990,7 +1018,18 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) ...@@ -990,7 +1018,18 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
mutex_lock(&serial_mutex); mutex_lock(&serial_mutex);
uart = serial8250_find_match_or_unused(&up->port); uart = serial8250_find_match_or_unused(&up->port);
if (uart && uart->port.type != PORT_8250_CIR) { if (!uart) {
/*
* If the port is past the initial isa ports, initialize a new
* port and increment nr_uarts accordingly.
*/
uart = serial8250_setup_port(nr_uarts);
if (!uart)
goto unlock;
nr_uarts++;
}
if (uart->port.type != PORT_8250_CIR) {
struct mctrl_gpios *gpios; struct mctrl_gpios *gpios;
if (uart->port.dev) if (uart->port.dev)
...@@ -1120,6 +1159,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) ...@@ -1120,6 +1159,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
} }
} }
unlock:
mutex_unlock(&serial_mutex); mutex_unlock(&serial_mutex);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment