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

Commit 2e5dacb7 authored by Shrenuj Bansal's avatar Shrenuj Bansal
Browse files

msm: kgsl: when unmapping from the mmu flush the entire tlb



Flushes the entire tlb when calling mmu_unmap to make sure there
is no race condition between unmapping and freeing the pages.

Change-Id: I911f8479a3aef2006f9df40a3419284423937542
Signed-off-by: default avatarShrenuj Bansal <shrenujb@codeaurora.org>
parent 4ae4d503
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -68,6 +68,11 @@ static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {

static struct iommu_access_ops *iommu_access_ops;

static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
		uint32_t flags);
static phys_addr_t
kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu);

static void _iommu_lock(struct kgsl_iommu const *iommu)
{
	if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
@@ -1681,9 +1686,11 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt,
		struct kgsl_memdesc *memdesc,
		unsigned int *tlb_flags)
{
	int ret;
	int ret = 0, lock_taken = 0;
	unsigned int range = memdesc->size;
	struct kgsl_iommu_pt *iommu_pt = pt->priv;
	struct kgsl_device *device = pt->mmu->device;
	struct kgsl_iommu *iommu = pt->mmu->priv;

	/* All GPU addresses as assigned are page aligned, but some
	   functions purturb the gpuaddr with an offset, so apply the
@@ -1698,18 +1705,38 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt,
		range += PAGE_SIZE;

	ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range);
	if (ret)
	if (ret) {
		KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed "
			"with err: %d\n", iommu_pt->domain, gpuaddr,
			range, ret);
		return ret;
	}

	/*
	 * Flushing only required if per process pagetables are used. With
	 * global case, flushing will happen inside iommu_map function
	 * Check to see if the current thread already holds the device mutex.
	 * If it does not, then take the device mutex which is required for
	 * flushing the tlb
	 */
	if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
		*tlb_flags = UINT_MAX;
	return 0;
	if (!mutex_is_locked(&device->mutex) ||
		device->mutex.owner != current) {
		mutex_lock(&device->mutex);
		lock_taken = 1;
	}

	/*
	 * Flush the tlb only if the iommu device is attached and the pagetable
	 * hasn't been switched yet
	 */
	if (kgsl_mmu_is_perprocess(pt->mmu) &&
		iommu->iommu_units[0].dev[KGSL_IOMMU_CONTEXT_USER].attached &&
		kgsl_iommu_pt_equal(pt->mmu, pt,
		kgsl_iommu_get_current_ptbase(pt->mmu)))
		kgsl_iommu_default_setstate(pt->mmu, KGSL_MMUFLAGS_TLBFLUSH);

	if (lock_taken)
		mutex_unlock(&device->mutex);

	return ret;
}

static int