Skip to contentSkip to conversation

dmaengine: mv_xor: protect MBUS window access with a spinlock

PATCH Superseded Rosen Penev 2 participants 2 messages Sep 17 – Oct 20 dmaengine

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 dmaengine: mv_xor: protect MBUS window access with a spinlock

mv_xor_add_io_win() reads and writes shared MBUS window registers and updates the shared win_start/win_end arrays in mv_xor_device. Multiple DMA channels can call this function concurrently via mv_xor_prep_dma_xor(), leading to races where two threads can select the same free window slot, corrupt the registers, or produce inconsistent cached state.

Add a spinlock to struct mv_xor_device and hold it across the register read-modify-write and cache update in mv_xor_add_io_win().

Fixes 77ff7a706f01 ("mv_xor: Add support for IO (PCIe) src/dst areas")
Assisted-by opencode:big-pickle

---
v2: use guard()

 drivers/dma/mv_xor.c | 3 +++
 drivers/dma/mv_xor.h | 1 +
 2 files changed, 4 insertions(+)
drivers/dma/mv_xor.c +3 -0
index c4e0dce3ca64..da8eea8789ae 100644
@@ -494,6 +494,8 @@ static int mv_xor_add_io_win(struct mv_xor_chan *mv_chan, u32 addr)
 	if (xordev->xor_type == XOR_ARMADA_37XX)
 		return 0;
 
+	guard(spinlock_irqsave)(&xordev->win_lock);
+
 	/*
 	 * Loop over the cached windows to check, if the requested area
 	 * is already mapped. If this the case, nothing needs to be done
@@ -1345,6 +1347,7 @@ static int mv_xor_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, xordev);
 
+	spin_lock_init(&xordev->win_lock);
 
 	/*
 	 * We need to know which type of XOR device we use before
drivers/dma/mv_xor.h +1 -0
index c87cefd38a07..034db4d0bfb1 100644
@@ -80,6 +80,7 @@ struct mv_xor_device {
 	struct clk	     *clk;
 	struct mv_xor_chan   *channels[MV_XOR_MAX_CHANNELS];
 	int		     xor_type;
+	spinlock_t	     win_lock;
 
 	u32                  win_start[WINDOW_COUNT];
 	u32                  win_end[WINDOW_COUNT];
Signature · 1 line
2.55.0
#1 lore raw
Quoted 45 lines · Rosen Penev

mv_xor_add_io_win() reads and writes shared MBUS window registers and updates the shared win_start/win_end arrays in mv_xor_device. Multiple DMA channels can call this function concurrently via mv_xor_prep_dma_xor(), leading to races where two threads can select the same free window slot, corrupt the registers, or produce inconsistent cached state.

Add a spinlock to struct mv_xor_device and hold it across the register read-modify-write and cache update in mv_xor_add_io_win().

Fixes 77ff7a706f01 ("mv_xor: Add support for IO (PCIe) src/dst areas")
Assisted-by opencode:big-pickle

---
v2: use guard()

 drivers/dma/mv_xor.c | 3 +++
 drivers/dma/mv_xor.h | 1 +
 2 files changed, 4 insertions(+)
drivers/dma/mv_xor.c +3 -0
index c4e0dce3ca64..da8eea8789ae 100644
@@ -494,6 +494,8 @@ static int mv_xor_add_io_win(struct mv_xor_chan *mv_chan, u32 addr)
 	if (xordev->xor_type == XOR_ARMADA_37XX)
 		return 0;
 
+	guard(spinlock_irqsave)(&xordev->win_lock);
+
 	/*
 	 * Loop over the cached windows to check, if the requested area
 	 * is already mapped. If this the case, nothing needs to be done
@@ -1345,6 +1347,7 @@ static int mv_xor_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, xordev);
 
+	spin_lock_init(&xordev->win_lock);
 
 	/*
 	 * We need to know which type of XOR device we use before
drivers/dma/mv_xor.h +0 -0
index c87cefd38a07..034db4d0bfb1 100644

drivers/dma/mv_xor.h struct mv_xor_device { · line 83

Quoted 4 lines
drivers/dma/mv_xor.h +1 -0
@@ -80,6 +80,7 @@ struct mv_xor_device {
 	struct clk	     *clk;
 	struct mv_xor_chan   *channels[MV_XOR_MAX_CHANNELS];
 	int		     xor_type;
+	spinlock_t	     win_lock;

check patch require all lock have comments for it.

Frank

Quoted 6 lines
drivers/dma/mv_xor.h +0 -1
 	u32                  win_start[WINDOW_COUNT];
 	u32                  win_end[WINDOW_COUNT];
--

2.55.0