From 7359adc0bfd3d94e4aa8f66b7f18aa276bffa598 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 3 Dec 2015 08:38:11 -0700 Subject: [PATCH] msm: kgsl: Move setstate to the IOMMU initialization The setstate memory is a IOMMU specific construct. Move it to the IOMMU code where it belongs. Change-Id: Ic0dedbada977f2861f7c1300a5365da5b09d70a9 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno_iommu.c | 9 ++++-- drivers/gpu/msm/adreno_snapshot.c | 34 +++++++++++++++------- drivers/gpu/msm/kgsl_iommu.c | 34 ++++++++++++++++++++-- drivers/gpu/msm/kgsl_iommu.h | 4 ++- drivers/gpu/msm/kgsl_mmu.c | 48 +++++++------------------------ drivers/gpu/msm/kgsl_mmu.h | 5 ++-- 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 */ @@ -784,25 +803,20 @@ 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.memstore); - 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,