summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/msm/adreno_iommu.c9
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c34
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c34
-rw-r--r--drivers/gpu/msm/kgsl_iommu.h4
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c48
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h5
6 files changed, 77 insertions, 57 deletions
diff --git a/drivers/gpu/msm/adreno_iommu.c b/drivers/gpu/msm/adreno_iommu.c
index ba240190f98b..02935f6ff1ec 100644
--- a/drivers/gpu/msm/adreno_iommu.c
+++ b/drivers/gpu/msm/adreno_iommu.c
@@ -600,8 +600,7 @@ unsigned int adreno_iommu_set_pt_generate_cmds(
cmds += adreno_iommu_set_apriv(adreno_dev, cmds, 1);
cmds += _adreno_iommu_add_idle_indirect_cmds(adreno_dev, cmds,
- device->mmu.setstate_memory.gpuaddr +
- KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ iommu->setstate.gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET);
if (iommu->version >= 2) {
if (adreno_is_a5xx(adreno_dev))
@@ -872,15 +871,19 @@ static int _set_pagetable_gpu(struct adreno_ringbuffer *rb,
int adreno_iommu_init(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = &adreno_dev->dev;
+ struct kgsl_iommu *iommu = device->mmu.priv;
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
return 0;
+ if (iommu == NULL)
+ return -ENODEV;
+
/*
* A nop is required in an indirect buffer when switching
* pagetables in-stream
*/
- kgsl_sharedmem_writel(device, &device->mmu.setstate_memory,
+ kgsl_sharedmem_writel(device, &iommu->setstate,
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
cp_packet(adreno_dev, CP_NOP, 1));
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 5d8560877dd1..c0b3b9f0352c 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -720,6 +720,26 @@ static size_t snapshot_preemption_record(struct kgsl_device *device, u8 *buf,
return size + sizeof(*header);
}
+/* Snapshot IOMMU specific buffers */
+static void adreno_snapshot_iommu(struct kgsl_device *device,
+ struct kgsl_snapshot *snapshot)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_iommu *iommu = mmu->priv;
+
+ if (iommu == NULL)
+ return;
+
+ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
+ snapshot, snapshot_global, &iommu->setstate);
+
+ if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
+ kgsl_snapshot_add_section(device,
+ KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
+ snapshot, snapshot_global, &iommu->smmu_info);
+}
+
/* adreno_snapshot - Snapshot the Adreno GPU state
* @device - KGSL device to snapshot
* @snapshot - Pointer to the snapshot instance
@@ -738,7 +758,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct adreno_ringbuffer *rb;
struct snapshot_rb_params snap_rb_params;
- struct kgsl_iommu *iommu = device->mmu.priv;
ib_max_objs = 0;
/* Reset the list of objects */
@@ -786,23 +805,18 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_global,
- &adreno_dev->dev.mmu.setstate_memory);
-
- kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
- snapshot, snapshot_global,
&adreno_dev->pwron_fixup);
- if (test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv)) {
+ if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
+ adreno_snapshot_iommu(device, snapshot);
+
+ if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) {
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
kgsl_snapshot_add_section(device,
KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_preemption_record,
&rb->preemption_desc);
}
-
- kgsl_snapshot_add_section(device,
- KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
- snapshot, snapshot_global, &iommu->smmu_info);
}
/*
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index a0e84472c8e8..0235fd5ebaff 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -957,6 +957,24 @@ static unsigned int kgsl_iommu_get_reg_ahbaddr(struct kgsl_mmu *mmu,
return result;
}
+static int _setstate_alloc(struct kgsl_device *device,
+ struct kgsl_iommu *iommu)
+{
+ int ret;
+
+ ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, NULL,
+ PAGE_SIZE);
+ if (ret)
+ return ret;
+
+ /* Mark the setstate memory as read only */
+ iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY;
+
+ kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE);
+
+ return 0;
+}
+
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
{
/*
@@ -974,6 +992,10 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
return -EINVAL;
}
+ status = _setstate_alloc(KGSL_MMU_DEVICE(mmu), iommu);
+ if (status)
+ return status;
+
/* check requirements for per process pagetables */
if (ctx->gpu_offset == UINT_MAX) {
KGSL_CORE_ERR("missing qcom,gpu-offset forces global pt\n");
@@ -994,7 +1016,8 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
if (iommu->regbase == NULL) {
KGSL_CORE_ERR("Could not map IOMMU registers 0x%lx:0x%x\n",
iommu->regstart, iommu->regsize);
- return -ENOMEM;
+ status = -ENOMEM;
+ goto done;
}
if (addr_entry_cache == NULL) {
@@ -1014,7 +1037,12 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
}
}
+ kgsl_add_global_pt_entry(KGSL_MMU_DEVICE(mmu), &iommu->setstate);
+
done:
+ if (status)
+ kgsl_sharedmem_free(&iommu->setstate);
+
return status;
}
@@ -1311,7 +1339,7 @@ static void kgsl_iommu_stop(struct kgsl_mmu *mmu)
}
}
-static int kgsl_iommu_close(struct kgsl_mmu *mmu)
+static void kgsl_iommu_close(struct kgsl_mmu *mmu)
{
struct kgsl_iommu *iommu = mmu->priv;
int i;
@@ -1336,7 +1364,7 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu)
kgsl_guard_page = NULL;
}
- return 0;
+ kgsl_free_global(&iommu->setstate);
}
static u64
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index 33c1f9bd71d3..4c256aadb87e 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -88,7 +88,7 @@ enum kgsl_iommu_context_id {
KGSL_IOMMU_CONTEXT_MAX,
};
-/* offset at which a nop command is placed in setstate_memory */
+/* offset at which a nop command is placed in setstate */
#define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024
/*
@@ -124,6 +124,7 @@ struct kgsl_iommu_context {
* @regbase: Virtual address of the IOMMU register base
* @regstart: Physical address of the iommu registers
* @regsize: Length of the iommu register region.
+ * @setstate: Scratch GPU memory for IOMMU operations
* @clk_enable_count: The ref count of clock enable calls
* @clks: Array of pointers to IOMMU clocks
* @micro_mmu_ctrl: GPU register offset of this glob al register
@@ -135,6 +136,7 @@ struct kgsl_iommu {
void __iomem *regbase;
unsigned long regstart;
unsigned int regsize;
+ struct kgsl_memdesc setstate;
atomic_t clk_enable_count;
struct clk *clks[KGSL_IOMMU_MAX_CLKS];
unsigned int micro_mmu_ctrl;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 065d34f0aab7..eaea2625e030 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -523,45 +523,24 @@ EXPORT_SYMBOL(kgsl_mmu_log_fault_addr);
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype)
{
- int status = 0;
struct kgsl_mmu *mmu = &device->mmu;
+ int ret = 0;
if (mmutype && !strcmp(mmutype, "nommu"))
kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
- /*
- * Don't use kgsl_allocate_global here because we need to get the MMU
- * set up before we can add the global entry but the MMU init needs the
- * setstate block. Allocate the memory here and map it later
- */
-
- status = kgsl_sharedmem_alloc_contig(device, &mmu->setstate_memory,
- NULL, PAGE_SIZE);
- if (status)
- return status;
-
- /* Mark the setstate memory as read only */
- mmu->setstate_memory.flags |= KGSL_MEMFLAGS_GPUREADONLY;
-
- kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0,
- mmu->setstate_memory.size);
-
- if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) {
+ switch (kgsl_mmu_type) {
+ case KGSL_MMU_TYPE_IOMMU:
mmu->mmu_ops = &kgsl_iommu_ops;
- status = mmu->mmu_ops->mmu_init(mmu);
+ break;
+ case KGSL_MMU_TYPE_NONE:
+ break;
}
- if (status)
- goto done;
+ if (MMU_OP_VALID(mmu, mmu_init))
+ ret = mmu->mmu_ops->mmu_init(mmu);
- /* Add the setstate memory to the global PT entry list */
- status = kgsl_add_global_pt_entry(device, &mmu->setstate_memory);
-
-done:
- if (status)
- kgsl_sharedmem_free(&mmu->setstate_memory);
-
- return status;
+ return ret;
}
EXPORT_SYMBOL(kgsl_mmu_init);
@@ -845,17 +824,12 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
}
EXPORT_SYMBOL(kgsl_mmu_unmap);
-int kgsl_mmu_close(struct kgsl_device *device)
+void kgsl_mmu_close(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
- int ret = 0;
-
- kgsl_free_global(&mmu->setstate_memory);
if (MMU_OP_VALID(mmu, mmu_close))
- ret = mmu->mmu_ops->mmu_close(mmu);
-
- return ret;
+ mmu->mmu_ops->mmu_close(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_close);
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index ce7afa1aa2ac..2d0570df9283 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -57,7 +57,7 @@ struct kgsl_mmu;
struct kgsl_mmu_ops {
int (*mmu_init) (struct kgsl_mmu *mmu);
- int (*mmu_close) (struct kgsl_mmu *mmu);
+ void (*mmu_close)(struct kgsl_mmu *mmu);
int (*mmu_start) (struct kgsl_mmu *mmu);
void (*mmu_stop) (struct kgsl_mmu *mmu);
int (*mmu_set_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
@@ -117,7 +117,6 @@ struct kgsl_mmu_pt_ops {
struct kgsl_mmu {
uint32_t flags;
- struct kgsl_memdesc setstate_memory;
/* current page table object being used by device mmu */
struct kgsl_pagetable *defaultpagetable;
/* secure global pagetable device mmu */
@@ -140,7 +139,7 @@ struct kgsl_pagetable *kgsl_mmu_getpagetable_ptbase(struct kgsl_mmu *,
void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype);
int kgsl_mmu_start(struct kgsl_device *device);
-int kgsl_mmu_close(struct kgsl_device *device);
+void kgsl_mmu_close(struct kgsl_device *device);
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,