Commit c1703e85 authored by Anton Blanchard's avatar Anton Blanchard Committed by Benjamin Herrenschmidt

powerpc/pseries: Disable interrupts around IOMMU percpu data accesses

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: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent b3f271e8
...@@ -192,12 +192,15 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -192,12 +192,15 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long l, limit; long l, limit;
long tcenum_start = tcenum, npages_start = npages; long tcenum_start = tcenum, npages_start = npages;
int ret = 0; int ret = 0;
unsigned long flags;
if (npages == 1) { if (npages == 1) {
return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction, attrs); direction, attrs);
} }
local_irq_save(flags); /* to protect tcep and the page behind it */
tcep = __get_cpu_var(tce_page); tcep = __get_cpu_var(tce_page);
/* This is safe to do since interrupts are off when we're called /* 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, ...@@ -207,6 +210,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcep = (u64 *)__get_free_page(GFP_ATOMIC); tcep = (u64 *)__get_free_page(GFP_ATOMIC);
/* If allocation fails, fall back to the loop implementation */ /* If allocation fails, fall back to the loop implementation */
if (!tcep) { if (!tcep) {
local_irq_restore(flags);
return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction, attrs); direction, attrs);
} }
...@@ -240,6 +244,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, ...@@ -240,6 +244,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum += limit; tcenum += limit;
} while (npages > 0 && !rc); } while (npages > 0 && !rc);
local_irq_restore(flags);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc; ret = (int)rc;
tce_freemulti_pSeriesLP(tbl, tcenum_start, tce_freemulti_pSeriesLP(tbl, tcenum_start,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment