ARM deadlock with PL310 on Armada-38x

Mark Tomlinson posted 1 patch 1 month ago
ARM deadlock with PL310 on Armada-38x
Posted by Mark Tomlinson 1 month ago
I have encountered an issue where, during allocation of DMA memory, the CPU
can deadlock, requiring a reset to clear. Although I have a work-around I
need some more information in order to make a patch I can be confident in.

I have found the patch 98ea2dba6593 "ARM: 8076/1: mm: add support for HW
coherent systems in PL310 cache" documents that writing to any PL310
register could cause a deadlock, and it disables the ->sync call to prevent
this. If I also disable the ->flush_range call I do not get my deadlock,
and everything seems fine.

However, Thomas' patch also states that these calls are necessary during
secondary CPU boot, so I am worried my patch is not complete. The CPU I am
using is dual-core, and although I'm not currently experiencing any issue,
there may be a latent bug. I am not sure the best way to fix this, if it
indeed is an issue.

Finally, Thomas' patch is only active when "arm,io-coherent" is added to
the DTS file. Although the comments imply that this code is necessary for
the Armada 375/38x, this DTS change is not in the dtsi files for these
CPUs. I find that a bit puzzling.

Here is my current patch to avoid the deadlock:

diff --git a/arch/arm/boot/dts/marvell/armada-38x.dtsi
b/arch/arm/boot/dts/marvell/armada-38x.dtsi
index 1181b13deabc..21c813a8222e 100644
--- a/arch/arm/boot/dts/marvell/armada-38x.dtsi
+++ b/arch/arm/boot/dts/marvell/armada-38x.dtsi
@@ -110,6 +110,7 @@ sdramc: sdramc@1400 {
 
 			L2: cache-controller@8000 {
 				compatible = "arm,pl310-cache";
+				arm,io-coherent;
 				reg = <0x8000 0x1000>;
 				cache-unified;
 				cache-level = <2>;
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 43d91bfd2360..6742e9934344 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -1341,7 +1341,6 @@ static const struct l2c_init_data
of_l2c310_coherent_data __initconst = {
 	.outer_cache = {
 		.inv_range   = l2c210_inv_range,
 		.clean_range = l2c210_clean_range,
-		.flush_range = l2c210_flush_range,
 		.flush_all   = l2c210_flush_all,
 		.disable     = l2c310_disable,
 		.resume      = l2c310_resume,