mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: iommu: Synchronize access to IOMMU cfg port
Add remote spinlock that allows CPU and GPU to synchronize access to IOMMU hardware. Add usage of remote spinlock to iommu driver and add depenency on SFPB hardware mutex being enabled.` This feature is not using SFPB hardware mutex. However, SFPB hardware mutex must be enabled since the remote spinlock implementation is making use of shared memory that is normally used when SFPB hardware mutex is not enabled. Change-Id: Idc622f3484062e0721493be3cbbfb8889ed9d800 Signed-off-by: Olav Haugan <ohaugan@codeaurora.org> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
parent
d83ae276b4
commit
b36256dbbb
3 changed files with 159 additions and 1 deletions
|
@ -124,6 +124,59 @@ struct msm_iommu_ctx_drvdata {
|
|||
irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
|
||||
irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id);
|
||||
|
||||
enum {
|
||||
PROC_APPS,
|
||||
PROC_GPU,
|
||||
PROC_MAX
|
||||
};
|
||||
|
||||
/* Expose structure to allow kgsl iommu driver to use the same structure to
|
||||
* communicate to GPU the addresses of the flag and turn variables.
|
||||
*/
|
||||
struct remote_iommu_petersons_spinlock {
|
||||
uint32_t flag[PROC_MAX];
|
||||
uint32_t turn;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_IOMMU
|
||||
void *msm_iommu_lock_initialize(void);
|
||||
void msm_iommu_mutex_lock(void);
|
||||
void msm_iommu_mutex_unlock(void);
|
||||
#else
|
||||
static inline void *msm_iommu_lock_initialize(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void msm_iommu_mutex_lock(void) { }
|
||||
static inline void msm_iommu_mutex_unlock(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
|
||||
void msm_iommu_remote_p0_spin_lock(void);
|
||||
void msm_iommu_remote_p0_spin_unlock(void);
|
||||
|
||||
#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()
|
||||
#else
|
||||
#define msm_iommu_remote_lock_init()
|
||||
#define msm_iommu_remote_spin_lock()
|
||||
#define msm_iommu_remote_spin_unlock()
|
||||
#endif
|
||||
|
||||
/* Allows kgsl iommu driver to acquire lock */
|
||||
#define msm_iommu_lock() \
|
||||
do { \
|
||||
msm_iommu_mutex_lock(); \
|
||||
msm_iommu_remote_spin_lock(); \
|
||||
} while (0)
|
||||
|
||||
#define msm_iommu_unlock() \
|
||||
do { \
|
||||
msm_iommu_remote_spin_unlock(); \
|
||||
msm_iommu_mutex_unlock(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_MSM_IOMMU
|
||||
/*
|
||||
* Look up an IOMMU context device by its context name. NULL if none found.
|
||||
|
|
|
@ -25,6 +25,17 @@ config MSM_IOMMU
|
|||
|
||||
If unsure, say N here.
|
||||
|
||||
# MSM IOMMU CPU-GPU sync programming support
|
||||
config MSM_IOMMU_GPU_SYNC
|
||||
bool "MSM IOMMU CPU-GPU Sync Support"
|
||||
depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930) && MSM_IOMMU && MSM_REMOTE_SPINLOCK_SFPB
|
||||
help
|
||||
Say Y here if you want to synchronize access to IOMMU configuration
|
||||
port between CPU and GPU. CPU will grab a remote spinlock before
|
||||
accessing IOMMU configuration registers and GPU will do the same.
|
||||
|
||||
If unsure, say N here.
|
||||
|
||||
config IOMMU_PGTABLES_L2
|
||||
bool "Allow SMMU page tables in the L2 cache (Experimental)"
|
||||
depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
|
||||
/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <mach/iommu_hw-8xxx.h>
|
||||
#include <mach/iommu.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
|
||||
#define MRC(reg, processor, op1, crn, crm, op2) \
|
||||
__asm__ __volatile__ ( \
|
||||
|
@ -63,6 +64,69 @@ static int msm_iommu_tex_class[4];
|
|||
|
||||
DEFINE_MUTEX(msm_iommu_lock);
|
||||
|
||||
/**
|
||||
* Remote spinlock implementation based on Peterson's algorithm to be used
|
||||
* to synchronize IOMMU config port access between CPU and GPU.
|
||||
* This implements Process 0 of the spin lock algorithm. GPU implements
|
||||
* Process 1. Flag and turn is stored in shared memory to allow GPU to
|
||||
* access these.
|
||||
*/
|
||||
struct msm_iommu_remote_lock {
|
||||
int initialized;
|
||||
struct remote_iommu_petersons_spinlock *lock;
|
||||
};
|
||||
|
||||
static struct msm_iommu_remote_lock msm_iommu_remote_lock;
|
||||
|
||||
#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
|
||||
static void _msm_iommu_remote_spin_lock_init(void)
|
||||
{
|
||||
msm_iommu_remote_lock.lock = smem_alloc(SMEM_SPINLOCK_ARRAY, 32);
|
||||
memset(msm_iommu_remote_lock.lock, 0,
|
||||
sizeof(*msm_iommu_remote_lock.lock));
|
||||
}
|
||||
|
||||
void msm_iommu_remote_p0_spin_lock(void)
|
||||
{
|
||||
msm_iommu_remote_lock.lock->flag[PROC_APPS] = 1;
|
||||
msm_iommu_remote_lock.lock->turn = 1;
|
||||
|
||||
smp_mb();
|
||||
|
||||
while (msm_iommu_remote_lock.lock->flag[PROC_GPU] == 1 &&
|
||||
msm_iommu_remote_lock.lock->turn == 1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
void msm_iommu_remote_p0_spin_unlock(void)
|
||||
{
|
||||
smp_mb();
|
||||
|
||||
msm_iommu_remote_lock.lock->flag[PROC_APPS] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void msm_iommu_mutex_lock(void)
|
||||
{
|
||||
mutex_lock(&msm_iommu_lock);
|
||||
}
|
||||
|
||||
inline void msm_iommu_mutex_unlock(void)
|
||||
{
|
||||
mutex_unlock(&msm_iommu_lock);
|
||||
}
|
||||
|
||||
void *msm_iommu_lock_initialize(void)
|
||||
{
|
||||
mutex_lock(&msm_iommu_lock);
|
||||
if (!msm_iommu_remote_lock.initialized) {
|
||||
msm_iommu_remote_lock_init();
|
||||
msm_iommu_remote_lock.initialized = 1;
|
||||
}
|
||||
mutex_unlock(&msm_iommu_lock);
|
||||
return msm_iommu_remote_lock.lock;
|
||||
}
|
||||
|
||||
struct msm_priv {
|
||||
unsigned long *pgtable;
|
||||
int redirect;
|
||||
|
@ -113,12 +177,17 @@ static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
|
||||
ctx_drvdata->num);
|
||||
|
||||
SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
|
||||
asid | (va & TLBIVA_VA));
|
||||
mb();
|
||||
|
||||
msm_iommu_remote_spin_unlock();
|
||||
|
||||
__disable_clocks(iommu_drvdata);
|
||||
}
|
||||
fail:
|
||||
|
@ -145,11 +214,16 @@ static int __flush_iotlb(struct iommu_domain *domain)
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
|
||||
ctx_drvdata->num);
|
||||
|
||||
SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
|
||||
mb();
|
||||
|
||||
msm_iommu_remote_spin_unlock();
|
||||
|
||||
__disable_clocks(iommu_drvdata);
|
||||
}
|
||||
fail:
|
||||
|
@ -186,6 +260,9 @@ static void __program_context(void __iomem *base, int ctx, int ncb,
|
|||
{
|
||||
unsigned int prrr, nmrr;
|
||||
int i, j, found;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
__reset_context(base, ctx);
|
||||
|
||||
/* Set up HTW mode */
|
||||
|
@ -275,6 +352,8 @@ static void __program_context(void __iomem *base, int ctx, int ncb,
|
|||
/* Enable the MMU */
|
||||
SET_M(base, ctx, 1);
|
||||
mb();
|
||||
|
||||
msm_iommu_remote_spin_unlock();
|
||||
}
|
||||
|
||||
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
|
||||
|
@ -414,10 +493,15 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
SET_TLBIASID(iommu_drvdata->base, ctx_dev->num,
|
||||
GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_dev->num));
|
||||
|
||||
__reset_context(iommu_drvdata->base, ctx_dev->num);
|
||||
|
||||
msm_iommu_remote_spin_unlock();
|
||||
|
||||
__disable_clocks(iommu_drvdata);
|
||||
list_del_init(&ctx_drvdata->attached_elm);
|
||||
ctx_drvdata->attached_domain = NULL;
|
||||
|
@ -917,6 +1001,8 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
SET_V2PPR(base, ctx, va & V2Pxx_VA);
|
||||
|
||||
mb();
|
||||
|
@ -931,6 +1017,8 @@ 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();
|
||||
|
||||
__disable_clocks(iommu_drvdata);
|
||||
fail:
|
||||
mutex_unlock(&msm_iommu_lock);
|
||||
|
@ -991,6 +1079,8 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
msm_iommu_remote_spin_lock();
|
||||
|
||||
fsr = GET_FSR(base, num);
|
||||
|
||||
if (fsr) {
|
||||
|
@ -1017,6 +1107,8 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
|
|||
} else
|
||||
ret = IRQ_NONE;
|
||||
|
||||
msm_iommu_remote_spin_unlock();
|
||||
|
||||
__disable_clocks(drvdata);
|
||||
fail:
|
||||
mutex_unlock(&msm_iommu_lock);
|
||||
|
@ -1087,6 +1179,8 @@ static int __init msm_iommu_init(void)
|
|||
if (!msm_soc_version_supports_iommu_v1())
|
||||
return -ENODEV;
|
||||
|
||||
msm_iommu_lock_initialize();
|
||||
|
||||
setup_iommu_tex_classes();
|
||||
bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue