mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-31 22:23:05 +00:00
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: Andrew Davis <afd@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Link: https://lore.kernel.org/r/20230508111903.39339-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
db86bb6ed4
commit
9d86719f87
@ -488,6 +488,34 @@ static inline void serial8250_apply_quirks(struct uart_8250_port *up)
|
||||
up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0;
|
||||
}
|
||||
|
||||
static struct uart_8250_port *serial8250_setup_port(int index)
|
||||
{
|
||||
struct uart_8250_port *up;
|
||||
|
||||
if (index >= UART_NR)
|
||||
return NULL;
|
||||
|
||||
up = &serial8250_ports[index];
|
||||
up->port.line = index;
|
||||
|
||||
serial8250_init_port(up);
|
||||
if (!base_ops)
|
||||
base_ops = up->port.ops;
|
||||
up->port.ops = &univ8250_port_ops;
|
||||
|
||||
timer_setup(&up->timer, serial8250_timeout, 0);
|
||||
|
||||
up->ops = &univ8250_driver_ops;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
|
||||
(IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
|
||||
up->port.set_mctrl = alpha_jensen_set_mctrl;
|
||||
|
||||
serial8250_set_defaults(up);
|
||||
|
||||
return up;
|
||||
}
|
||||
|
||||
static void __init serial8250_isa_init_ports(void)
|
||||
{
|
||||
struct uart_8250_port *up;
|
||||
@ -501,26 +529,13 @@ static void __init serial8250_isa_init_ports(void)
|
||||
if (nr_uarts > UART_NR)
|
||||
nr_uarts = UART_NR;
|
||||
|
||||
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);
|
||||
if (!base_ops)
|
||||
base_ops = port->ops;
|
||||
port->ops = &univ8250_port_ops;
|
||||
|
||||
timer_setup(&up->timer, serial8250_timeout, 0);
|
||||
|
||||
up->ops = &univ8250_driver_ops;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
|
||||
(IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
|
||||
port->set_mctrl = alpha_jensen_set_mctrl;
|
||||
|
||||
serial8250_set_defaults(up);
|
||||
}
|
||||
/*
|
||||
* 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 */
|
||||
univ8250_port_ops = *base_ops;
|
||||
@ -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)
|
||||
{
|
||||
struct uart_8250_port *up;
|
||||
struct uart_port *port;
|
||||
int retval;
|
||||
int retval, i;
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (co->index >= nr_uarts)
|
||||
if (co->index >= UART_NR)
|
||||
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;
|
||||
/* link port to console */
|
||||
port->cons = co;
|
||||
@ -990,7 +1018,18 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
|
||||
mutex_lock(&serial_mutex);
|
||||
|
||||
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;
|
||||
|
||||
if (uart->port.dev)
|
||||
@ -1120,6 +1159,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&serial_mutex);
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user