]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - arch/powerpc/platforms/pseries/iommu.c
powerpc/pseries: Disable interrupts around IOMMU percpu data accesses
[linux-imx.git] / 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,