[RFC] ARM: OMAP2+: hwmod: don't touch hwmod if disabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I already did an RFC [1] that tried to do the same but I think this one is
cleaner. If a hardware module is disabled in devicetree the address range
will still be touched by omap_hwmod.c. If the corresponding  module isn't
powered this can lead to a crash of the kernel (for example rtc):
[    2.101166] omap_hwmod: rtc: enabling
[    2.105038] omap_hwmod: rtc: enabling clocks
[    2.109517] omap_hwmod: rtc: _omap4_enable_module: 2
[    2.114917] Unhandled fault: external abort on non-linefetch (0x1028) at 0xf9e3e078
[    2.122877] pgd = c0204000
[    2.125747] [f9e3e078] *pgd=44e11452(bad)
[    2.129977] Internal error: : 1028 [#1] SMP ARM
[    2.134720] Modules linked in:
[    2.137959] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-00006-g8cdb736-dirty #221
[    2.146188] Hardware name: Generic AM33XX (Flattened Device Tree)
[    2.152543] task: cb084000 task.stack: cb088000
[    2.157305] PC is at _update_sysc_cache+0x28/0x98
[    2.162232] LR is at _enable+0x1d8/0x288
[    2.166355] pc : [<c03297c0>]    lr : [<c0329f40>]    psr: 40000013
[    2.166355] sp : cb089ec8  ip : 00000000  fp : 00000000
[    2.178342] r10: 0000014f  r9 : c1337910  r8 : c12c783c
[    2.183804] r7 : c141d448  r6 : 00000000  r5 : c15846b8  r4 : c141cdc8
[    2.190606] r3 : f9e3e078  r2 : c141d8f4  r1 : f9e3e000  r0 : c141cdc8
[    2.197407] Flags: nZcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[    2.204834] Control: 10c5387d  Table: 80204019  DAC: 00000051
[    2.210831] Process swapper/0 (pid: 1, stack limit = 0xcb088220)
[    2.217093] Stack: (0xcb089ec8 to 0xcb08a000)
[    2.221668] 9ec0:                   00000000 a0000013 c141ce0c c141cdc8 c141cdf8 c141ce0c
[    2.230174] 9ee0: c12c7824 c1211f70 c140c30c c140c368 00000000 00000009 c141cdc8 c140c368
[    2.238679] 9f00: 00000000 c12124c8 00000002 c12123dc 00000000 c0301f30 0000014f 0000014f
[    2.247185] 9f20: cfdffc00 cfdffcf0 c112c044 0000014f 0000014e c0361a90 c112a62c 00000000
[    2.255689] 9f40: 00000002 00000002 cfdffcf0 00000000 c1436428 00000002 c1582dc0 c1582dc0
[    2.264196] 9f60: 00000002 c1582dc0 c1582dc0 c12c783c c1337910 c1200de8 00000002 00000002
[    2.272702] 9f80: 00000000 c12005a0 00000000 c0cd64c4 00000000 00000000 00000000 00000000
[    2.281208] 9fa0: 00000000 c0cd64cc 00000000 c0307ef8 00000000 00000000 00000000 00000000
[    2.289716] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    2.298219] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 fefff797 97eb77d5
[    2.306739] [<c03297c0>] (_update_sysc_cache) from [<a0000013>] (0xa0000013)
[    2.314086] Code: e3110c01 e5901054 e6f13073 1a00000c (e5933000)
[    2.320465] ---[ end trace d06e062f91dfe35a ]---
[    2.325386] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[    2.325386]
[    2.334975] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b

This patch will immediately set the disabled module to
_HWMOD_STATE_DISABLED.

Because the timers are disable to be hidden from the rest of the system,
this patch checks if it's a timer and will in this case still enable the
hw module.

To be affected by this patch, the status in the devicetree needs to be
changed to status = "disabled".
This is more convenient then to have a separate flag as requested by the
last RFC.

I think something that is perhaps unwanted, when u-boot would power a
hw module that should be disabled in Linux, Linux won't disable it 
anymore. Is this a usecase and what would be the expected behaviour?

[1] http://marc.info/?l=linux-omap&m=146712955420293

Signed-off-by: Stefan Eichenberger <stefan.eichenberger@xxxxxxxxxxxxx>
---
 arch/arm/mach-omap2/omap_hwmod.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 3b47ded..63f7eb2 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2462,6 +2462,21 @@ static int __init _init(struct omap_hwmod *oh, void *data)
 		pr_warn("omap_hwmod: %s using broken dt data from %s\n",
 			oh->name, np->name);
 
+	if (np) {
+		/*
+		 * If a hw module is disabled the driver should not touch it.
+		 * Timer modules are disabled by software to hide them from
+		 * the system. Therefore timers should always be enabled.
+		 */
+		if (!of_device_is_available(np) &&
+		    strncmp("timer", oh->name, 5)) {
+			pr_debug("omap_hwmod: set %s to state disabled\n",
+				 oh->name);
+			oh->_state = _HWMOD_STATE_DISABLED;
+			return 0;
+		}
+	}
+
 	r = _init_mpu_rt_base(oh, NULL, index, np);
 	if (r < 0) {
 		WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux