io-pgtable lock removal
Get series with b4
b4 am [email protected]Versions newest first
- v1 Latest0 of 8 patches 0 repliesNew
Patches in v1 No applies recorded yet
None of the 8 patches the cover letter announces are in this archive.
Reviews trailers per patch
No Reviewed-by, Acked-by or Tested-by trailers for v1 yet.
Cover letter [PATCH 0/8] io-pgtable lock removal
Hi Ray,
Robin and I have been bashing our heads against the tlb_sync_pending flag this morning, and we reckon it could have something to do with your timeouts on MMU-500.
Quoted 4 lines · Ray Jui
Quoted 4 lines
Quoted 4 lines
Also, in a few occasions, I observed the following message during the test, when multiple cores are involved:
arm-smmu 64000000.mmu: TLB sync timed out -- SMMU may be deadlocked
The tlb_sync_pending logic was written under the assumption of a global page-table lock, so it assumes that it only has to care about syncing flushes from the current CPU/context. That's not true anymore, and the current code can accidentally skip syncs and (what I think is happening in your case) allow concurrent syncs, which will potentially lead to timeouts if a CPU is unlucky enough to keep missing the Ack.
Please can you try the diff below and see if it fixes things for you? This applies on top of my for-joerg/arm-smmu/updates branch, but note that I've only shown it to the compiler. Not tested at all.
Will
--->8
drivers/iommu/io-pgtable.c +1 -0
@@ -59,6 +59,7 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, iop->cookie = cookie; iop->cfg = *cfg; +atomic_set (&iop->tlb_sync_pending,0 );return &iop->ops; }
drivers/iommu/io-pgtable.h +6 -6
@@ -1,5 +1,7 @@#ifndef __IO_PGTABLE_H#define __IO_PGTABLE_H + +#include <linux/atomic.h> #include <linux/bitops.h> /*
@@ -165,7 +167,7 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops);struct io_pgtable {enum io_pgtable_fmt fmt;void *cookie; -bool tlb_sync_pending; +atomic_t tlb_sync_pending;struct io_pgtable_cfg cfg;struct io_pgtable_ops ops; };
@@ -175,22 +177,20 @@ struct io_pgtable {static inline void io_pgtable_tlb_flush_all (struct io_pgtable *iop) { iop->cfg.tlb->tlb_flush_all (iop->cookie); - iop->tlb_sync_pending = true; +atomic_set_release (&iop->tlb_sync_pending,1 ); }static inline void io_pgtable_tlb_add_flush (struct io_pgtable *iop,unsigned long iova,size_t size,size_t granule,bool leaf) { iop->cfg.tlb->tlb_add_flush (iova, size, granule, leaf, iop->cookie); - iop->tlb_sync_pending = true; +atomic_set_release (&iop->tlb_sync_pending,1 ); }static inline void io_pgtable_tlb_sync (struct io_pgtable *iop) { -if (iop->tlb_sync_pending) { +if (atomic_xchg_relaxed (&iop->tlb_sync_pending,0 )) iop->cfg.tlb->tlb_sync (iop->cookie); - iop->tlb_sync_pending = false; - } }/**