Merge "msm: kgsl: Map GPU QDSS STM through GPU IOMMU"

This commit is contained in:
Linux Build Service Account 2016-07-27 19:27:07 -07:00 committed by Gerrit - the friendly Code Review server
commit 608c991c8e
7 changed files with 122 additions and 0 deletions

View file

@ -138,6 +138,11 @@ Optional Properties:
Specify the size of snapshot in bytes. This will override
snapshot size defined in the driver code.
- qcom,gpu-qdss-stm:
<baseAddr size>
baseAddr - base address of the gpu channels in the qdss stm memory region
size - size of the gpu stm region
GPU Quirks:
- qcom,gpu-quirk-two-pass-use-wfi:
Signal the GPU to set Set TWOPASSUSEWFI bit in

View file

@ -1760,6 +1760,30 @@ static int adreno_getproperty(struct kgsl_device *device,
status = 0;
}
break;
case KGSL_PROP_DEVICE_QDSS_STM:
{
struct kgsl_qdss_stm_prop qdssprop = {0};
struct kgsl_memdesc *qdss_desc =
kgsl_mmu_get_qdss_global_entry(device);
if (sizebytes != sizeof(qdssprop)) {
status = -EINVAL;
break;
}
if (qdss_desc) {
qdssprop.gpuaddr = qdss_desc->gpuaddr;
qdssprop.size = qdss_desc->size;
}
if (copy_to_user(value, &qdssprop,
sizeof(qdssprop))) {
status = -EFAULT;
break;
}
status = 0;
}
break;
case KGSL_PROP_MMU_ENABLE:
{
/* Report MMU only if we can handle paged memory */

View file

@ -89,6 +89,30 @@ int adreno_getproperty_compat(struct kgsl_device *device,
status = 0;
}
break;
case KGSL_PROP_DEVICE_QDSS_STM:
{
struct kgsl_qdss_stm_prop qdssprop = {0};
struct kgsl_memdesc *qdss_desc =
kgsl_mmu_get_qdss_global_entry(device);
if (sizebytes != sizeof(qdssprop)) {
status = -EINVAL;
break;
}
if (qdss_desc) {
qdssprop.gpuaddr = qdss_desc->gpuaddr;
qdssprop.size = qdss_desc->size;
}
if (copy_to_user(value, &qdssprop,
sizeof(qdssprop))) {
status = -EFAULT;
break;
}
status = 0;
}
break;
default:
/*
* Call the adreno_getproperty to check if the property type

View file

@ -96,6 +96,7 @@ static struct kgsl_memdesc *global_pt_entries[GLOBAL_PT_ENTRIES];
static struct kgsl_memdesc *kgsl_global_secure_pt_entry;
static int global_pt_count;
uint64_t global_pt_alloc;
static struct kgsl_memdesc gpu_qdss_desc;
static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable)
{
@ -183,6 +184,51 @@ void kgsl_add_global_secure_entry(struct kgsl_device *device,
kgsl_global_secure_pt_entry = memdesc;
}
struct kgsl_memdesc *kgsl_iommu_get_qdss_global_entry(void)
{
return &gpu_qdss_desc;
}
static void kgsl_setup_qdss_desc(struct kgsl_device *device)
{
int result = 0;
uint32_t gpu_qdss_entry[2];
if (!of_find_property(device->pdev->dev.of_node,
"qcom,gpu-qdss-stm", NULL))
return;
if (of_property_read_u32_array(device->pdev->dev.of_node,
"qcom,gpu-qdss-stm", gpu_qdss_entry, 2)) {
KGSL_CORE_ERR("Failed to read gpu qdss dts entry\n");
return;
}
gpu_qdss_desc.flags = 0;
gpu_qdss_desc.priv = 0;
gpu_qdss_desc.physaddr = gpu_qdss_entry[0];
gpu_qdss_desc.size = gpu_qdss_entry[1];
gpu_qdss_desc.pagetable = NULL;
gpu_qdss_desc.ops = NULL;
gpu_qdss_desc.dev = device->dev->parent;
gpu_qdss_desc.hostptr = NULL;
result = memdesc_sg_dma(&gpu_qdss_desc, gpu_qdss_desc.physaddr,
gpu_qdss_desc.size);
if (result) {
KGSL_CORE_ERR("memdesc_sg_dma failed: %d\n", result);
return;
}
kgsl_mmu_add_global(device, &gpu_qdss_desc);
}
static inline void kgsl_cleanup_qdss_desc(struct kgsl_mmu *mmu)
{
kgsl_iommu_remove_global(mmu, &gpu_qdss_desc);
kgsl_sharedmem_free(&gpu_qdss_desc);
}
static inline void _iommu_sync_mmu_pc(bool lock)
{
@ -1265,6 +1311,7 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
kgsl_iommu_remove_global(mmu, &iommu->setstate);
kgsl_sharedmem_free(&iommu->setstate);
kgsl_cleanup_qdss_desc(mmu);
}
static int _setstate_alloc(struct kgsl_device *device,
@ -1336,6 +1383,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
}
kgsl_iommu_add_global(mmu, &iommu->setstate);
kgsl_setup_qdss_desc(device);
done:
if (status)
@ -2341,6 +2389,7 @@ struct kgsl_mmu_ops kgsl_iommu_ops = {
.mmu_add_global = kgsl_iommu_add_global,
.mmu_remove_global = kgsl_iommu_remove_global,
.mmu_getpagetable = kgsl_iommu_getpagetable,
.mmu_get_qdss_global_entry = kgsl_iommu_get_qdss_global_entry,
.probe = kgsl_iommu_probe,
};

View file

@ -546,6 +546,17 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable,
}
EXPORT_SYMBOL(kgsl_mmu_gpuaddr_in_range);
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
if (MMU_OP_VALID(mmu, mmu_get_qdss_global_entry))
return mmu->mmu_ops->mmu_get_qdss_global_entry();
return NULL;
}
EXPORT_SYMBOL(kgsl_mmu_get_qdss_global_entry);
/*
* NOMMU defintions - NOMMU really just means that the MMU is kept in pass
* through and the GPU directly accesses physical memory. Used in debug mode and

View file

@ -80,6 +80,7 @@ struct kgsl_mmu_ops {
struct kgsl_memdesc *memdesc);
struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu,
unsigned long name);
struct kgsl_memdesc* (*mmu_get_qdss_global_entry)(void);
};
struct kgsl_mmu_pt_ops {
@ -227,6 +228,8 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
uint64_t size);
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device);
/*
* Static inline functions of MMU that simply call the SMMU specific
* function using a function pointer. These functions can be thought

View file

@ -308,6 +308,7 @@ enum kgsl_timestamp_type {
#define KGSL_PROP_GPMU_VERSION 0x16
#define KGSL_PROP_HIGHEST_BANK_BIT 0x17
#define KGSL_PROP_DEVICE_BITNESS 0x18
#define KGSL_PROP_DEVICE_QDSS_STM 0x19
struct kgsl_shadowprop {
unsigned long gpuaddr;
@ -315,6 +316,11 @@ struct kgsl_shadowprop {
unsigned int flags; /* contains KGSL_FLAGS_ values */
};
struct kgsl_qdss_stm_prop {
uint64_t gpuaddr;
uint64_t size;
};
struct kgsl_version {
unsigned int drv_major;
unsigned int drv_minor;