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

Commit f472e823 authored by Olav Haugan's avatar Olav Haugan
Browse files

iommu: msm: Refactor use of remote spinlock



The remote spinlock was originally meant to synchronize access between
GPU and CPU accessing SMMU. However, there are more use cases that
this remote spinlock serves. This change decouples the spinlock from
GPU and adds support for taking the spinlock only for SMMUs that are
specified in the device tree.

CRs-fixed: 517873
Change-Id: Ic50992d0d1a102fbd05855e09e254e627f99ec33
Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
parent 79f95400
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -150,8 +150,8 @@ struct iommu_access_ops {
	int (*iommu_clk_on)(struct msm_iommu_drvdata *);
	void (*iommu_clk_off)(struct msm_iommu_drvdata *);
	void * (*iommu_lock_initialize)(void);
	void (*iommu_lock_acquire)(void);
	void (*iommu_lock_release)(void);
	void (*iommu_lock_acquire)(unsigned int need_extra_lock);
	void (*iommu_lock_release)(unsigned int need_extra_lock);
};

void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
@@ -283,16 +283,18 @@ static inline struct iommu_access_ops *msm_get_iommu_access_ops(void)
#endif

#ifdef CONFIG_MSM_IOMMU_SYNC
void msm_iommu_remote_p0_spin_lock(void);
void msm_iommu_remote_p0_spin_unlock(void);
void msm_iommu_remote_p0_spin_lock(unsigned int need_lock);
void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock);

#define msm_iommu_remote_lock_init() _msm_iommu_remote_spin_lock_init()
#define msm_iommu_remote_spin_lock() msm_iommu_remote_p0_spin_lock()
#define msm_iommu_remote_spin_unlock() msm_iommu_remote_p0_spin_unlock()
#define msm_iommu_remote_spin_lock(need_lock) \
				msm_iommu_remote_p0_spin_lock(need_lock)
#define msm_iommu_remote_spin_unlock(need_lock) \
				msm_iommu_remote_p0_spin_unlock(need_lock)
#else
#define msm_iommu_remote_lock_init()
#define msm_iommu_remote_spin_lock()
#define msm_iommu_remote_spin_unlock()
#define msm_iommu_remote_spin_lock(need_lock)
#define msm_iommu_remote_spin_unlock(need_lock)
#endif

#ifdef CONFIG_MSM_IOMMU
+20 −10
Original line number Diff line number Diff line
@@ -72,16 +72,18 @@ static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {

static struct iommu_access_ops *iommu_access_ops;

static void _iommu_lock(void)
static void _iommu_lock(struct kgsl_iommu const *iommu)
{
	if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
		iommu_access_ops->iommu_lock_acquire();
		iommu_access_ops->iommu_lock_acquire(
						iommu->sync_lock_initialized);
}

static void _iommu_unlock(void)
static void _iommu_unlock(struct kgsl_iommu const *iommu)
{
	if (iommu_access_ops && iommu_access_ops->iommu_lock_release)
		iommu_access_ops->iommu_lock_release();
		iommu_access_ops->iommu_lock_release(
						iommu->sync_lock_initialized);
}

struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -924,6 +926,8 @@ static int kgsl_iommu_start_sync_lock(struct kgsl_mmu *mmu)
	return 0;
}

#ifdef CONFIG_MSM_IOMMU_GPU_SYNC

/*
 * kgsl_get_sync_lock - Init Sync Lock between GPU and CPU
 * @mmu - Pointer to mmu device
@@ -991,6 +995,12 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)

	return status;
}
#else
static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
{
	return 0;
}
#endif

/*
 * kgsl_iommu_sync_lock - Acquire Sync Lock between GPU and CPU
@@ -1673,7 +1683,7 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
	 * changing pagetables we can use this lsb value of the pagetable w/o
	 * having to read it again
	 */
	_iommu_lock();
	_iommu_lock(iommu);
	for (i = 0; i < iommu->unit_count; i++) {
		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
		for (j = 0; j < iommu_unit->dev_count; j++) {
@@ -1712,7 +1722,7 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
		}
	}
	kgsl_iommu_lock_rb_in_tlb(mmu);
	_iommu_unlock();
	_iommu_unlock(iommu);

	/* For complete CFF */
	kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr +
@@ -1818,7 +1828,7 @@ void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu)
			for (j = 0; j < iommu_unit->dev_count; j++) {
				if (iommu_unit->dev[j].fault) {
					kgsl_iommu_enable_clk(mmu, j);
					_iommu_lock();
					_iommu_lock(iommu);
					KGSL_IOMMU_SET_CTX_REG(iommu,
						iommu_unit,
						iommu_unit->dev[j].ctx_id,
@@ -1827,7 +1837,7 @@ void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu)
						iommu_unit,
						iommu_unit->dev[j].ctx_id,
						FSR, 0);
					_iommu_unlock();
					_iommu_unlock(iommu);
					iommu_unit->dev[j].fault = 0;
				}
			}
@@ -1952,7 +1962,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
	}

	/* Acquire GPU-CPU sync Lock here */
	_iommu_lock();
	_iommu_lock(iommu);

	if (flags & KGSL_MMUFLAGS_PTUPDATE) {
		if (!msm_soc_version_supports_iommu_v0()) {
@@ -2022,7 +2032,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
	}
unlock:
	/* Release GPU-CPU sync Lock here */
	_iommu_unlock();
	_iommu_unlock(iommu);

	/* Disable smmu clock */
	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
+29 −20
Original line number Diff line number Diff line
@@ -83,8 +83,11 @@ static void _msm_iommu_remote_spin_lock_init(void)
			sizeof(*msm_iommu_remote_lock.lock));
}

void msm_iommu_remote_p0_spin_lock(void)
void msm_iommu_remote_p0_spin_lock(unsigned int need_lock)
{
	if (!need_lock)
		return;

	msm_iommu_remote_lock.lock->flag[PROC_APPS] = 1;
	msm_iommu_remote_lock.lock->turn = 1;

@@ -95,8 +98,11 @@ void msm_iommu_remote_p0_spin_lock(void)
		cpu_relax();
}

void msm_iommu_remote_p0_spin_unlock(void)
void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock)
{
	if (!need_lock)
		return;

	smp_mb();

	msm_iommu_remote_lock.lock->flag[PROC_APPS] = 0;
@@ -192,15 +198,15 @@ static void *_iommu_lock_initialize(void)
	return msm_iommu_lock_initialize();
}

static void _iommu_lock_acquire(void)
static void _iommu_lock_acquire(unsigned int need_extra_lock)
{
	msm_iommu_mutex_lock();
	msm_iommu_remote_spin_lock();
	msm_iommu_remote_spin_lock(need_extra_lock);
}

static void _iommu_lock_release(void)
static void _iommu_lock_release(unsigned int need_extra_lock)
{
	msm_iommu_remote_spin_unlock();
	msm_iommu_remote_spin_unlock(need_extra_lock);
	msm_iommu_mutex_unlock();
}

@@ -235,7 +241,7 @@ static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
		if (ret)
			goto fail;

		msm_iommu_remote_spin_lock();
		msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);

		asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
					   ctx_drvdata->num);
@@ -244,7 +250,7 @@ static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
			   asid | (va & TLBIVA_VA));
		mb();

		msm_iommu_remote_spin_unlock();
		msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);

		__disable_clocks(iommu_drvdata);
	}
@@ -272,7 +278,7 @@ static int __flush_iotlb(struct iommu_domain *domain)
		if (ret)
			goto fail;

		msm_iommu_remote_spin_lock();
		msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);

		asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
					   ctx_drvdata->num);
@@ -280,7 +286,7 @@ static int __flush_iotlb(struct iommu_domain *domain)
		SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
		mb();

		msm_iommu_remote_spin_unlock();
		msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);

		__disable_clocks(iommu_drvdata);
	}
@@ -312,13 +318,16 @@ static void __reset_context(void __iomem *base, void __iomem *glb_base, int ctx)
	mb();
}

static void __program_context(void __iomem *base, void __iomem *glb_base,
static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
			      int ctx, int ncb, phys_addr_t pgtable,
			      int redirect, int ttbr_split)
{
	void __iomem *base = iommu_drvdata->base;
	void __iomem *glb_base = iommu_drvdata->glb_base;
	unsigned int prrr, nmrr;
	int i, j, found;
	msm_iommu_remote_spin_lock();

	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);

	__reset_context(base, glb_base, ctx);

@@ -410,7 +419,7 @@ static void __program_context(void __iomem *base, void __iomem *glb_base,
	SET_M(base, ctx, 1);
	mb();

	msm_iommu_remote_spin_unlock();
	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
}

static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
@@ -524,7 +533,7 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
	if (ret)
		goto unlock;

	__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
	__program_context(iommu_drvdata,
			  ctx_drvdata->num, iommu_drvdata->ncb,
			  __pa(priv->pt.fl_table), priv->pt.redirect,
			  iommu_drvdata->ttbr_split);
@@ -576,7 +585,7 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
	if (ret)
		goto unlock;

	msm_iommu_remote_spin_lock();
	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);

	SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
		    GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
@@ -584,7 +593,7 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
	__reset_context(iommu_drvdata->base, iommu_drvdata->glb_base,
			ctx_drvdata->num);

	msm_iommu_remote_spin_unlock();
	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);

	__disable_clocks(iommu_drvdata);

@@ -1245,7 +1254,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
	if (ret)
		goto fail;

	msm_iommu_remote_spin_lock();
	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);

	SET_V2PPR(base, ctx, va & V2Pxx_VA);

@@ -1261,7 +1270,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
	if (GET_FAULT(base, ctx))
		ret = 0;

	msm_iommu_remote_spin_unlock();
	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);

	__disable_clocks(iommu_drvdata);
fail:
@@ -1323,7 +1332,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
	if (ret)
		goto fail;

	msm_iommu_remote_spin_lock();
	msm_iommu_remote_spin_lock(drvdata->needs_rem_spinlock);

	fsr = GET_FSR(base, num);

@@ -1356,7 +1365,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
	} else
		ret = IRQ_NONE;

	msm_iommu_remote_spin_unlock();
	msm_iommu_remote_spin_unlock(drvdata->needs_rem_spinlock);

	__disable_clocks(drvdata);
fail:
+2 −2
Original line number Diff line number Diff line
@@ -148,12 +148,12 @@ static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
	clk_disable_unprepare(drvdata->pclk);
}

static void _iommu_lock_acquire(void)
static void _iommu_lock_acquire(unsigned int need_extra_lock)
{
	mutex_lock(&msm_iommu_lock);
}

static void _iommu_lock_release(void)
static void _iommu_lock_release(unsigned int need_extra_lock)
{
	mutex_unlock(&msm_iommu_lock);
}
+2 −2
Original line number Diff line number Diff line
@@ -176,9 +176,9 @@ static irqreturn_t iommu_pm_evt_ovfl_int_handler(int irq, void *dev_id)
		goto out;
	}

	iommu->ops->iommu_lock_acquire();
	iommu->ops->iommu_lock_acquire(1);
	iommu_pm_check_for_overflow(pmon);
	iommu->ops->iommu_lock_release();
	iommu->ops->iommu_lock_release(1);

	mutex_unlock(&pmon->lock);

Loading