[PATCH linux dev-4.13] clk: aspeed: Update to upstream to avoid schedule()ing from atomic context
Andrew Jeffery
andrew at aj.id.au
Tue Feb 20 15:03:39 AEDT 2018
The patch is generated against v4.16-rc2. Critically, it fixes a bug where
we schedule() from an atomic context:
[ 1.570455] BUG: scheduling while atomic: swapper/1/0x00000003
[ 1.576541] 4 locks held by swapper/1:
[ 1.580326] #0: (&dev->mutex){......}, at: [<802b7ac0>] __driver_attach+0x64/0x10c
[ 1.588177] #1: (&dev->mutex){......}, at: [<802b7ad0>] __driver_attach+0x74/0x10c
[ 1.596002] #2: (enable_lock){......}, at: [<80286f68>] clk_enable_lock+0x28/0x130
[ 1.603839] #3: (aspeed_clk_lock){......}, at: [<8028ff30>] aspeed_clk_enable+0x38/0xf4
[ 1.612096] irq event stamp: 157268
[ 1.615630] hardirqs last enabled at (157267): [<804c10a0>] _raw_spin_unlock_irqrestore+0x40/0x6c
[ 1.624621] hardirqs last disabled at (157268): [<80286f60>] clk_enable_lock+0x20/0x130
[ 1.632670] softirqs last enabled at (156064): [<80116160>] bdi_register_va+0xf4/0x240
[ 1.640713] softirqs last disabled at (156062): [<80116144>] bdi_register_va+0xd8/0x240
[ 1.648744] CPU: 0 PID: 1 Comm: swapper Not tainted 4.13.16-00190-g78a200cb21ab #2393
[ 1.656583] Hardware name: Generic DT based system
[ 1.661438] [<8001141c>] (unwind_backtrace) from [<8000e87c>] (show_stack+0x20/0x24)
[ 1.669235] [<8000e87c>] (show_stack) from [<804a65ec>] (dump_stack+0x20/0x28)
[ 1.676527] [<804a65ec>] (dump_stack) from [<80047680>] (__schedule_bug+0x70/0xa4)
[ 1.684150] [<80047680>] (__schedule_bug) from [<804bb8e0>] (__schedule+0x648/0x8a4)
[ 1.691933] [<804bb8e0>] (__schedule) from [<804bbbec>] (schedule+0x5c/0xcc)
[ 1.699025] [<804bbbec>] (schedule) from [<804bffec>] (schedule_timeout+0x220/0x498)
[ 1.706819] [<804bffec>] (schedule_timeout) from [<80073af0>] (msleep+0x48/0x58)
[ 1.714264] [<80073af0>] (msleep) from [<8028ffac>] (aspeed_clk_enable+0xb4/0xf4)
[ 1.721796] [<8028ffac>] (aspeed_clk_enable) from [<80288654>] (clk_core_enable+0xac/0x248)
[ 1.730189] [<80288654>] (clk_core_enable) from [<80288818>] (clk_core_enable_lock+0x28/0x3c)
[ 1.738760] [<80288818>] (clk_core_enable_lock) from [<8028aab4>] (clk_enable+0x24/0x28)
[ 1.746907] [<8028aab4>] (clk_enable) from [<802df144>] (aspeed_lpc_ctrl_probe+0x148/0x25c)
[ 1.755315] [<802df144>] (aspeed_lpc_ctrl_probe) from [<802b97c8>] (platform_drv_probe+0x60/0xbc)
[ 1.764230] [<802b97c8>] (platform_drv_probe) from [<802b78f0>] (driver_probe_device+0x2e4/0x450)
[ 1.773135] [<802b78f0>] (driver_probe_device) from [<802b7b28>] (__driver_attach+0xcc/0x10c)
[ 1.781699] [<802b7b28>] (__driver_attach) from [<802b58a4>] (bus_for_each_dev+0x5c/0xac)
[ 1.789915] [<802b58a4>] (bus_for_each_dev) from [<802b7d04>] (driver_attach+0x28/0x30)
[ 1.797958] [<802b7d04>] (driver_attach) from [<802b62dc>] (bus_add_driver+0x194/0x254)
[ 1.806001] [<802b62dc>] (bus_add_driver) from [<802b8b54>] (driver_register+0x88/0x104)
[ 1.814133] [<802b8b54>] (driver_register) from [<802ba42c>] (__platform_driver_register+0x3c/0x50)
[ 1.823234] [<802ba42c>] (__platform_driver_register) from [<8068a814>] (aspeed_lpc_ctrl_driver_init+0x20/0x28)
[ 1.833381] [<8068a814>] (aspeed_lpc_ctrl_driver_init) from [<80669f1c>] (do_one_initcall+0xb0/0x170)
[ 1.842651] [<80669f1c>] (do_one_initcall) from [<8066a0f4>] (kernel_init_freeable+0x118/0x1d0)
[ 1.851406] [<8066a0f4>] (kernel_init_freeable) from [<804b9b94>] (kernel_init+0x18/0x104)
[ 1.859717] [<804b9b94>] (kernel_init) from [<8000a868>] (ret_from_fork+0x14/0x2c)
Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
drivers/clk/clk-aspeed.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c
index 4a0d2649d907..9f7f931d6b2f 100644
--- a/drivers/clk/clk-aspeed.c
+++ b/drivers/clk/clk-aspeed.c
@@ -1,13 +1,4 @@
-/*
- * Copyright 2017 IBM Corporation
- *
- * Joel Stanley <joel at jms.id.au>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
#define pr_fmt(fmt) "clk-aspeed: " fmt
@@ -220,6 +211,7 @@ static int aspeed_clk_enable(struct clk_hw *hw)
unsigned long flags;
u32 clk = BIT(gate->clock_idx);
u32 rst = BIT(gate->reset_idx);
+ u32 enval;
spin_lock_irqsave(gate->lock, flags);
@@ -232,12 +224,12 @@ static int aspeed_clk_enable(struct clk_hw *hw)
}
/* Enable clock */
- regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, 0);
+ enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
+ regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
if (gate->reset_idx >= 0) {
- /* Delay 10ms */
- /* TODO: can we sleep here? */
- msleep(10);
+ /* A delay of 10ms is specified by the ASPEED docs */
+ mdelay(10);
/* Take IP out of reset */
regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0);
@@ -253,10 +245,12 @@ static void aspeed_clk_disable(struct clk_hw *hw)
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
unsigned long flags;
u32 clk = BIT(gate->clock_idx);
+ u32 enval;
spin_lock_irqsave(gate->lock, flags);
- regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, clk);
+ enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? clk : 0;
+ regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
spin_unlock_irqrestore(gate->lock, flags);
}
@@ -488,7 +482,12 @@ static int aspeed_clk_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) {
const struct aspeed_gate_data *gd = &aspeed_gates[i];
+ u32 gate_flags;
+ /* Special case: the USB port 1 clock (bit 14) is always
+ * working the opposite way from the other ones.
+ */
+ gate_flags = (gd->clock_idx == 14) ? 0 : CLK_GATE_SET_TO_DISABLE;
hw = aspeed_clk_hw_register_gate(dev,
gd->name,
gd->parent_name,
@@ -496,7 +495,7 @@ static int aspeed_clk_probe(struct platform_device *pdev)
map,
gd->clock_idx,
gd->reset_idx,
- CLK_GATE_SET_TO_DISABLE,
+ gate_flags,
&aspeed_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
@@ -619,7 +618,7 @@ static void __init aspeed_cc_init(struct device_node *np)
int i;
scu_base = of_iomap(np, 0);
- if (IS_ERR(scu_base))
+ if (!scu_base)
return;
aspeed_clk_data = kzalloc(sizeof(*aspeed_clk_data) +
--
2.14.1
More information about the openbmc
mailing list