Loading drivers/iommu/arm-smmu.c +52 −48 Original line number Diff line number Diff line Loading @@ -1059,50 +1059,57 @@ static void arm_smmu_secure_pool_destroy(struct arm_smmu_domain *smmu_domain) } } static void *arm_smmu_alloc_pages_exact(void *cookie, int order, gfp_t gfp_mask) static void *arm_smmu_alloc_pgtable(void *cookie, int order, gfp_t gfp_mask) { int ret; void *page; struct page *page; void *page_addr; size_t size = (1UL << order) * PAGE_SIZE; struct arm_smmu_domain *smmu_domain = cookie; if (!arm_smmu_has_secure_vmid(smmu_domain)) { struct page *pg; /* size is expected to be 4K with current configuration */ if (size == PAGE_SIZE) { pg = list_first_entry_or_null( page = list_first_entry_or_null( &smmu_domain->nonsecure_pool, struct page, lru); if (pg) { list_del_init(&pg->lru); return page_address(pg); if (page) { list_del_init(&page->lru); return page_address(page); } } return alloc_pages_exact(size, gfp_mask); page = alloc_pages(gfp_mask, order); if (!page) return NULL; return page_address(page); } page = arm_smmu_secure_pool_remove(smmu_domain, size); if (page) return page; page_addr = arm_smmu_secure_pool_remove(smmu_domain, size); if (page_addr) return page_addr; page = alloc_pages_exact(size, gfp_mask); if (page) { ret = arm_smmu_prepare_pgtable(page, cookie); page = alloc_pages(gfp_mask, order); if (!page) return NULL; page_addr = page_address(page); ret = arm_smmu_prepare_pgtable(page_addr, cookie); if (ret) { free_pages_exact(page, size); free_pages((unsigned long)page_addr, order); return NULL; } } return page; return page_addr; } static void arm_smmu_free_pages_exact(void *cookie, void *virt, int order) static void arm_smmu_free_pgtable(void *cookie, void *virt, int order) { struct arm_smmu_domain *smmu_domain = cookie; size_t size = (1UL << order) * PAGE_SIZE; if (!arm_smmu_has_secure_vmid(smmu_domain)) { free_pages_exact(virt, size); free_pages((unsigned long)virt, order); return; } Loading @@ -1111,43 +1118,39 @@ static void arm_smmu_free_pages_exact(void *cookie, void *virt, int order) } static const struct iommu_pgtable_ops arm_smmu_pgtable_ops = { .alloc_pgtable = arm_smmu_alloc_pages_exact, .free_pgtable = arm_smmu_free_pages_exact, .alloc_pgtable = arm_smmu_alloc_pgtable, .free_pgtable = arm_smmu_free_pgtable, }; #define ARM_SMMU_INIT_MSM_TLB_OPS(_tlb_flush_all) \ {\ .tlb_ops = { \ .tlb_flush_all = _tlb_flush_all, \ .tlb_flush_walk = arm_smmu_tlb_inv_walk, \ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, \ .tlb_add_page = arm_smmu_tlb_add_page, \ } \ } #define ARM_SMMU_MSM_TLB_OPS_S1 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s1) #define ARM_SMMU_MSM_TLB_OPS_S2_V2 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s2) #define ARM_SMMU_MSM_TLB_OPS_S2_V1 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s2) static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = { .tlb = ARM_SMMU_MSM_TLB_OPS_S1, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s1, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_range_s1, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = { .tlb = ARM_SMMU_MSM_TLB_OPS_S2_V2, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_range_s2, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb = ARM_SMMU_MSM_TLB_OPS_S2_V1, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_vmid_nosync, .tlb_sync = arm_smmu_tlb_sync_vmid, }; Loading Loading @@ -2176,7 +2179,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .ias = ias, .oas = oas, .coherent_walk = is_iommu_pt_coherent(smmu_domain), .tlb = &smmu_domain->flush_ops->tlb.tlb_ops, .tlb = &smmu_domain->flush_ops->tlb, .iommu_pgtable_ops = &arm_smmu_pgtable_ops, .iommu_dev = smmu->dev, }; Loading Loading @@ -2748,7 +2751,8 @@ static void arm_smmu_unassign_table(struct arm_smmu_domain *smmu_domain) if (WARN_ON(ret)) break; free_pages_exact(pte_info->virt_addr, pte_info->size); free_pages((unsigned long)pte_info->virt_addr, get_order(pte_info->size)); } list_for_each_entry_safe(pte_info, temp, &smmu_domain->unassign_list, Loading Loading @@ -3242,7 +3246,7 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) arm_smmu_rpm_put(smmu); return; } smmu_domain->flush_ops->tlb.tlb_ops.tlb_flush_all(smmu_domain); smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); arm_smmu_domain_power_off(domain, smmu); arm_smmu_rpm_put(smmu); } Loading drivers/iommu/arm-smmu.h +1 −1 Original line number Diff line number Diff line Loading @@ -461,7 +461,7 @@ enum arm_smmu_domain_stage { }; struct arm_smmu_flush_ops { struct msm_iommu_flush_ops tlb; struct iommu_flush_ops tlb; void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie); void (*tlb_sync)(void *cookie); Loading drivers/iommu/io-pgtable.c +0 −30 Original line number Diff line number Diff line Loading @@ -114,36 +114,6 @@ static void mod_pages_allocated(int nr_pages) } #endif void *io_pgtable_alloc_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, size_t size, gfp_t gfp_mask) { void *ret; struct msm_iommu_flush_ops *ops = to_msm_iommu_flush_ops(cfg->tlb); if (ops->alloc_pages_exact) ret = ops->alloc_pages_exact(cookie, size, gfp_mask); else ret = alloc_pages_exact(size, gfp_mask); if (likely(ret)) mod_pages_allocated(1 << get_order(size)); return ret; } void io_pgtable_free_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, void *virt, size_t size) { struct msm_iommu_flush_ops *ops = to_msm_iommu_flush_ops(cfg->tlb); if (ops->free_pages_exact) ops->free_pages_exact(cookie, virt, size); else free_pages_exact(virt, size); mod_pages_allocated(-(1 << get_order(size))); } void *io_pgtable_alloc_pages(struct io_pgtable_cfg *cfg, void *cookie, int order, gfp_t gfp_mask) { Loading include/linux/io-pgtable.h +0 −17 Original line number Diff line number Diff line Loading @@ -7,8 +7,6 @@ #include <linux/scatterlist.h> #define to_msm_iommu_flush_ops(_tlb_ops) \ container_of(_tlb_ops, struct msm_iommu_flush_ops, tlb_ops) #define to_msm_io_pgtable_info(_cfg) \ container_of(_cfg, struct msm_io_pgtable_info, pgtbl_cfg) Loading Loading @@ -56,21 +54,6 @@ struct iommu_flush_ops { unsigned long iova, size_t granule, void *cookie); }; /** * struct msm_iommu_flush_ops - MSM and standard IOMMU callbacks for TLB and * page table management. * * @alloc_pages_exact: Allocate page table memory (optional, defaults to * alloc_pages_exact) * @free_pages_exact: Free page table memory (optional, defaults to * free_pages_exact) */ struct msm_iommu_flush_ops { void *(*alloc_pages_exact)(void *cookie, size_t size, gfp_t gfp_mask); void (*free_pages_exact)(void *cookie, void *virt, size_t size); const struct iommu_flush_ops tlb_ops; }; /** * struct iommu_pgtable_ops - IOMMU callbacks for page table memory management. * Loading Loading
drivers/iommu/arm-smmu.c +52 −48 Original line number Diff line number Diff line Loading @@ -1059,50 +1059,57 @@ static void arm_smmu_secure_pool_destroy(struct arm_smmu_domain *smmu_domain) } } static void *arm_smmu_alloc_pages_exact(void *cookie, int order, gfp_t gfp_mask) static void *arm_smmu_alloc_pgtable(void *cookie, int order, gfp_t gfp_mask) { int ret; void *page; struct page *page; void *page_addr; size_t size = (1UL << order) * PAGE_SIZE; struct arm_smmu_domain *smmu_domain = cookie; if (!arm_smmu_has_secure_vmid(smmu_domain)) { struct page *pg; /* size is expected to be 4K with current configuration */ if (size == PAGE_SIZE) { pg = list_first_entry_or_null( page = list_first_entry_or_null( &smmu_domain->nonsecure_pool, struct page, lru); if (pg) { list_del_init(&pg->lru); return page_address(pg); if (page) { list_del_init(&page->lru); return page_address(page); } } return alloc_pages_exact(size, gfp_mask); page = alloc_pages(gfp_mask, order); if (!page) return NULL; return page_address(page); } page = arm_smmu_secure_pool_remove(smmu_domain, size); if (page) return page; page_addr = arm_smmu_secure_pool_remove(smmu_domain, size); if (page_addr) return page_addr; page = alloc_pages_exact(size, gfp_mask); if (page) { ret = arm_smmu_prepare_pgtable(page, cookie); page = alloc_pages(gfp_mask, order); if (!page) return NULL; page_addr = page_address(page); ret = arm_smmu_prepare_pgtable(page_addr, cookie); if (ret) { free_pages_exact(page, size); free_pages((unsigned long)page_addr, order); return NULL; } } return page; return page_addr; } static void arm_smmu_free_pages_exact(void *cookie, void *virt, int order) static void arm_smmu_free_pgtable(void *cookie, void *virt, int order) { struct arm_smmu_domain *smmu_domain = cookie; size_t size = (1UL << order) * PAGE_SIZE; if (!arm_smmu_has_secure_vmid(smmu_domain)) { free_pages_exact(virt, size); free_pages((unsigned long)virt, order); return; } Loading @@ -1111,43 +1118,39 @@ static void arm_smmu_free_pages_exact(void *cookie, void *virt, int order) } static const struct iommu_pgtable_ops arm_smmu_pgtable_ops = { .alloc_pgtable = arm_smmu_alloc_pages_exact, .free_pgtable = arm_smmu_free_pages_exact, .alloc_pgtable = arm_smmu_alloc_pgtable, .free_pgtable = arm_smmu_free_pgtable, }; #define ARM_SMMU_INIT_MSM_TLB_OPS(_tlb_flush_all) \ {\ .tlb_ops = { \ .tlb_flush_all = _tlb_flush_all, \ .tlb_flush_walk = arm_smmu_tlb_inv_walk, \ .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, \ .tlb_add_page = arm_smmu_tlb_add_page, \ } \ } #define ARM_SMMU_MSM_TLB_OPS_S1 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s1) #define ARM_SMMU_MSM_TLB_OPS_S2_V2 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s2) #define ARM_SMMU_MSM_TLB_OPS_S2_V1 \ ARM_SMMU_INIT_MSM_TLB_OPS(arm_smmu_tlb_inv_context_s2) static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = { .tlb = ARM_SMMU_MSM_TLB_OPS_S1, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s1, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_range_s1, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = { .tlb = ARM_SMMU_MSM_TLB_OPS_S2_V2, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_range_s2, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb = ARM_SMMU_MSM_TLB_OPS_S2_V1, .tlb = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, }, .tlb_inv_range = arm_smmu_tlb_inv_vmid_nosync, .tlb_sync = arm_smmu_tlb_sync_vmid, }; Loading Loading @@ -2176,7 +2179,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .ias = ias, .oas = oas, .coherent_walk = is_iommu_pt_coherent(smmu_domain), .tlb = &smmu_domain->flush_ops->tlb.tlb_ops, .tlb = &smmu_domain->flush_ops->tlb, .iommu_pgtable_ops = &arm_smmu_pgtable_ops, .iommu_dev = smmu->dev, }; Loading Loading @@ -2748,7 +2751,8 @@ static void arm_smmu_unassign_table(struct arm_smmu_domain *smmu_domain) if (WARN_ON(ret)) break; free_pages_exact(pte_info->virt_addr, pte_info->size); free_pages((unsigned long)pte_info->virt_addr, get_order(pte_info->size)); } list_for_each_entry_safe(pte_info, temp, &smmu_domain->unassign_list, Loading Loading @@ -3242,7 +3246,7 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) arm_smmu_rpm_put(smmu); return; } smmu_domain->flush_ops->tlb.tlb_ops.tlb_flush_all(smmu_domain); smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); arm_smmu_domain_power_off(domain, smmu); arm_smmu_rpm_put(smmu); } Loading
drivers/iommu/arm-smmu.h +1 −1 Original line number Diff line number Diff line Loading @@ -461,7 +461,7 @@ enum arm_smmu_domain_stage { }; struct arm_smmu_flush_ops { struct msm_iommu_flush_ops tlb; struct iommu_flush_ops tlb; void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie); void (*tlb_sync)(void *cookie); Loading
drivers/iommu/io-pgtable.c +0 −30 Original line number Diff line number Diff line Loading @@ -114,36 +114,6 @@ static void mod_pages_allocated(int nr_pages) } #endif void *io_pgtable_alloc_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, size_t size, gfp_t gfp_mask) { void *ret; struct msm_iommu_flush_ops *ops = to_msm_iommu_flush_ops(cfg->tlb); if (ops->alloc_pages_exact) ret = ops->alloc_pages_exact(cookie, size, gfp_mask); else ret = alloc_pages_exact(size, gfp_mask); if (likely(ret)) mod_pages_allocated(1 << get_order(size)); return ret; } void io_pgtable_free_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, void *virt, size_t size) { struct msm_iommu_flush_ops *ops = to_msm_iommu_flush_ops(cfg->tlb); if (ops->free_pages_exact) ops->free_pages_exact(cookie, virt, size); else free_pages_exact(virt, size); mod_pages_allocated(-(1 << get_order(size))); } void *io_pgtable_alloc_pages(struct io_pgtable_cfg *cfg, void *cookie, int order, gfp_t gfp_mask) { Loading
include/linux/io-pgtable.h +0 −17 Original line number Diff line number Diff line Loading @@ -7,8 +7,6 @@ #include <linux/scatterlist.h> #define to_msm_iommu_flush_ops(_tlb_ops) \ container_of(_tlb_ops, struct msm_iommu_flush_ops, tlb_ops) #define to_msm_io_pgtable_info(_cfg) \ container_of(_cfg, struct msm_io_pgtable_info, pgtbl_cfg) Loading Loading @@ -56,21 +54,6 @@ struct iommu_flush_ops { unsigned long iova, size_t granule, void *cookie); }; /** * struct msm_iommu_flush_ops - MSM and standard IOMMU callbacks for TLB and * page table management. * * @alloc_pages_exact: Allocate page table memory (optional, defaults to * alloc_pages_exact) * @free_pages_exact: Free page table memory (optional, defaults to * free_pages_exact) */ struct msm_iommu_flush_ops { void *(*alloc_pages_exact)(void *cookie, size_t size, gfp_t gfp_mask); void (*free_pages_exact)(void *cookie, void *virt, size_t size); const struct iommu_flush_ops tlb_ops; }; /** * struct iommu_pgtable_ops - IOMMU callbacks for page table memory management. * Loading