ARM: 9075/1: kernel: Fix interrupted SMC calls
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Wed, 14 Apr 2021 03:41:16 +0000 (04:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 22 May 2021 08:59:49 +0000 (10:59 +0200)
[ Upstream commit 57ac51667d8cd62731223d687e5fe7b41c502f89 ]

On Qualcomm ARM32 platforms, the SMC call can return before it has
completed. If this occurs, the call can be restarted, but it requires
using the returned session ID value from the interrupted SMC call.

The ARM32 SMCC code already has the provision to add platform specific
quirks for things like this. So let's make use of it and add the
Qualcomm specific quirk (ARM_SMCCC_QUIRK_QCOM_A6) used by the QCOM_SCM
driver.

This change is similar to the below one added for ARM64 a while ago:
commit 82bcd087029f ("firmware: qcom: scm: Fix interrupted SCM calls")

Without this change, the Qualcomm ARM32 platforms like SDX55 will return
-EINVAL for SMC calls used for modem firmware loading and validation.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/smccc-call.S

index ae85f67a635201931c624b4a8c4fb3dc68acce72..40afe953a0e2d736563e204435eee659a8b955b5 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/vdso_datapage.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
+#include <linux/arm-smccc.h>
 #include "signal.h"
 
 /*
@@ -159,6 +160,8 @@ int main(void)
   DEFINE(SLEEP_SAVE_SP_PHYS,   offsetof(struct sleep_save_sp, save_ptr_stash_phys));
   DEFINE(SLEEP_SAVE_SP_VIRT,   offsetof(struct sleep_save_sp, save_ptr_stash));
 #endif
+  DEFINE(ARM_SMCCC_QUIRK_ID_OFFS,      offsetof(struct arm_smccc_quirk, id));
+  DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS,   offsetof(struct arm_smccc_quirk, state));
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,    DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,                DMA_TO_DEVICE);
index e5d43066b88948b8e079e14f1ffd33ad884db067..13d307cd364c5cd4689203b90c014575dbc5e19f 100644 (file)
@@ -12,7 +12,9 @@
  *
  */
 #include <linux/linkage.h>
+#include <linux/arm-smccc.h>
 
+#include <asm/asm-offsets.h>
 #include <asm/opcodes-sec.h>
 #include <asm/opcodes-virt.h>
 #include <asm/unwind.h>
@@ -36,7 +38,14 @@ UNWIND(      .fnstart)
 UNWIND(        .save   {r4-r7})
        ldm     r12, {r4-r7}
        \instr
-       pop     {r4-r7}
+       ldr     r4, [sp, #36]
+       cmp     r4, #0
+       beq     1f                      // No quirk structure
+       ldr     r5, [r4, #ARM_SMCCC_QUIRK_ID_OFFS]
+       cmp     r5, #ARM_SMCCC_QUIRK_QCOM_A6
+       bne     1f                      // No quirk present
+       str     r6, [r4, #ARM_SMCCC_QUIRK_STATE_OFFS]
+1:     pop     {r4-r7}
        ldr     r12, [sp, #(4 * 4)]
        stm     r12, {r0-r3}
        bx      lr