iommu/arm-smmu: Fix event queues synchronization
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Mon, 22 Aug 2016 13:42:24 +0000 (14:42 +0100)
committerWill Deacon <will.deacon@arm.com>
Fri, 16 Sep 2016 08:34:12 +0000 (09:34 +0100)
commitb4163fb3333cf2279f5bfa2bb4d2d93aa66a3eac
tree6161c98a707476d341af78ddfb29cfd5ea385802
parente2d42311ffc9a5014eb129d02eb0e7bc791430f0
iommu/arm-smmu: Fix event queues synchronization

SMMUv3 only sends interrupts for event queues (EVTQ and PRIQ) when they
transition from empty to non-empty. At the moment, if the SMMU adds new
items to a queue before the event thread finished consuming a previous
batch, the driver ignores any new item. The queue is then stuck in
non-empty state and all subsequent events will be lost.

As an example, consider the following flow, where (P, C) is the SMMU view
of producer/consumer indices, and (p, c) the driver view.

P C | p c
  1. SMMU appends a PPR to the PRI queue, 1 0 | 0 0
          sends an MSI
  2. PRIQ handler is called. 1 0 | 1 0
  3. SMMU appends a PPR to the PRI queue. 2 0 | 1 0
  4. PRIQ thread removes the first element. 2 1 | 1 1

  5. PRIQ thread believes that the queue is empty, goes into idle
     indefinitely.

To avoid this, always synchronize the producer index and drain the queue
once before leaving an event handler. In order to prevent races on the
local producer index, move all event queue handling into the threads.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
drivers/iommu/arm-smmu-v3.c