Commit 27afac93 authored by Lukas Wunner's avatar Lukas Wunner Committed by Greg Kroah-Hartman

serial: pl011: Fix oops on -EPROBE_DEFER

If probing of a pl011 gets deferred until after free_initmem(), an oops
ensues because pl011_console_match() is called which has been freed.

Fix by removing the __init attribute from the function and those it
calls.

Commit 10879ae5 ("serial: pl011: add console matching function")
introduced pl011_console_match() not just for early consoles but
regular preferred consoles, such as those added by acpi_parse_spcr().
Regular consoles may be registered after free_initmem() for various
reasons, one being deferred probing, another being dynamic enablement
of serial ports using a DeviceTree overlay.

Thus, pl011_console_match() must not be declared __init and the
functions it calls mustn't either.

Stack trace for posterity:

Unable to handle kernel paging request at virtual address 80c38b58
Internal error: Oops: 8000000d [#1] PREEMPT SMP ARM
PC is at pl011_console_match+0x0/0xfc
LR is at register_console+0x150/0x468
[<80187004>] (register_console)
[<805a8184>] (uart_add_one_port)
[<805b2b68>] (pl011_register_port)
[<805b3ce4>] (pl011_probe)
[<80569214>] (amba_probe)
[<805ca088>] (really_probe)
[<805ca2ec>] (driver_probe_device)
[<805ca5b0>] (__device_attach_driver)
[<805c8060>] (bus_for_each_drv)
[<805c9dfc>] (__device_attach)
[<805ca630>] (device_initial_probe)
[<805c90a8>] (bus_probe_device)
[<805c95a8>] (deferred_probe_work_func)

Fixes: 10879ae5 ("serial: pl011: add console matching function")
Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
Cc: stable@vger.kernel.org # v4.10+
Cc: Aleksey Makarov <amakarov@marvell.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Christopher Covington <cov@codeaurora.org>
Link: https://lore.kernel.org/r/f827ff09da55b8c57d316a1b008a137677b58921.1597315557.git.lukas@wunner.deSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 89efbe70
...@@ -2241,8 +2241,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2241,8 +2241,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
clk_disable(uap->clk); clk_disable(uap->clk);
} }
static void __init static void pl011_console_get_options(struct uart_amba_port *uap, int *baud,
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits) int *parity, int *bits)
{ {
if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) { if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
...@@ -2276,7 +2275,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, ...@@ -2276,7 +2275,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
} }
} }
static int __init pl011_console_setup(struct console *co, char *options) static int pl011_console_setup(struct console *co, char *options)
{ {
struct uart_amba_port *uap; struct uart_amba_port *uap;
int baud = 38400; int baud = 38400;
...@@ -2344,7 +2343,7 @@ static int __init pl011_console_setup(struct console *co, char *options) ...@@ -2344,7 +2343,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
* *
* Returns 0 if console matches; otherwise non-zero to use default matching * Returns 0 if console matches; otherwise non-zero to use default matching
*/ */
static int __init pl011_console_match(struct console *co, char *name, int idx, static int pl011_console_match(struct console *co, char *name, int idx,
char *options) char *options)
{ {
unsigned char iotype; unsigned char iotype;
......
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