]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/iommu-arm-smmu-v3-use-explicit-mb-when-moving-cons-p.patch
autosel patches for 4.14
[thirdparty/kernel/stable-queue.git] / queue-4.14 / iommu-arm-smmu-v3-use-explicit-mb-when-moving-cons-p.patch
1 From 1a27f2261b683a80ba80c38bc477757534550ac6 Mon Sep 17 00:00:00 2001
2 From: Will Deacon <will.deacon@arm.com>
3 Date: Wed, 7 Nov 2018 22:58:24 +0000
4 Subject: iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer
5
6 [ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]
7
8 After removing an entry from a queue (e.g. reading an event in
9 arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
10 pointer to free the queue slot back to the SMMU. A memory barrier is
11 required here so that all reads targetting the queue entry have
12 completed before the consumer pointer is updated.
13
14 The implementation of queue_inc_cons() relies on a writel() to complete
15 the previous reads, but this is incorrect because writel() is only
16 guaranteed to complete prior writes. This patch replaces the call to
17 writel() with an mb(); writel_relaxed() sequence, which gives us the
18 read->write ordering which we require.
19
20 Cc: Robin Murphy <robin.murphy@arm.com>
21 Signed-off-by: Will Deacon <will.deacon@arm.com>
22 Signed-off-by: Sasha Levin <sashal@kernel.org>
23 ---
24 drivers/iommu/arm-smmu-v3.c | 8 +++++++-
25 1 file changed, 7 insertions(+), 1 deletion(-)
26
27 diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
28 index 26e99c03390f..09eb258a9a7d 100644
29 --- a/drivers/iommu/arm-smmu-v3.c
30 +++ b/drivers/iommu/arm-smmu-v3.c
31 @@ -730,7 +730,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
32 u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
33
34 q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
35 - writel(q->cons, q->cons_reg);
36 +
37 + /*
38 + * Ensure that all CPU accesses (reads and writes) to the queue
39 + * are complete before we update the cons pointer.
40 + */
41 + mb();
42 + writel_relaxed(q->cons, q->cons_reg);
43 }
44
45 static int queue_sync_prod(struct arm_smmu_queue *q)
46 --
47 2.19.1
48