On Fri, Apr 10, 2015 at 04:30:57PM +1000, Alexey Kardashevskiy wrote: > This adds missing locks in iommu_take_ownership()/ > iommu_release_ownership(). > > This marks all pages busy in iommu_table::it_map in order to catch > errors if there is an attempt to use this table while ownership over it > is taken. > > This only clears TCE content if there is no page marked busy in it_map. > Clearing must be done outside of the table locks as iommu_clear_tce() > called from iommu_clear_tces_and_put_pages() does this. > > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> > --- > Changes: > v5: > * do not store bit#0 value, it has to be set for zero-based table > anyway > * removed test_and_clear_bit > --- > arch/powerpc/kernel/iommu.c | 26 ++++++++++++++++++++++---- > 1 file changed, 22 insertions(+), 4 deletions(-) > > diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c > index 7d6089b..068fe4ff 100644 > --- a/arch/powerpc/kernel/iommu.c > +++ b/arch/powerpc/kernel/iommu.c > @@ -1052,17 +1052,28 @@ EXPORT_SYMBOL_GPL(iommu_tce_build); > > static int iommu_table_take_ownership(struct iommu_table *tbl) > { > - unsigned long sz = (tbl->it_size + 7) >> 3; > + unsigned long flags, i, sz = (tbl->it_size + 7) >> 3; > + int ret = 0; > + > + spin_lock_irqsave(&tbl->large_pool.lock, flags); > + for (i = 0; i < tbl->nr_pools; i++) > + spin_lock(&tbl->pools[i].lock); > > if (tbl->it_offset == 0) > clear_bit(0, tbl->it_map); > > if (!bitmap_empty(tbl->it_map, tbl->it_size)) { > pr_err("iommu_tce: it_map is not empty"); > - return -EBUSY; > + ret = -EBUSY; > + if (tbl->it_offset == 0) > + set_bit(0, tbl->it_map);
This really needs a comment. Why on earth are you changing the it_map on a failure case? > + } else { > + memset(tbl->it_map, 0xff, sz); > } > > - memset(tbl->it_map, 0xff, sz); > + for (i = 0; i < tbl->nr_pools; i++) > + spin_unlock(&tbl->pools[i].lock); > + spin_unlock_irqrestore(&tbl->large_pool.lock, flags); > > return 0; > } > @@ -1095,7 +1106,11 @@ EXPORT_SYMBOL_GPL(iommu_take_ownership); > > static void iommu_table_release_ownership(struct iommu_table *tbl) > { > - unsigned long sz = (tbl->it_size + 7) >> 3; > + unsigned long flags, i, sz = (tbl->it_size + 7) >> 3; > + > + spin_lock_irqsave(&tbl->large_pool.lock, flags); > + for (i = 0; i < tbl->nr_pools; i++) > + spin_lock(&tbl->pools[i].lock); > > memset(tbl->it_map, 0, sz); > > @@ -1103,6 +1118,9 @@ static void iommu_table_release_ownership(struct > iommu_table *tbl) > if (tbl->it_offset == 0) > set_bit(0, tbl->it_map); > > + for (i = 0; i < tbl->nr_pools; i++) > + spin_unlock(&tbl->pools[i].lock); > + spin_unlock_irqrestore(&tbl->large_pool.lock, flags); > } > > extern void iommu_release_ownership(struct iommu_table_group *table_group) -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
pgpdLzsO_RT1i.pgp
Description: PGP signature