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:
parent
ca2aa87713
commit
7359adc0bf
6 changed files with 77 additions and 57 deletions
|
@ -600,8 +600,7 @@ unsigned int adreno_iommu_set_pt_generate_cmds(
|
||||||
cmds += adreno_iommu_set_apriv(adreno_dev, cmds, 1);
|
cmds += adreno_iommu_set_apriv(adreno_dev, cmds, 1);
|
||||||
|
|
||||||
cmds += _adreno_iommu_add_idle_indirect_cmds(adreno_dev, cmds,
|
cmds += _adreno_iommu_add_idle_indirect_cmds(adreno_dev, cmds,
|
||||||
device->mmu.setstate_memory.gpuaddr +
|
iommu->setstate.gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET);
|
||||||
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
|
|
||||||
|
|
||||||
if (iommu->version >= 2) {
|
if (iommu->version >= 2) {
|
||||||
if (adreno_is_a5xx(adreno_dev))
|
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)
|
int adreno_iommu_init(struct adreno_device *adreno_dev)
|
||||||
{
|
{
|
||||||
struct kgsl_device *device = &adreno_dev->dev;
|
struct kgsl_device *device = &adreno_dev->dev;
|
||||||
|
struct kgsl_iommu *iommu = device->mmu.priv;
|
||||||
|
|
||||||
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
|
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (iommu == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A nop is required in an indirect buffer when switching
|
* A nop is required in an indirect buffer when switching
|
||||||
* pagetables in-stream
|
* pagetables in-stream
|
||||||
*/
|
*/
|
||||||
kgsl_sharedmem_writel(device, &device->mmu.setstate_memory,
|
kgsl_sharedmem_writel(device, &iommu->setstate,
|
||||||
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
|
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
|
||||||
cp_packet(adreno_dev, CP_NOP, 1));
|
cp_packet(adreno_dev, CP_NOP, 1));
|
||||||
|
|
||||||
|
|
|
@ -720,6 +720,26 @@ static size_t snapshot_preemption_record(struct kgsl_device *device, u8 *buf,
|
||||||
return size + sizeof(*header);
|
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
|
/* adreno_snapshot - Snapshot the Adreno GPU state
|
||||||
* @device - KGSL device to snapshot
|
* @device - KGSL device to snapshot
|
||||||
* @snapshot - Pointer to the snapshot instance
|
* @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_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||||
struct adreno_ringbuffer *rb;
|
struct adreno_ringbuffer *rb;
|
||||||
struct snapshot_rb_params snap_rb_params;
|
struct snapshot_rb_params snap_rb_params;
|
||||||
struct kgsl_iommu *iommu = device->mmu.priv;
|
|
||||||
|
|
||||||
ib_max_objs = 0;
|
ib_max_objs = 0;
|
||||||
/* Reset the list of objects */
|
/* 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,
|
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
|
||||||
snapshot, snapshot_global, &adreno_dev->dev.memstore);
|
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,
|
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
|
||||||
snapshot, snapshot_global,
|
snapshot, snapshot_global,
|
||||||
&adreno_dev->pwron_fixup);
|
&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) {
|
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
||||||
kgsl_snapshot_add_section(device,
|
kgsl_snapshot_add_section(device,
|
||||||
KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
|
KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
|
||||||
snapshot, snapshot_preemption_record,
|
snapshot, snapshot_preemption_record,
|
||||||
&rb->preemption_desc);
|
&rb->preemption_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
kgsl_snapshot_add_section(device,
|
|
||||||
KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
|
|
||||||
snapshot, snapshot_global, &iommu->smmu_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -957,6 +957,24 @@ static unsigned int kgsl_iommu_get_reg_ahbaddr(struct kgsl_mmu *mmu,
|
||||||
return result;
|
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)
|
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -974,6 +992,10 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = _setstate_alloc(KGSL_MMU_DEVICE(mmu), iommu);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* check requirements for per process pagetables */
|
/* check requirements for per process pagetables */
|
||||||
if (ctx->gpu_offset == UINT_MAX) {
|
if (ctx->gpu_offset == UINT_MAX) {
|
||||||
KGSL_CORE_ERR("missing qcom,gpu-offset forces global pt\n");
|
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) {
|
if (iommu->regbase == NULL) {
|
||||||
KGSL_CORE_ERR("Could not map IOMMU registers 0x%lx:0x%x\n",
|
KGSL_CORE_ERR("Could not map IOMMU registers 0x%lx:0x%x\n",
|
||||||
iommu->regstart, iommu->regsize);
|
iommu->regstart, iommu->regsize);
|
||||||
return -ENOMEM;
|
status = -ENOMEM;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_entry_cache == NULL) {
|
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:
|
done:
|
||||||
|
if (status)
|
||||||
|
kgsl_sharedmem_free(&iommu->setstate);
|
||||||
|
|
||||||
return status;
|
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;
|
struct kgsl_iommu *iommu = mmu->priv;
|
||||||
int i;
|
int i;
|
||||||
|
@ -1336,7 +1364,7 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu)
|
||||||
kgsl_guard_page = NULL;
|
kgsl_guard_page = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
kgsl_free_global(&iommu->setstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64
|
static u64
|
||||||
|
|
|
@ -88,7 +88,7 @@ enum kgsl_iommu_context_id {
|
||||||
KGSL_IOMMU_CONTEXT_MAX,
|
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
|
#define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -124,6 +124,7 @@ struct kgsl_iommu_context {
|
||||||
* @regbase: Virtual address of the IOMMU register base
|
* @regbase: Virtual address of the IOMMU register base
|
||||||
* @regstart: Physical address of the iommu registers
|
* @regstart: Physical address of the iommu registers
|
||||||
* @regsize: Length of the iommu register region.
|
* @regsize: Length of the iommu register region.
|
||||||
|
* @setstate: Scratch GPU memory for IOMMU operations
|
||||||
* @clk_enable_count: The ref count of clock enable calls
|
* @clk_enable_count: The ref count of clock enable calls
|
||||||
* @clks: Array of pointers to IOMMU clocks
|
* @clks: Array of pointers to IOMMU clocks
|
||||||
* @micro_mmu_ctrl: GPU register offset of this glob al register
|
* @micro_mmu_ctrl: GPU register offset of this glob al register
|
||||||
|
@ -135,6 +136,7 @@ struct kgsl_iommu {
|
||||||
void __iomem *regbase;
|
void __iomem *regbase;
|
||||||
unsigned long regstart;
|
unsigned long regstart;
|
||||||
unsigned int regsize;
|
unsigned int regsize;
|
||||||
|
struct kgsl_memdesc setstate;
|
||||||
atomic_t clk_enable_count;
|
atomic_t clk_enable_count;
|
||||||
struct clk *clks[KGSL_IOMMU_MAX_CLKS];
|
struct clk *clks[KGSL_IOMMU_MAX_CLKS];
|
||||||
unsigned int micro_mmu_ctrl;
|
unsigned int micro_mmu_ctrl;
|
||||||
|
|
|
@ -523,45 +523,24 @@ EXPORT_SYMBOL(kgsl_mmu_log_fault_addr);
|
||||||
|
|
||||||
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype)
|
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype)
|
||||||
{
|
{
|
||||||
int status = 0;
|
|
||||||
struct kgsl_mmu *mmu = &device->mmu;
|
struct kgsl_mmu *mmu = &device->mmu;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (mmutype && !strcmp(mmutype, "nommu"))
|
if (mmutype && !strcmp(mmutype, "nommu"))
|
||||||
kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
|
kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
|
||||||
|
|
||||||
/*
|
switch (kgsl_mmu_type) {
|
||||||
* Don't use kgsl_allocate_global here because we need to get the MMU
|
case KGSL_MMU_TYPE_IOMMU:
|
||||||
* 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) {
|
|
||||||
mmu->mmu_ops = &kgsl_iommu_ops;
|
mmu->mmu_ops = &kgsl_iommu_ops;
|
||||||
status = mmu->mmu_ops->mmu_init(mmu);
|
break;
|
||||||
|
case KGSL_MMU_TYPE_NONE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status)
|
if (MMU_OP_VALID(mmu, mmu_init))
|
||||||
goto done;
|
ret = mmu->mmu_ops->mmu_init(mmu);
|
||||||
|
|
||||||
/* Add the setstate memory to the global PT entry list */
|
return ret;
|
||||||
status = kgsl_add_global_pt_entry(device, &mmu->setstate_memory);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (status)
|
|
||||||
kgsl_sharedmem_free(&mmu->setstate_memory);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kgsl_mmu_init);
|
EXPORT_SYMBOL(kgsl_mmu_init);
|
||||||
|
|
||||||
|
@ -845,17 +824,12 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kgsl_mmu_unmap);
|
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;
|
struct kgsl_mmu *mmu = &device->mmu;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
kgsl_free_global(&mmu->setstate_memory);
|
|
||||||
|
|
||||||
if (MMU_OP_VALID(mmu, mmu_close))
|
if (MMU_OP_VALID(mmu, mmu_close))
|
||||||
ret = mmu->mmu_ops->mmu_close(mmu);
|
mmu->mmu_ops->mmu_close(mmu);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kgsl_mmu_close);
|
EXPORT_SYMBOL(kgsl_mmu_close);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct kgsl_mmu;
|
||||||
|
|
||||||
struct kgsl_mmu_ops {
|
struct kgsl_mmu_ops {
|
||||||
int (*mmu_init) (struct kgsl_mmu *mmu);
|
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);
|
int (*mmu_start) (struct kgsl_mmu *mmu);
|
||||||
void (*mmu_stop) (struct kgsl_mmu *mmu);
|
void (*mmu_stop) (struct kgsl_mmu *mmu);
|
||||||
int (*mmu_set_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
|
int (*mmu_set_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
|
||||||
|
@ -117,7 +117,6 @@ struct kgsl_mmu_pt_ops {
|
||||||
|
|
||||||
struct kgsl_mmu {
|
struct kgsl_mmu {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct kgsl_memdesc setstate_memory;
|
|
||||||
/* current page table object being used by device mmu */
|
/* current page table object being used by device mmu */
|
||||||
struct kgsl_pagetable *defaultpagetable;
|
struct kgsl_pagetable *defaultpagetable;
|
||||||
/* secure global pagetable device mmu */
|
/* 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);
|
void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
|
||||||
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype);
|
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype);
|
||||||
int kgsl_mmu_start(struct kgsl_device *device);
|
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,
|
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
|
||||||
struct kgsl_memdesc *memdesc);
|
struct kgsl_memdesc *memdesc);
|
||||||
int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
|
int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
|
||||||
|
|
Loading…
Add table
Reference in a new issue