[openwrt/openwrt] ltq-vdsl-mei: add locking to interrupt handler

LEDE Commits lede-commits at lists.infradead.org
Tue Jun 7 14:02:35 PDT 2022


hauke pushed a commit to openwrt/openwrt.git, branch openwrt-22.03:
https://git.openwrt.org/290c13b7d70b0b396509bf20787ab75ccb057cb7

commit 290c13b7d70b0b396509bf20787ab75ccb057cb7
Author: Jan Hoffmann <jan at 3e8.eu>
AuthorDate: Sun Mar 13 22:14:38 2022 +0100

    ltq-vdsl-mei: add locking to interrupt handler
    
    Some users noticed repeated resyncs at random intervals, which go away
    when the MEI driver is configured to use polling instead of interrupts.
    Debugging shows that this seems to be caused by concurrent calls to
    MEI_ReadMailbox (in the interrupt handler) and MEI_WriteMailbox. This
    appears to be mostly triggered when there is an interrupt for vectoring
    error reports.
    
    In polling mode, calls to MEI_ReadMailbox are protected by the same
    semaphore as is used in MEI_WriteMailbox. When interrupts are used,
    MEI_WriteMailbox appears to rely on MEI_DisableDeviceInt and
    MEI_EnableDeviceInt to provide mutual exclusion with the interrupt
    handler. These functions mask/unmask interrupts, and there is an
    additional check of the mask in the interrupt handler itself. However,
    this is not sufficient on systems with SMP, as the interrupt handler
    may be running in parallel, and could already be past the interrupt
    mask check at this point.
    
    This adds a lock to the interrupt handler, and also acquires this lock
    in MEI_DisableDeviceInt. This should make sure that after a call to
    MEI_DisableDeviceInt the interrupt is masked, and the interrupt handler
    is either not running, has alread finished its work, or is still before
    the interrupt mask check, and is thus going to detect the change.
    
    Tested-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
    Signed-off-by: Jan Hoffmann <jan at 3e8.eu>
    (cherry picked from commit 17004245534731ab03c9a8683208e84d9c399979)
---
 package/kernel/lantiq/ltq-vdsl-mei/Makefile        |  2 +-
 .../ltq-vdsl-mei/patches/200-interrupt-lock.patch  | 45 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/package/kernel/lantiq/ltq-vdsl-mei/Makefile b/package/kernel/lantiq/ltq-vdsl-mei/Makefile
index d4a5ea720b..b7060eb2b4 100644
--- a/package/kernel/lantiq/ltq-vdsl-mei/Makefile
+++ b/package/kernel/lantiq/ltq-vdsl-mei/Makefile
@@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=ltq-vdsl-vr9-mei
 PKG_VERSION:=1.5.17.6
-PKG_RELEASE:=5
+PKG_RELEASE:=6
 
 PKG_BASE_NAME:=drv_mei_cpe
 PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz
diff --git a/package/kernel/lantiq/ltq-vdsl-mei/patches/200-interrupt-lock.patch b/package/kernel/lantiq/ltq-vdsl-mei/patches/200-interrupt-lock.patch
new file mode 100644
index 0000000000..a677ccec55
--- /dev/null
+++ b/package/kernel/lantiq/ltq-vdsl-mei/patches/200-interrupt-lock.patch
@@ -0,0 +1,45 @@
+--- a/src/drv_mei_cpe_common.c
++++ b/src/drv_mei_cpe_common.c
+@@ -104,6 +104,8 @@ IFX_uint32_t MEI_FsmStateSetMsgPreAction
+ MEI_DEVCFG_DATA_T MEI_DevCfgData;
+ #endif
+ 
++static DEFINE_SPINLOCK(MEI_InterruptLock);
++
+ /* ============================================================================
+    Proc-FS and debug variable definitions
+    ========================================================================= */
+@@ -2134,6 +2136,9 @@ IFX_int32_t MEI_ProcessIntPerIrq(MEIX_CN
+ #if (MEI_SUPPORT_DEBUG_STREAMS == 1)
+    IFX_int_t   extraDbgStreamLoop = 0;
+ #endif
++   unsigned long flags;
++
++   spin_lock_irqsave(&MEI_InterruptLock, flags);
+ 
+    /* get the actual chip device from the list and step through the VRX devices */
+    while(pNextXCntrl)
+@@ -2167,6 +2172,8 @@ IFX_int32_t MEI_ProcessIntPerIrq(MEIX_CN
+    }
+ #endif
+ 
++   spin_unlock_irqrestore(&MEI_InterruptLock, flags);
++
+    return meiIntCnt;
+ }
+ 
+@@ -2639,9 +2646,14 @@ IFX_int32_t MEI_MsgSendPreAction(
+ */
+ IFX_void_t MEI_DisableDeviceInt(MEI_DEV_T *pMeiDev)
+ {
++   unsigned long flags;
++   spin_lock_irqsave(&MEI_InterruptLock, flags);
++
+    MEI_MaskInterrupts( &pMeiDev->meiDrvCntrl,
+                        ME_ARC2ME_INTERRUPT_MASK_ALL);
+ 
++   spin_unlock_irqrestore(&MEI_InterruptLock, flags);
++
+    return;
+ }
+ 




More information about the lede-commits mailing list