@@ -166,7 +166,7 @@ static inline bool iopte_leaf(arm_lpae_iopte pte, int lvl,
/* Generic functions */
void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
- arm_lpae_iopte *ptep);
+ arm_lpae_iopte *ptep, bool only_children);
int arm_lpae_init_pgtable(struct io_pgtable_cfg *cfg,
struct arm_lpae_io_pgtable *data);
@@ -299,7 +299,7 @@ int arm_lpae_map_pages(struct io_pgtable *iop, unsigned long iova,
}
void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
- arm_lpae_iopte *ptep)
+ arm_lpae_iopte *ptep, bool only_children)
{
arm_lpae_iopte *start, *end;
unsigned long table_size;
@@ -323,10 +323,12 @@ void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
if (!pte || iopte_leaf(pte, lvl, data->iop.cfg.fmt))
continue;
- __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+ __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data),
+ false);
}
- __arm_lpae_free_pages(start, table_size, &data->iop.cfg);
+ if (!only_children)
+ __arm_lpae_free_pages(start, table_size, &data->iop.cfg);
}
static size_t arm_lpae_split_blk_unmap(struct io_pgtable *iop,
@@ -428,7 +430,8 @@ static size_t __arm_lpae_unmap(struct io_pgtable *iop,
/* Also flush any partial walks */
io_pgtable_tlb_flush_walk(cfg, iop, iova + i * size, size,
ARM_LPAE_GRANULE(data));
- __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+ __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data),
+ false);
} else if (!iommu_iotlb_gather_queued(gather)) {
io_pgtable_tlb_add_page(cfg, iop, gather,
iova + i * size, size);
@@ -84,7 +84,7 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
{
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(iop->ops);
- __arm_lpae_free_pgtable(data, data->start_level, iop->pgd);
+ __arm_lpae_free_pgtable(data, data->start_level, iop->pgd, false);
kfree(data);
}
The hypervisor side of io-pgtable-arm needs to free the top-level page table separately from the other tables (which are page-sized and will use a page queue). Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> --- include/linux/io-pgtable-arm.h | 2 +- drivers/iommu/io-pgtable-arm-common.c | 11 +++++++---- drivers/iommu/io-pgtable-arm.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-)