diff options
author | Pali Rohár <pali@kernel.org> | 2021-06-26 16:26:56 +0200 |
---|---|---|
committer | Pali Rohár <pali@kernel.org> | 2021-08-23 23:59:53 +0100 |
commit | 068fe919613197bf221c00fb84a1d94c66a7a8ca (patch) | |
tree | 2ad53518c80eb253afb701940b2e8445738f8785 /plat/marvell | |
parent | 485d1f8003f7a05049bf770b676d46cc31e799cb (diff) | |
download | arm-trusted-firmware-068fe919613197bf221c00fb84a1d94c66a7a8ca.tar.gz |
fix(plat/marvell/a3k): update information about PCIe abort hack
A3700 plat_ea_handler was introduced into TF-A codebase just because of
bugs in U-Boot and Linux kernel PCIe controller driver pci-aardvark.c.
These bugs were finally fixed in both U-Boot and Linux kernel drivers:
https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
Add all these information into comments, including printing error
message into a3k plat_ea_handler. Also check that abort is really
asynchronous and comes from lower level than EL3.
Signed-off-by: Pali Rohár <pali@kernel.org>
Change-Id: I46318d221b39773d5e25b3a0221d7738736ffdf1
Diffstat (limited to 'plat/marvell')
-rw-r--r-- | plat/marvell/armada/a3k/common/a3700_ea.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/plat/marvell/armada/a3k/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c index 3a4f7203b..dde92e38a 100644 --- a/plat/marvell/armada/a3k/common/a3700_ea.c +++ b/plat/marvell/armada/a3k/common/a3700_ea.c @@ -8,14 +8,75 @@ #include <common/debug.h> #include <arch_helpers.h> #include <plat/common/platform.h> +#include <bl31/ea_handle.h> -#define ADVK_SERROR_SYNDROME 0xbf000002 +#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002 + +#if !ENABLE_BACKTRACE +static const char *get_el_str(unsigned int el) +{ + if (el == MODE_EL3) { + return "EL3"; + } else if (el == MODE_EL2) { + return "EL2"; + } + return "S-EL1"; +} +#endif /* !ENABLE_BACKTRACE */ void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, void *handle, uint64_t flags) { - if (syndrome == ADVK_SERROR_SYNDROME) + unsigned int level = (unsigned int)GET_EL(read_spsr_el3()); + + /* + * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53 + * core means SError interrupt caused by AXI SLVERR on external access. + * + * In most cases this indicates a bug in U-Boot or Linux kernel driver + * pci-aardvark.c which implements access to A3700 PCIe config space. + * Driver does not wait for PCIe PIO transfer completion and try to + * start a new PCIe PIO transfer while previous has not finished yet. + * A3700 PCIe controller in this case sends SLVERR via AXI which results + * in a fatal Asynchronous SError interrupt on Cortex A53 CPU. + * + * Following patches fix that bug in U-Boot and Linux kernel drivers: + * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01 + * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7 + * + * As a hacky workaround for unpatched U-Boot and Linux kernel drivers + * ignore all asynchronous aborts with that syndrome value received on + * CPU from level lower than EL3. + * + * Because these aborts are delivered on CPU asynchronously, they are + * imprecise and we cannot check the real reason of abort and neither + * who and why sent this abort. We expect that on A3700 it is always + * PCIe controller. + * + * Hence ignoring all aborts with this syndrome value is just a giant + * hack that we need only because of bugs in old U-Boot and Linux kernel + * versions and because it was decided that TF-A would implement this + * hack for U-Boot and Linux kernel it in this way. New patched U-Boot + * and kernel versions do not need it anymore. + * + * Links to discussion about this workaround: + * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/ + * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/ + * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541 + */ + if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC && + syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) { + ERROR_NL(); + ERROR("Ignoring Asynchronous External Abort with" + " syndrome 0x%llx received on 0x%lx from %s\n", + syndrome, read_mpidr_el1(), get_el_str(level)); + ERROR("SError interrupt: AXI SLVERR on external access\n"); + ERROR("This indicates a bug in pci-aardvark.c driver\n"); + ERROR("Please update U-Boot/Linux to the latest version\n"); + ERROR_NL(); + console_flush(); return; + } plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); } |