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 <jcrouse@codeaurora.org>
This commit is contained in:
Jordan Crouse 2015-12-03 08:38:11 -07:00 committed by David Keitel
parent ca2aa87713
commit 7359adc0bf
6 changed files with 77 additions and 57 deletions

View file

@ -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));

View file

@ -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);
}
/*

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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,