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. Commit10879ae5f1
("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:10879ae5f1
("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>
This commit is contained in:
parent
89efbe70b2
commit
27afac93e3
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
*
|
*
|
||||||
* 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;
|
||||||
|
|
Loading…
Reference in New Issue