[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