| From 27afac93e3bd7fa89749cf11da5d86ac9cde4dba Mon Sep 17 00:00:00 2001 |
| From: Lukas Wunner <lukas@wunner.de> |
| Date: Thu, 13 Aug 2020 12:52:40 +0200 |
| Subject: serial: pl011: Fix oops on -EPROBE_DEFER |
| |
| From: Lukas Wunner <lukas@wunner.de> |
| |
| commit 27afac93e3bd7fa89749cf11da5d86ac9cde4dba upstream. |
| |
| 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 10879ae5f12e ("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: 10879ae5f12e ("serial: pl011: add console matching function") |
| Signed-off-by: Lukas 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.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/tty/serial/amba-pl011.c | 11 +++++------ |
| 1 file changed, 5 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/tty/serial/amba-pl011.c |
| +++ b/drivers/tty/serial/amba-pl011.c |
| @@ -2249,9 +2249,8 @@ pl011_console_write(struct console *co, |
| clk_disable(uap->clk); |
| } |
| |
| -static void __init |
| -pl011_console_get_options(struct uart_amba_port *uap, int *baud, |
| - int *parity, int *bits) |
| +static void pl011_console_get_options(struct uart_amba_port *uap, int *baud, |
| + int *parity, int *bits) |
| { |
| if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) { |
| unsigned int lcr_h, ibrd, fbrd; |
| @@ -2284,7 +2283,7 @@ pl011_console_get_options(struct uart_am |
| } |
| } |
| |
| -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; |
| int baud = 38400; |
| @@ -2352,8 +2351,8 @@ static int __init pl011_console_setup(st |
| * |
| * 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, |
| - char *options) |
| +static int pl011_console_match(struct console *co, char *name, int idx, |
| + char *options) |
| { |
| unsigned char iotype; |
| resource_size_t addr; |