Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-microblaze.git] / drivers / iommu / iova.c
index 3941ed6..9e8bc80 100644 (file)
@@ -121,8 +121,6 @@ int init_iova_flush_queue(struct iova_domain *iovad,
                spin_lock_init(&fq->lock);
        }
 
-       smp_wmb();
-
        iovad->fq = queue;
 
        timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
@@ -635,10 +633,20 @@ void queue_iova(struct iova_domain *iovad,
                unsigned long pfn, unsigned long pages,
                unsigned long data)
 {
-       struct iova_fq *fq = raw_cpu_ptr(iovad->fq);
+       struct iova_fq *fq;
        unsigned long flags;
        unsigned idx;
 
+       /*
+        * Order against the IOMMU driver's pagetable update from unmapping
+        * @pte, to guarantee that iova_domain_flush() observes that if called
+        * from a different CPU before we release the lock below. Full barrier
+        * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
+        * written fq state here.
+        */
+       smp_mb();
+
+       fq = raw_cpu_ptr(iovad->fq);
        spin_lock_irqsave(&fq->lock, flags);
 
        /*