Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ad46ada authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu/arm-smmu: Remove [alloc/free]_pages_exact usage"

parents 4d8585f3 91fe85a2
Loading
Loading
Loading
Loading
+52 −48
Original line number Diff line number Diff line
@@ -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;
	}

@@ -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,
};
@@ -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,
	};
@@ -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,
@@ -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);
	}
+1 −1
Original line number Diff line number Diff line
@@ -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);
+0 −30
Original line number Diff line number Diff line
@@ -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)
{
+0 −17
Original line number Diff line number Diff line
@@ -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)

@@ -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.
 *