powerpc/pseries: Disable interrupts around IOMMU percpu data accesses
authorAnton Blanchard <anton@samba.org>
Sun, 3 Jun 2012 19:42:13 +0000 (19:42 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 3 Jul 2012 04:14:46 +0000 (14:14 +1000)
tce_buildmulti_pSeriesLP uses a per cpu page to communicate with the
hypervisor. We currently rely on the IOMMU table spinlock but
subsequent patches will be removing that so disable interrupts
around all accesses of tce_page.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/iommu.c

index d5d1dd58ca742f4b686b8fda2837eacafd215677..07c09cbbfb19fdf1807dd0c87a5870d9a9a9cf3b 100644 (file)
@@ -192,12 +192,15 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
        long l, limit;
        long tcenum_start = tcenum, npages_start = npages;
        int ret = 0;
+       unsigned long flags;
 
        if (npages == 1) {
                return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
                                           direction, attrs);
        }
 
+       local_irq_save(flags);  /* to protect tcep and the page behind it */
+
        tcep = __get_cpu_var(tce_page);
 
        /* This is safe to do since interrupts are off when we're called
@@ -207,6 +210,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcep = (u64 *)__get_free_page(GFP_ATOMIC);
                /* If allocation fails, fall back to the loop implementation */
                if (!tcep) {
+                       local_irq_restore(flags);
                        return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
                                            direction, attrs);
                }
@@ -240,6 +244,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcenum += limit;
        } while (npages > 0 && !rc);
 
+       local_irq_restore(flags);
+
        if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
                ret = (int)rc;
                tce_freemulti_pSeriesLP(tbl, tcenum_start,