On Fri, 2015-04-10 at 16:30 +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;
This error is never returned. > + if (tbl->it_offset == 0) > + set_bit(0, tbl->it_map); > + } 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) _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev