From 7946b878038d5113262d6eae09ff22fb2956351f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 24 Nov 2015 10:14:28 -0500 Subject: drm/amdgpu: add a callback for reading the bios from the rom directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is necessary when the vbios image is not directly accessible via the rom BAR or legacy vga location. Reviewed-by: Jammy Zhou Reviewed-by: Christian König Reviewed-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 251b14736de9..1799973e7744 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1826,6 +1826,8 @@ struct amdgpu_cu_info { */ struct amdgpu_asic_funcs { bool (*read_disabled_bios)(struct amdgpu_device *adev); + bool (*read_bios_from_rom)(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes); int (*read_register)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 reg_offset, u32 *value); void (*set_vga_state)(struct amdgpu_device *adev, bool state); @@ -2232,6 +2234,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec)) #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev)) #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev)) +#define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l)) #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v))) #define amdgpu_asic_get_cu_info(adev, info) (adev)->asic_funcs->get_cu_info((adev), (info)) #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid)) -- cgit v1.2.3 From d033a6de80054139b4358db12cf6bb8d6cf58853 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Thu, 5 Nov 2015 15:23:09 +0800 Subject: drm/amd: abstract kernel rq and normal rq to priority of run queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows us to set priorities in the scheduler. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Reviewed-by: Junwei Zhang --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 11 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 14 +++++++++----- drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 9 +++++++-- 5 files changed, 23 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1799973e7744..5f975030bb72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1044,7 +1044,7 @@ struct amdgpu_ctx_mgr { struct idr ctx_handles; }; -int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, +int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, struct amdgpu_ctx *ctx); void amdgpu_ctx_fini(struct amdgpu_ctx *ctx); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index fec65f01c031..c1f2308b4115 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -25,7 +25,7 @@ #include #include "amdgpu.h" -int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, +int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, struct amdgpu_ctx *ctx) { unsigned i, j; @@ -42,10 +42,9 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, /* create context entity for each ring */ for (i = 0; i < adev->num_rings; i++) { struct amd_sched_rq *rq; - if (kernel) - rq = &adev->rings[i]->sched.kernel_rq; - else - rq = &adev->rings[i]->sched.sched_rq; + if (pri >= AMD_SCHED_MAX_PRIORITY) + return -EINVAL; + rq = &adev->rings[i]->sched.sched_rq[pri]; r = amd_sched_entity_init(&adev->rings[i]->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs); @@ -103,7 +102,7 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev, return r; } *id = (uint32_t)r; - r = amdgpu_ctx_init(adev, false, ctx); + r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_NORMAL, ctx); mutex_unlock(&mgr->lock); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 58cb6987b078..84775964b138 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1528,7 +1528,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, return r; } - r = amdgpu_ctx_init(adev, true, &adev->kernel_ctx); + r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_KERNEL, &adev->kernel_ctx); if (r) { dev_err(adev->dev, "failed to create kernel context (%d).\n", r); return r; diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 651129f2ec1d..e13b7a013a40 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -348,14 +348,17 @@ static struct amd_sched_entity * amd_sched_select_entity(struct amd_gpu_scheduler *sched) { struct amd_sched_entity *entity; + int i; if (!amd_sched_ready(sched)) return NULL; /* Kernel run queue has higher priority than normal run queue*/ - entity = amd_sched_rq_select_entity(&sched->kernel_rq); - if (entity == NULL) - entity = amd_sched_rq_select_entity(&sched->sched_rq); + for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++) { + entity = amd_sched_rq_select_entity(&sched->sched_rq[i]); + if (entity) + break; + } return entity; } @@ -477,12 +480,13 @@ int amd_sched_init(struct amd_gpu_scheduler *sched, struct amd_sched_backend_ops *ops, unsigned hw_submission, long timeout, const char *name) { + int i; sched->ops = ops; sched->hw_submission_limit = hw_submission; sched->name = name; sched->timeout = timeout; - amd_sched_rq_init(&sched->sched_rq); - amd_sched_rq_init(&sched->kernel_rq); + for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++) + amd_sched_rq_init(&sched->sched_rq[i]); init_waitqueue_head(&sched->wake_up_worker); init_waitqueue_head(&sched->job_scheduled); diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index a0f0ae53aacd..9403145d7bee 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -104,6 +104,12 @@ struct amd_sched_backend_ops { struct fence *(*run_job)(struct amd_sched_job *sched_job); }; +enum amd_sched_priority { + AMD_SCHED_PRIORITY_KERNEL = 0, + AMD_SCHED_PRIORITY_NORMAL, + AMD_SCHED_MAX_PRIORITY +}; + /** * One scheduler is implemented for each hardware ring */ @@ -112,8 +118,7 @@ struct amd_gpu_scheduler { uint32_t hw_submission_limit; long timeout; const char *name; - struct amd_sched_rq sched_rq; - struct amd_sched_rq kernel_rq; + struct amd_sched_rq sched_rq[AMD_SCHED_MAX_PRIORITY]; wait_queue_head_t wake_up_worker; wait_queue_head_t job_scheduled; atomic_t hw_rq_count; -- cgit v1.2.3 From 9c4153b1eef9bc8da6a624252a3a25790b705136 Mon Sep 17 00:00:00 2001 From: jimqu Date: Fri, 4 Dec 2015 17:17:00 +0800 Subject: drm/amdgpu: add spin lock to protect freed list in vm (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit there is a protection fault about freed list when OCL test. add a spin lock to protect it. v2: drop changes in vm_fini Signed-off-by: JimQu Reviewed-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5f975030bb72..3b5d3706f0cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -955,6 +955,8 @@ struct amdgpu_vm { struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS]; /* for interval tree */ spinlock_t it_lock; + /* protecting freed */ + spinlock_t freed_lock; }; struct amdgpu_vm_manager { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index ae037e5b6ad0..fce4c6d952c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -885,17 +885,21 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping; int r; + spin_lock(&vm->freed_lock); while (!list_empty(&vm->freed)) { mapping = list_first_entry(&vm->freed, struct amdgpu_bo_va_mapping, list); list_del(&mapping->list); - + spin_unlock(&vm->freed_lock); r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, 0, 0, NULL); kfree(mapping); if (r) return r; + spin_lock(&vm->freed_lock); } + spin_unlock(&vm->freed_lock); + return 0; } @@ -1150,10 +1154,13 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, spin_unlock(&vm->it_lock); trace_amdgpu_vm_bo_unmap(bo_va, mapping); - if (valid) + if (valid) { + spin_lock(&vm->freed_lock); list_add(&mapping->list, &vm->freed); - else + spin_unlock(&vm->freed_lock); + } else { kfree(mapping); + } return 0; } @@ -1186,7 +1193,9 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, interval_tree_remove(&mapping->it, &vm->va); spin_unlock(&vm->it_lock); trace_amdgpu_vm_bo_unmap(bo_va, mapping); + spin_lock(&vm->freed_lock); list_add(&mapping->list, &vm->freed); + spin_unlock(&vm->freed_lock); } list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { list_del(&mapping->list); @@ -1247,6 +1256,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) INIT_LIST_HEAD(&vm->cleared); INIT_LIST_HEAD(&vm->freed); spin_lock_init(&vm->it_lock); + spin_lock_init(&vm->freed_lock); pd_size = amdgpu_vm_directory_size(adev); pd_entries = amdgpu_vm_num_pdes(adev); -- cgit v1.2.3 From 37cd0ca204a55e123fca9ce411e6571ac49fa8f7 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Thu, 10 Dec 2015 15:45:11 +0800 Subject: drm/amdgpu: unify AMDGPU_CTX_MAX_CS_PENDING and amdgpu_sched_jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 25 ++++++++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3b5d3706f0cb..c3996e0e2e7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1023,11 +1023,9 @@ int amdgpu_vm_free_job(struct amdgpu_job *job); * context related structures */ -#define AMDGPU_CTX_MAX_CS_PENDING 16 - struct amdgpu_ctx_ring { uint64_t sequence; - struct fence *fences[AMDGPU_CTX_MAX_CS_PENDING]; + struct fence **fences; struct amd_sched_entity entity; }; @@ -1036,6 +1034,7 @@ struct amdgpu_ctx { struct amdgpu_device *adev; unsigned reset_counter; spinlock_t ring_lock; + struct fence **fences; struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS]; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 15e341634536..ee121ec2917b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -35,15 +35,24 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, ctx->adev = adev; kref_init(&ctx->refcount); spin_lock_init(&ctx->ring_lock); - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - ctx->rings[i].sequence = 1; + ctx->fences = kzalloc(sizeof(struct fence *) * amdgpu_sched_jobs * + AMDGPU_MAX_RINGS, GFP_KERNEL); + if (!ctx->fences) + return -ENOMEM; + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + ctx->rings[i].sequence = 1; + ctx->rings[i].fences = (void *)ctx->fences + sizeof(struct fence *) * + amdgpu_sched_jobs * i; + } if (amdgpu_enable_scheduler) { /* create context entity for each ring */ for (i = 0; i < adev->num_rings; i++) { struct amd_sched_rq *rq; - if (pri >= AMD_SCHED_MAX_PRIORITY) + if (pri >= AMD_SCHED_MAX_PRIORITY) { + kfree(ctx->fences); return -EINVAL; + } rq = &adev->rings[i]->sched.sched_rq[pri]; r = amd_sched_entity_init(&adev->rings[i]->sched, &ctx->rings[i].entity, @@ -56,6 +65,7 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, for (j = 0; j < i; j++) amd_sched_entity_fini(&adev->rings[j]->sched, &ctx->rings[j].entity); + kfree(ctx->fences); return r; } } @@ -71,8 +81,9 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) return; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j) + for (j = 0; j < amdgpu_sched_jobs; ++j) fence_put(ctx->rings[i].fences[j]); + kfree(ctx->fences); if (amdgpu_enable_scheduler) { for (i = 0; i < adev->num_rings; i++) @@ -241,7 +252,7 @@ uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, unsigned idx = 0; struct fence *other = NULL; - idx = seq % AMDGPU_CTX_MAX_CS_PENDING; + idx = seq % amdgpu_sched_jobs; other = cring->fences[idx]; if (other) { signed long r; @@ -276,12 +287,12 @@ struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, } - if (seq + AMDGPU_CTX_MAX_CS_PENDING < cring->sequence) { + if (seq + amdgpu_sched_jobs < cring->sequence) { spin_unlock(&ctx->ring_lock); return NULL; } - fence = fence_get(cring->fences[seq % AMDGPU_CTX_MAX_CS_PENDING]); + fence = fence_get(cring->fences[seq % amdgpu_sched_jobs]); spin_unlock(&ctx->ring_lock); return fence; -- cgit v1.2.3 From 91acbeb68ab10c0c0f65f30b5b7fddbde4c97dd2 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 14 Dec 2015 16:42:31 +0100 Subject: drm/amdgpu: fix user fence handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a random corruption under memory pressure. We need to fence the BO for the user fence as well, otherwise it might be swapped out and the GPU could write the fence value to an undesired location. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 63 ++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5a5f04d0902d..048cfe073dae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1264,7 +1264,8 @@ struct amdgpu_cs_parser { struct ww_acquire_ctx ticket; /* user fence */ - struct amdgpu_user_fence uf; + struct amdgpu_user_fence uf; + struct amdgpu_bo_list_entry uf_entry; }; struct amdgpu_job { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 4f352ec9dec4..25a3e2485cc2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -127,6 +127,37 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, return 0; } +static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, + struct drm_amdgpu_cs_chunk_fence *fence_data) +{ + struct drm_gem_object *gobj; + uint32_t handle; + + handle = fence_data->handle; + gobj = drm_gem_object_lookup(p->adev->ddev, p->filp, + fence_data->handle); + if (gobj == NULL) + return -EINVAL; + + p->uf.bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj)); + p->uf.offset = fence_data->offset; + + if (amdgpu_ttm_tt_has_userptr(p->uf.bo->tbo.ttm)) { + drm_gem_object_unreference_unlocked(gobj); + return -EINVAL; + } + + p->uf_entry.robj = amdgpu_bo_ref(p->uf.bo); + p->uf_entry.prefered_domains = AMDGPU_GEM_DOMAIN_GTT; + p->uf_entry.allowed_domains = AMDGPU_GEM_DOMAIN_GTT; + p->uf_entry.priority = 0; + p->uf_entry.tv.bo = &p->uf_entry.robj->tbo; + p->uf_entry.tv.shared = true; + + drm_gem_object_unreference_unlocked(gobj); + return 0; +} + int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) { union drm_amdgpu_cs *cs = data; @@ -207,28 +238,15 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) case AMDGPU_CHUNK_ID_FENCE: size = sizeof(struct drm_amdgpu_cs_chunk_fence); - if (p->chunks[i].length_dw * sizeof(uint32_t) >= size) { - uint32_t handle; - struct drm_gem_object *gobj; - struct drm_amdgpu_cs_chunk_fence *fence_data; - - fence_data = (void *)p->chunks[i].kdata; - handle = fence_data->handle; - gobj = drm_gem_object_lookup(p->adev->ddev, - p->filp, handle); - if (gobj == NULL) { - ret = -EINVAL; - goto free_partial_kdata; - } - - p->uf.bo = gem_to_amdgpu_bo(gobj); - amdgpu_bo_ref(p->uf.bo); - drm_gem_object_unreference_unlocked(gobj); - p->uf.offset = fence_data->offset; - } else { + if (p->chunks[i].length_dw * sizeof(uint32_t) < size) { ret = -EINVAL; goto free_partial_kdata; } + + ret = amdgpu_cs_user_fence_chunk(p, (void *)p->chunks[i].kdata); + if (ret) + goto free_partial_kdata; + break; case AMDGPU_CHUNK_ID_DEPENDENCIES: @@ -391,6 +409,9 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, &p->validated); + if (p->uf.bo) + list_add(&p->uf_entry.tv.head, &p->validated); + if (need_mmap_lock) down_read(¤t->mm->mmap_sem); @@ -488,8 +509,8 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo for (i = 0; i < parser->num_ibs; i++) amdgpu_ib_free(parser->adev, &parser->ibs[i]); kfree(parser->ibs); - if (parser->uf.bo) - amdgpu_bo_unref(&parser->uf.bo); + amdgpu_bo_unref(&parser->uf.bo); + amdgpu_bo_unref(&parser->uf_entry.robj); } static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, -- cgit v1.2.3 From 3c0eea6c35d932c4d25070868067dc9cd9ceab91 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 14:39:05 +0100 Subject: drm/amdgpu: put VM page tables directly into duplicates list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They share the reservation object with the page directory anyway. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12 +++++++----- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c3996e0e2e7e..dc3dab539e4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -982,7 +982,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct list_head *head); + struct list_head *validated, + struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1d44d508d4d4..9591c13781bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -386,13 +386,13 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) amdgpu_cs_buckets_get_list(&buckets, &p->validated); } + INIT_LIST_HEAD(&duplicates); p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, - &p->validated); + &p->validated, &duplicates); if (need_mmap_lock) down_read(¤t->mm->mmap_sem); - INIT_LIST_HEAD(&duplicates); r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates); if (unlikely(r != 0)) goto error_reserve; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fc32fc01a64b..7fe7f8afa5ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -460,7 +460,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, tv.shared = true; list_add(&tv.head, &list); - vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list); + vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list, &duplicates); if (!vm_bos) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index fce4c6d952c8..f6c1d6f0bf37 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -78,14 +78,16 @@ static unsigned amdgpu_vm_directory_size(struct amdgpu_device *adev) * amdgpu_vm_get_bos - add the vm BOs to a validation list * * @vm: vm providing the BOs - * @head: head of validation list + * @validated: head of validation list + * @duplicates: head of duplicates list * * Add the page directory to the list of BOs to * validate for command submission (cayman+). */ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *head) + struct amdgpu_vm *vm, + struct list_head *validated, + struct list_head *duplicates) { struct amdgpu_bo_list_entry *list; unsigned i, idx; @@ -103,7 +105,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, list[0].priority = 0; list[0].tv.bo = &vm->page_directory->tbo; list[0].tv.shared = true; - list_add(&list[0].tv.head, head); + list_add(&list[0].tv.head, validated); for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { if (!vm->page_tables[i].bo) @@ -115,7 +117,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, list[idx].priority = 0; list[idx].tv.bo = &list[idx].robj->tbo; list[idx].tv.shared = true; - list_add(&list[idx++].tv.head, head); + list_add(&list[idx++].tv.head, duplicates); } return list; -- cgit v1.2.3 From 56467ebfb254836dc30eb45d4ac8a46a400bfad6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 15:16:32 +0100 Subject: drm/amdgpu: split VM PD and PT handling during CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we avoid the extra allocation for the page directory entry. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 10 +++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 16 +++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 45 ++++++++++++++++++++------------- 4 files changed, 51 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index dc3dab539e4c..40850afa763f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -980,10 +980,11 @@ struct amdgpu_vm_manager { void amdgpu_vm_manager_fini(struct amdgpu_device *adev); int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *validated, - struct list_head *duplicates); +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry); +struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, + struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, @@ -1253,6 +1254,7 @@ struct amdgpu_cs_parser { unsigned nchunks; struct amdgpu_cs_chunk *chunks; /* relocations */ + struct amdgpu_bo_list_entry vm_pd; struct amdgpu_bo_list_entry *vm_bos; struct list_head validated; struct fence *fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 9591c13781bd..3fb21ecd29e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -387,8 +387,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) } INIT_LIST_HEAD(&duplicates); - p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, - &p->validated, &duplicates); + amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd); if (need_mmap_lock) down_read(¤t->mm->mmap_sem); @@ -397,6 +396,12 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) if (unlikely(r != 0)) goto error_reserve; + p->vm_bos = amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); + if (!p->vm_bos) { + r = -ENOMEM; + goto error_validate; + } + r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); if (r) goto error_validate; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7fe7f8afa5ff..ea0fe94e4b54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -448,6 +448,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry *vm_bos; + struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; unsigned domain; @@ -460,14 +461,18 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, tv.shared = true; list_add(&tv.head, &list); - vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list, &duplicates); - if (!vm_bos) - return; + amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd); /* Provide duplicates to avoid -EALREADY */ r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) - goto error_free; + goto error_print; + + vm_bos = amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); + if (!vm_bos) { + r = -ENOMEM; + goto error_unreserve; + } list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); @@ -489,10 +494,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); - -error_free: drm_free_large(vm_bos); +error_print: if (r && r != -ERESTARTSYS) DRM_ERROR("Couldn't update BO_VA (%d)\n", r); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f6c1d6f0bf37..592be6438a6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -75,39 +75,50 @@ static unsigned amdgpu_vm_directory_size(struct amdgpu_device *adev) } /** - * amdgpu_vm_get_bos - add the vm BOs to a validation list + * amdgpu_vm_get_pd_bo - add the VM PD to a validation list * * @vm: vm providing the BOs * @validated: head of validation list + * @entry: entry to add + * + * Add the page directory to the list of BOs to + * validate for command submission. + */ +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry) +{ + entry->robj = vm->page_directory; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &vm->page_directory->tbo; + entry->tv.shared = true; + list_add(&entry->tv.head, validated); +} + +/** + * amdgpu_vm_get_bos - add the vm BOs to a validation list + * + * @vm: vm providing the BOs * @duplicates: head of duplicates list * * Add the page directory to the list of BOs to * validate for command submission (cayman+). */ -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *validated, - struct list_head *duplicates) +struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, + struct list_head *duplicates) { struct amdgpu_bo_list_entry *list; unsigned i, idx; - list = drm_malloc_ab(vm->max_pde_used + 2, + list = drm_malloc_ab(vm->max_pde_used + 1, sizeof(struct amdgpu_bo_list_entry)); - if (!list) { + if (!list) return NULL; - } /* add the vm page table to the list */ - list[0].robj = vm->page_directory; - list[0].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].priority = 0; - list[0].tv.bo = &vm->page_directory->tbo; - list[0].tv.shared = true; - list_add(&list[0].tv.head, validated); - - for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { + for (i = 0, idx = 0; i <= vm->max_pde_used; i++) { if (!vm->page_tables[i].bo) continue; -- cgit v1.2.3 From ee1782c3f27fec5462363af48f27811b049155ab Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 21:01:23 +0100 Subject: drm/amdgpu: keep the PTs validation list in the VM v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids allocating it on the fly. v2: fix grammar in comment Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 7 +---- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 +----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 50 +++++++++++++++------------------ 4 files changed, 27 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 40850afa763f..d4e9272b60e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -917,8 +917,8 @@ struct amdgpu_ring { #define AMDGPU_VM_FAULT_STOP_ALWAYS 2 struct amdgpu_vm_pt { - struct amdgpu_bo *bo; - uint64_t addr; + struct amdgpu_bo_list_entry entry; + uint64_t addr; }; struct amdgpu_vm_id { @@ -983,8 +983,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); -struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, - struct list_head *duplicates); +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, @@ -1255,7 +1254,6 @@ struct amdgpu_cs_parser { struct amdgpu_cs_chunk *chunks; /* relocations */ struct amdgpu_bo_list_entry vm_pd; - struct amdgpu_bo_list_entry *vm_bos; struct list_head validated; struct fence *fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 3fb21ecd29e0..6ce595ff1aff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -396,11 +396,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) if (unlikely(r != 0)) goto error_reserve; - p->vm_bos = amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); - if (!p->vm_bos) { - r = -ENOMEM; - goto error_validate; - } + amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); if (r) @@ -483,7 +479,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo if (parser->bo_list) amdgpu_bo_list_put(parser->bo_list); - drm_free_large(parser->vm_bos); for (i = 0; i < parser->nchunks; i++) drm_free_large(parser->chunks[i].kdata); kfree(parser->chunks); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index ea0fe94e4b54..8c5687e4a6d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -447,7 +447,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; - struct amdgpu_bo_list_entry *vm_bos; struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; @@ -468,12 +467,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (r) goto error_print; - vm_bos = amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); - if (!vm_bos) { - r = -ENOMEM; - goto error_unreserve; - } - + amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); /* if anything is swapped out don't swap it in here, @@ -494,7 +488,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); - drm_free_large(vm_bos); error_print: if (r && r != -ERESTARTSYS) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 592be6438a6c..e0fa9d9ff5c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -98,40 +98,27 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, } /** - * amdgpu_vm_get_bos - add the vm BOs to a validation list + * amdgpu_vm_get_bos - add the vm BOs to a duplicates list * * @vm: vm providing the BOs * @duplicates: head of duplicates list * - * Add the page directory to the list of BOs to - * validate for command submission (cayman+). + * Add the page directory to the BO duplicates list + * for command submission. */ -struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, - struct list_head *duplicates) +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates) { - struct amdgpu_bo_list_entry *list; - unsigned i, idx; - - list = drm_malloc_ab(vm->max_pde_used + 1, - sizeof(struct amdgpu_bo_list_entry)); - if (!list) - return NULL; + unsigned i; /* add the vm page table to the list */ - for (i = 0, idx = 0; i <= vm->max_pde_used; i++) { - if (!vm->page_tables[i].bo) + for (i = 0; i <= vm->max_pde_used; ++i) { + struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + + if (!entry->robj) continue; - list[idx].robj = vm->page_tables[i].bo; - list[idx].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].priority = 0; - list[idx].tv.bo = &list[idx].robj->tbo; - list[idx].tv.shared = true; - list_add(&list[idx++].tv.head, duplicates); + list_add(&entry->tv.head, duplicates); } - - return list; } /** @@ -474,7 +461,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, /* walk over the address space and update the page directory */ for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { - struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj; uint64_t pde, pt; if (bo == NULL) @@ -651,7 +638,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev, /* walk over the address space and update the page tables */ for (addr = start; addr < end; ) { uint64_t pt_idx = addr >> amdgpu_vm_block_size; - struct amdgpu_bo *pt = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *pt = vm->page_tables[pt_idx].entry.robj; unsigned nptes; uint64_t pte; int r; @@ -1083,9 +1070,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, /* walk over the address space and allocate the page tables */ for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { struct reservation_object *resv = vm->page_directory->tbo.resv; + struct amdgpu_bo_list_entry *entry; struct amdgpu_bo *pt; - if (vm->page_tables[pt_idx].bo) + entry = &vm->page_tables[pt_idx].entry; + if (entry->robj) continue; r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, @@ -1102,8 +1091,13 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, goto error_free; } + entry->robj = pt; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &entry->robj->tbo; + entry->tv.shared = true; vm->page_tables[pt_idx].addr = 0; - vm->page_tables[pt_idx].bo = pt; } return 0; @@ -1334,7 +1328,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) - amdgpu_bo_unref(&vm->page_tables[i].bo); + amdgpu_bo_unref(&vm->page_tables[i].entry.robj); kfree(vm->page_tables); amdgpu_bo_unref(&vm->page_directory); -- cgit v1.2.3 From 3a2c788d95a24dc4cf720ddd19c1b115a03f41bf Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 25 Aug 2015 15:57:43 +0800 Subject: drm/amdgpu: share struct amdgpu_pm_state_type with powerplay module rename amdgpu_pm_state_type to amd_pm_state_type Signed-off-by: Rex Zhu Acked-by: Jammy Zhou Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 28 ++-------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 8 ++++---- drivers/gpu/drm/amd/include/amd_shared.h | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d4e9272b60e8..d454ad6ff798 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1299,31 +1299,7 @@ struct amdgpu_wb { int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb); void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb); -/** - * struct amdgpu_pm - power management datas - * It keeps track of various data needed to take powermanagement decision. - */ -enum amdgpu_pm_state_type { - /* not used for dpm */ - POWER_STATE_TYPE_DEFAULT, - POWER_STATE_TYPE_POWERSAVE, - /* user selectable states */ - POWER_STATE_TYPE_BATTERY, - POWER_STATE_TYPE_BALANCED, - POWER_STATE_TYPE_PERFORMANCE, - /* internal states */ - POWER_STATE_TYPE_INTERNAL_UVD, - POWER_STATE_TYPE_INTERNAL_UVD_SD, - POWER_STATE_TYPE_INTERNAL_UVD_HD, - POWER_STATE_TYPE_INTERNAL_UVD_HD2, - POWER_STATE_TYPE_INTERNAL_UVD_MVC, - POWER_STATE_TYPE_INTERNAL_BOOT, - POWER_STATE_TYPE_INTERNAL_THERMAL, - POWER_STATE_TYPE_INTERNAL_ACPI, - POWER_STATE_TYPE_INTERNAL_ULV, - POWER_STATE_TYPE_INTERNAL_3DPERF, -}; enum amdgpu_int_thermal_type { THERMAL_TYPE_NONE, @@ -1605,8 +1581,8 @@ struct amdgpu_dpm { /* vce requirements */ struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS]; enum amdgpu_vce_level vce_level; - enum amdgpu_pm_state_type state; - enum amdgpu_pm_state_type user_state; + enum amd_pm_state_type state; + enum amd_pm_state_type user_state; u32 platform_caps; u32 voltage_response_time; u32 backbias_response_time; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 22a8c7d3a3ab..eea1933947ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -52,7 +52,7 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amdgpu_pm_state_type pm = adev->pm.dpm.user_state; + enum amd_pm_state_type pm = adev->pm.dpm.user_state; return snprintf(buf, PAGE_SIZE, "%s\n", (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : @@ -351,7 +351,7 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) container_of(work, struct amdgpu_device, pm.dpm.thermal.work); /* switch to the thermal state */ - enum amdgpu_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; if (!adev->pm.dpm_enabled) return; @@ -379,7 +379,7 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) } static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amdgpu_pm_state_type dpm_state) + enum amd_pm_state_type dpm_state) { int i; struct amdgpu_ps *ps; @@ -516,7 +516,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { int i; struct amdgpu_ps *ps; - enum amdgpu_pm_state_type dpm_state; + enum amd_pm_state_type dpm_state; int ret; /* if dpm init failed */ diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index fe28fb353fab..1195d06f55bc 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -85,6 +85,27 @@ enum amd_powergating_state { AMD_PG_STATE_UNGATE, }; +enum amd_pm_state_type { + /* not used for dpm */ + POWER_STATE_TYPE_DEFAULT, + POWER_STATE_TYPE_POWERSAVE, + /* user selectable states */ + POWER_STATE_TYPE_BATTERY, + POWER_STATE_TYPE_BALANCED, + POWER_STATE_TYPE_PERFORMANCE, + /* internal states */ + POWER_STATE_TYPE_INTERNAL_UVD, + POWER_STATE_TYPE_INTERNAL_UVD_SD, + POWER_STATE_TYPE_INTERNAL_UVD_HD, + POWER_STATE_TYPE_INTERNAL_UVD_HD2, + POWER_STATE_TYPE_INTERNAL_UVD_MVC, + POWER_STATE_TYPE_INTERNAL_BOOT, + POWER_STATE_TYPE_INTERNAL_THERMAL, + POWER_STATE_TYPE_INTERNAL_ACPI, + POWER_STATE_TYPE_INTERNAL_ULV, + POWER_STATE_TYPE_INTERNAL_3DPERF, +}; + struct amd_ip_funcs { /* sets up early driver state (pre sw_init), does not configure hw - Optional */ int (*early_init)(void *handle); -- cgit v1.2.3 From 1f7371b2a5faf139465f0af386cccbb54b832534 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Dec 2015 17:46:21 -0500 Subject: drm/amd/powerplay: add basic powerplay framework amdgpu_pp_ip_funcs is introduced to handle the two code paths, the legacy one and the new powerplay implementation. CONFIG_DRM_AMD_POWERPLAY kernel configuration option is introduced for the powerplay component. v4: squash in fixes v3: register debugfs file when powerplay module enable v2: add amdgpu_ucode_init_bo in hw init when amdgpu_powerplay enable. Signed-off-by: Rex Zhu Signed-off-by: Jammy Zhou Reviewed-by: Alex Deucher --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/amd/amdgpu/Makefile | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 280 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h | 33 +++ drivers/gpu/drm/amd/amdgpu/cik.c | 11 +- drivers/gpu/drm/amd/amdgpu/vi.c | 7 +- drivers/gpu/drm/amd/powerplay/Kconfig | 6 + drivers/gpu/drm/amd/powerplay/Makefile | 15 ++ drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 194 +++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 162 +++++++++++++ 12 files changed, 718 insertions(+), 9 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h create mode 100644 drivers/gpu/drm/amd/powerplay/Kconfig create mode 100644 drivers/gpu/drm/amd/powerplay/Makefile create mode 100644 drivers/gpu/drm/amd/powerplay/amd_powerplay.c create mode 100644 drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c4bf9a1cf4a6..b42c1ba8df9a 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -160,6 +160,7 @@ config DRM_AMDGPU If M is selected, the module will be called amdgpu. source "drivers/gpu/drm/amd/amdgpu/Kconfig" +source "drivers/gpu/drm/amd/powerplay/Kconfig" source "drivers/gpu/drm/nouveau/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index a5c3aa0de773..16603a0f87e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -7,7 +7,8 @@ FULL_AMD_PATH=$(src)/.. ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ - -I$(FULL_AMD_PATH)/scheduler + -I$(FULL_AMD_PATH)/scheduler \ + -I$(FULL_AMD_PATH)/powerplay/inc amdgpu-y := amdgpu_drv.o @@ -46,6 +47,7 @@ amdgpu-y += \ # add SMC block amdgpu-y += \ amdgpu_dpm.o \ + amdgpu_powerplay.o \ cz_smc.o cz_dpm.o \ tonga_smc.o tonga_dpm.o \ fiji_smc.o fiji_dpm.o \ @@ -96,6 +98,14 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o +ifneq ($(CONFIG_DRM_AMD_POWERPLAY),) + +include drivers/gpu/drm/amd/powerplay/Makefile + +amdgpu-y += $(AMD_POWERPLAY_FILES) + +endif + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o CFLAGS_amdgpu_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d454ad6ff798..6f08d39a3232 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -52,6 +52,7 @@ #include "amdgpu_irq.h" #include "amdgpu_ucode.h" #include "amdgpu_gds.h" +#include "amd_powerplay.h" #include "gpu_scheduler.h" @@ -85,6 +86,7 @@ extern int amdgpu_enable_scheduler; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_enable_semaphores; +extern int amdgpu_powerplay; #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -2036,6 +2038,9 @@ struct amdgpu_device { /* interrupts */ struct amdgpu_irq irq; + /* powerplay */ + struct amd_powerplay powerplay; + /* dpm */ struct amdgpu_pm pm; u32 cg_flags; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 642e305bcbcd..09248a640dbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -82,6 +82,7 @@ int amdgpu_enable_scheduler = 1; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_enable_semaphores = 0; +int amdgpu_powerplay = 0; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c new file mode 100644 index 000000000000..5dd2a4c1a70d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -0,0 +1,280 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "atom.h" +#include "amdgpu.h" +#include "amd_shared.h" +#include +#include +#include "amdgpu_pm.h" +#include +#include "amdgpu_powerplay.h" +#include "cik_dpm.h" +#include "vi_dpm.h" + +static int amdgpu_powerplay_init(struct amdgpu_device *adev) +{ + int ret = 0; + struct amd_powerplay *amd_pp; + + amd_pp = &(adev->powerplay); + + if (amdgpu_powerplay) { +#ifdef CONFIG_DRM_AMD_POWERPLAY + struct amd_pp_init *pp_init; + + pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL); + + if (pp_init == NULL) + return -ENOMEM; + + pp_init->chip_family = adev->family; + pp_init->chip_id = adev->asic_type; + pp_init->device = amdgpu_cgs_create_device(adev); + + ret = amd_powerplay_init(pp_init, amd_pp); + kfree(pp_init); +#endif + } else { + amd_pp->pp_handle = (void *)adev; + + switch (adev->asic_type) { +#ifdef CONFIG_DRM_AMDGPU_CIK + case CHIP_BONAIRE: + case CHIP_HAWAII: + amd_pp->ip_funcs = &ci_dpm_ip_funcs; + break; + case CHIP_KABINI: + case CHIP_MULLINS: + case CHIP_KAVERI: + amd_pp->ip_funcs = &kv_dpm_ip_funcs; + break; +#endif + case CHIP_TOPAZ: + amd_pp->ip_funcs = &iceland_dpm_ip_funcs; + break; + case CHIP_TONGA: + amd_pp->ip_funcs = &tonga_dpm_ip_funcs; + break; + case CHIP_CARRIZO: + amd_pp->ip_funcs = &cz_dpm_ip_funcs; + break; + default: + ret = -EINVAL; + break; + } + } + return ret; +} + +static int amdgpu_pp_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret = 0; + + ret = amdgpu_powerplay_init(adev); + if (ret) + return ret; + + if (adev->powerplay.ip_funcs->early_init) + ret = adev->powerplay.ip_funcs->early_init( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_sw_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->sw_init) + ret = adev->powerplay.ip_funcs->sw_init( + adev->powerplay.pp_handle); + +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (amdgpu_powerplay) { + adev->pm.dpm_enabled = true; + amdgpu_pm_sysfs_init(adev); + } +#endif + + return ret; +} + +static int amdgpu_pp_sw_fini(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->sw_fini) + ret = adev->powerplay.ip_funcs->sw_fini( + adev->powerplay.pp_handle); + if (ret) + return ret; + +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (amdgpu_powerplay) { + amdgpu_pm_sysfs_fini(adev); + amd_powerplay_fini(adev->powerplay.pp_handle); + } +#endif + + return ret; +} + +static int amdgpu_pp_hw_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (amdgpu_powerplay && adev->firmware.smu_load) + amdgpu_ucode_init_bo(adev); + + if (adev->powerplay.ip_funcs->hw_init) + ret = adev->powerplay.ip_funcs->hw_init( + adev->powerplay.pp_handle); + + return ret; +} + +static int amdgpu_pp_hw_fini(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->hw_fini) + ret = adev->powerplay.ip_funcs->hw_fini( + adev->powerplay.pp_handle); + + if (amdgpu_powerplay && adev->firmware.smu_load) + amdgpu_ucode_fini_bo(adev); + + return ret; +} + +static int amdgpu_pp_suspend(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->suspend) + ret = adev->powerplay.ip_funcs->suspend( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_resume(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->resume) + ret = adev->powerplay.ip_funcs->resume( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->set_clockgating_state) + ret = adev->powerplay.ip_funcs->set_clockgating_state( + adev->powerplay.pp_handle, state); + return ret; +} + +static int amdgpu_pp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->set_powergating_state) + ret = adev->powerplay.ip_funcs->set_powergating_state( + adev->powerplay.pp_handle, state); + return ret; +} + + +static bool amdgpu_pp_is_idle(void *handle) +{ + bool ret = true; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->is_idle) + ret = adev->powerplay.ip_funcs->is_idle( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_wait_for_idle(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->wait_for_idle) + ret = adev->powerplay.ip_funcs->wait_for_idle( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_soft_reset(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->soft_reset) + ret = adev->powerplay.ip_funcs->soft_reset( + adev->powerplay.pp_handle); + return ret; +} + +static void amdgpu_pp_print_status(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->print_status) + adev->powerplay.ip_funcs->print_status( + adev->powerplay.pp_handle); +} + +const struct amd_ip_funcs amdgpu_pp_ip_funcs = { + .early_init = amdgpu_pp_early_init, + .late_init = NULL, + .sw_init = amdgpu_pp_sw_init, + .sw_fini = amdgpu_pp_sw_fini, + .hw_init = amdgpu_pp_hw_init, + .hw_fini = amdgpu_pp_hw_fini, + .suspend = amdgpu_pp_suspend, + .resume = amdgpu_pp_resume, + .is_idle = amdgpu_pp_is_idle, + .wait_for_idle = amdgpu_pp_wait_for_idle, + .soft_reset = amdgpu_pp_soft_reset, + .print_status = amdgpu_pp_print_status, + .set_clockgating_state = amdgpu_pp_set_clockgating_state, + .set_powergating_state = amdgpu_pp_set_powergating_state, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h new file mode 100644 index 000000000000..da5cf47cfd99 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h @@ -0,0 +1,33 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_POPWERPLAY_H__ +#define __AMDGPU_POPWERPLAY_H__ + +#include "amd_shared.h" + +extern const struct amd_ip_funcs amdgpu_pp_ip_funcs; + +#endif /* __AMDSOC_DM_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 61689f094ba8..c7c298b88170 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -65,6 +65,7 @@ #include "oss/oss_2_0_sh_mask.h" #include "amdgpu_amdkfd.h" +#include "amdgpu_powerplay.h" /* * Indirect registers accessor @@ -1953,7 +1954,7 @@ static const struct amdgpu_ip_block_version bonaire_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &ci_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2021,7 +2022,7 @@ static const struct amdgpu_ip_block_version hawaii_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &ci_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2089,7 +2090,7 @@ static const struct amdgpu_ip_block_version kabini_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2157,7 +2158,7 @@ static const struct amdgpu_ip_block_version mullins_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2225,7 +2226,7 @@ static const struct amdgpu_ip_block_version kaveri_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 30b408f1d5c0..8e4c026824d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -71,6 +71,7 @@ #include "uvd_v5_0.h" #include "uvd_v6_0.h" #include "vce_v3_0.h" +#include "amdgpu_powerplay.h" /* * Indirect registers accessor @@ -1130,7 +1131,7 @@ static const struct amdgpu_ip_block_version topaz_ip_blocks[] = .major = 7, .minor = 1, .rev = 0, - .funcs = &iceland_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_GFX, @@ -1177,7 +1178,7 @@ static const struct amdgpu_ip_block_version tonga_ip_blocks[] = .major = 7, .minor = 1, .rev = 0, - .funcs = &tonga_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -1313,7 +1314,7 @@ static const struct amdgpu_ip_block_version cz_ip_blocks[] = .major = 8, .minor = 0, .rev = 0, - .funcs = &cz_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs }, { .type = AMD_IP_BLOCK_TYPE_DCE, diff --git a/drivers/gpu/drm/amd/powerplay/Kconfig b/drivers/gpu/drm/amd/powerplay/Kconfig new file mode 100644 index 000000000000..af380335b425 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/Kconfig @@ -0,0 +1,6 @@ +config DRM_AMD_POWERPLAY + bool "Enable AMD powerplay component" + depends on DRM_AMDGPU + default n + help + select this option will enable AMD powerplay component. diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile new file mode 100644 index 000000000000..e7428a149b62 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/Makefile @@ -0,0 +1,15 @@ + +subdir-ccflags-y += -Iinclude/drm \ + -Idrivers/gpu/drm/amd/powerplay/inc/ \ + -Idrivers/gpu/drm/amd/include/asic_reg \ + -Idrivers/gpu/drm/amd/include + +AMD_PP_PATH = ../powerplay + +include $(AMD_POWERPLAY) + +POWER_MGR = amd_powerplay.o + +AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_POWER) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c new file mode 100644 index 000000000000..39ffc5d4e49f --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -0,0 +1,194 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include +#include +#include "amd_shared.h" +#include "amd_powerplay.h" + +static int pp_early_init(void *handle) +{ + return 0; +} + +static int pp_sw_init(void *handle) +{ + return 0; +} + +static int pp_sw_fini(void *handle) +{ + return 0; +} + +static int pp_hw_init(void *handle) +{ + return 0; +} + +static int pp_hw_fini(void *handle) +{ + return 0; +} + +static bool pp_is_idle(void *handle) +{ + return 0; +} + +static int pp_wait_for_idle(void *handle) +{ + return 0; +} + +static int pp_sw_reset(void *handle) +{ + return 0; +} + +static void pp_print_status(void *handle) +{ + +} + +static int pp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int pp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static int pp_suspend(void *handle) +{ + return 0; +} + +static int pp_resume(void *handle) +{ + return 0; +} + +const struct amd_ip_funcs pp_ip_funcs = { + .early_init = pp_early_init, + .late_init = NULL, + .sw_init = pp_sw_init, + .sw_fini = pp_sw_fini, + .hw_init = pp_hw_init, + .hw_fini = pp_hw_fini, + .suspend = pp_suspend, + .resume = pp_resume, + .is_idle = pp_is_idle, + .wait_for_idle = pp_wait_for_idle, + .soft_reset = pp_sw_reset, + .print_status = pp_print_status, + .set_clockgating_state = pp_set_clockgating_state, + .set_powergating_state = pp_set_powergating_state, +}; + +static int pp_dpm_load_fw(void *handle) +{ + return 0; +} + +static int pp_dpm_fw_loading_complete(void *handle) +{ + return 0; +} + +static int pp_dpm_force_performance_level(void *handle, + enum amd_dpm_forced_level level) +{ + return 0; +} +static enum amd_dpm_forced_level pp_dpm_get_performance_level( + void *handle) +{ + return 0; +} +static int pp_dpm_get_sclk(void *handle, bool low) +{ + return 0; +} +static int pp_dpm_get_mclk(void *handle, bool low) +{ + return 0; +} +static int pp_dpm_powergate_vce(void *handle, bool gate) +{ + return 0; +} +static int pp_dpm_powergate_uvd(void *handle, bool gate) +{ + return 0; +} + +int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output) +{ + return 0; +} +enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) +{ + return 0; +} +static void +pp_debugfs_print_current_performance_level(void *handle, + struct seq_file *m) +{ + return; +} +const struct amd_powerplay_funcs pp_dpm_funcs = { + .get_temperature = NULL, + .load_firmware = pp_dpm_load_fw, + .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, + .force_performance_level = pp_dpm_force_performance_level, + .get_performance_level = pp_dpm_get_performance_level, + .get_current_power_state = pp_dpm_get_current_power_state, + .get_sclk = pp_dpm_get_sclk, + .get_mclk = pp_dpm_get_mclk, + .powergate_vce = pp_dpm_powergate_vce, + .powergate_uvd = pp_dpm_powergate_uvd, + .dispatch_tasks = pp_dpm_dispatch_tasks, + .print_current_performance_level = pp_debugfs_print_current_performance_level, +}; + +int amd_powerplay_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp) +{ + if (pp_init == NULL || amd_pp == NULL) + return -EINVAL; + + amd_pp->ip_funcs = &pp_ip_funcs; + amd_pp->pp_funcs = &pp_dpm_funcs; + + return 0; +} + +int amd_powerplay_fini(void *handle) +{ + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h new file mode 100644 index 000000000000..09d9d5ae0f13 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -0,0 +1,162 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _AMD_POWERPLAY_H_ +#define _AMD_POWERPLAY_H_ + +#include +#include +#include "amd_shared.h" +#include "cgs_common.h" + + +enum amd_pp_event { + AMD_PP_EVENT_INITIALIZE = 0, + AMD_PP_EVENT_UNINITIALIZE, + AMD_PP_EVENT_POWER_SOURCE_CHANGE, + AMD_PP_EVENT_SUSPEND, + AMD_PP_EVENT_RESUME, + AMD_PP_EVENT_ENTER_REST_STATE, + AMD_PP_EVENT_EXIT_REST_STATE, + AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, + AMD_PP_EVENT_THERMAL_NOTIFICATION, + AMD_PP_EVENT_VBIOS_NOTIFICATION, + AMD_PP_EVENT_ENTER_THERMAL_STATE, + AMD_PP_EVENT_EXIT_THERMAL_STATE, + AMD_PP_EVENT_ENTER_FORCED_STATE, + AMD_PP_EVENT_EXIT_FORCED_STATE, + AMD_PP_EVENT_ENTER_EXCLUSIVE_MODE, + AMD_PP_EVENT_EXIT_EXCLUSIVE_MODE, + AMD_PP_EVENT_ENTER_SCREEN_SAVER, + AMD_PP_EVENT_EXIT_SCREEN_SAVER, + AMD_PP_EVENT_VPU_RECOVERY_BEGIN, + AMD_PP_EVENT_VPU_RECOVERY_END, + AMD_PP_EVENT_ENABLE_POWER_PLAY, + AMD_PP_EVENT_DISABLE_POWER_PLAY, + AMD_PP_EVENT_CHANGE_POWER_SOURCE_UI_LABEL, + AMD_PP_EVENT_ENABLE_USER2D_PERFORMANCE, + AMD_PP_EVENT_DISABLE_USER2D_PERFORMANCE, + AMD_PP_EVENT_ENABLE_USER3D_PERFORMANCE, + AMD_PP_EVENT_DISABLE_USER3D_PERFORMANCE, + AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST, + AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST, + AMD_PP_EVENT_ENABLE_REDUCED_REFRESH_RATE, + AMD_PP_EVENT_DISABLE_REDUCED_REFRESH_RATE, + AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING, + AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING, + AMD_PP_EVENT_ENABLE_CGPG, + AMD_PP_EVENT_DISABLE_CGPG, + AMD_PP_EVENT_ENTER_TEXT_MODE, + AMD_PP_EVENT_EXIT_TEXT_MODE, + AMD_PP_EVENT_VIDEO_START, + AMD_PP_EVENT_VIDEO_STOP, + AMD_PP_EVENT_ENABLE_USER_STATE, + AMD_PP_EVENT_DISABLE_USER_STATE, + AMD_PP_EVENT_READJUST_POWER_STATE, + AMD_PP_EVENT_START_INACTIVITY, + AMD_PP_EVENT_STOP_INACTIVITY, + AMD_PP_EVENT_LINKED_ADAPTERS_READY, + AMD_PP_EVENT_ADAPTER_SAFE_TO_DISABLE, + AMD_PP_EVENT_COMPLETE_INIT, + AMD_PP_EVENT_CRITICAL_THERMAL_FAULT, + AMD_PP_EVENT_BACKLIGHT_CHANGED, + AMD_PP_EVENT_ENABLE_VARI_BRIGHT, + AMD_PP_EVENT_DISABLE_VARI_BRIGHT, + AMD_PP_EVENT_ENABLE_VARI_BRIGHT_ON_POWER_XPRESS, + AMD_PP_EVENT_DISABLE_VARI_BRIGHT_ON_POWER_XPRESS, + AMD_PP_EVENT_SET_VARI_BRIGHT_LEVEL, + AMD_PP_EVENT_VARI_BRIGHT_MONITOR_MEASUREMENT, + AMD_PP_EVENT_SCREEN_ON, + AMD_PP_EVENT_SCREEN_OFF, + AMD_PP_EVENT_PRE_DISPLAY_CONFIG_CHANGE, + AMD_PP_EVENT_ENTER_ULP_STATE, + AMD_PP_EVENT_EXIT_ULP_STATE, + AMD_PP_EVENT_REGISTER_IP_STATE, + AMD_PP_EVENT_UNREGISTER_IP_STATE, + AMD_PP_EVENT_ENTER_MGPU_MODE, + AMD_PP_EVENT_EXIT_MGPU_MODE, + AMD_PP_EVENT_ENTER_MULTI_GPU_MODE, + AMD_PP_EVENT_PRE_SUSPEND, + AMD_PP_EVENT_PRE_RESUME, + AMD_PP_EVENT_ENTER_BACOS, + AMD_PP_EVENT_EXIT_BACOS, + AMD_PP_EVENT_RESUME_BACO, + AMD_PP_EVENT_RESET_BACO, + AMD_PP_EVENT_PRE_DISPLAY_PHY_ACCESS, + AMD_PP_EVENT_POST_DISPLAY_PHY_CCESS, + AMD_PP_EVENT_START_COMPUTE_APPLICATION, + AMD_PP_EVENT_STOP_COMPUTE_APPLICATION, + AMD_PP_EVENT_REDUCE_POWER_LIMIT, + AMD_PP_EVENT_ENTER_FRAME_LOCK, + AMD_PP_EVENT_EXIT_FRAME_LOOCK, + AMD_PP_EVENT_LONG_IDLE_REQUEST_BACO, + AMD_PP_EVENT_LONG_IDLE_ENTER_BACO, + AMD_PP_EVENT_LONG_IDLE_EXIT_BACO, + AMD_PP_EVENT_HIBERNATE, + AMD_PP_EVENT_CONNECTED_STANDBY, + AMD_PP_EVENT_ENTER_SELF_REFRESH, + AMD_PP_EVENT_EXIT_SELF_REFRESH, + AMD_PP_EVENT_START_AVFS_BTC, + AMD_PP_EVENT_MAX +}; + +enum amd_dpm_forced_level { + AMD_DPM_FORCED_LEVEL_AUTO = 0, + AMD_DPM_FORCED_LEVEL_LOW = 1, + AMD_DPM_FORCED_LEVEL_HIGH = 2, +}; + +struct amd_pp_init { + struct cgs_device *device; + uint32_t chip_family; + uint32_t chip_id; + uint32_t rev_id; +}; + +struct amd_powerplay_funcs { + int (*get_temperature)(void *handle); + int (*load_firmware)(void *handle); + int (*wait_for_fw_loading_complete)(void *handle); + int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); + enum amd_dpm_forced_level (*get_performance_level)(void *handle); + enum amd_pm_state_type (*get_current_power_state)(void *handle); + int (*get_sclk)(void *handle, bool low); + int (*get_mclk)(void *handle, bool low); + int (*powergate_vce)(void *handle, bool gate); + int (*powergate_uvd)(void *handle, bool gate); + int (*dispatch_tasks)(void *handle, enum amd_pp_event event_id, + void *input, void *output); + void (*print_current_performance_level)(void *handle, + struct seq_file *m); +}; + +struct amd_powerplay { + void *pp_handle; + const struct amd_ip_funcs *ip_funcs; + const struct amd_powerplay_funcs *pp_funcs; +}; + +int amd_powerplay_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp); +int amd_powerplay_fini(void *handle); + +#endif /* _AMD_POWERPLAY_H_ */ -- cgit v1.2.3 From 1b5708ffb1032a2f24b4224320753532303c1ae4 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 10 Nov 2015 18:25:24 -0500 Subject: drm/amdgpu: export amd_powerplay_func to amdgpu and other ip block Update amdgpu to deal with the new powerplay module properly. v2: squash in fixes v3: squash in Rex's power state reporting fix Signed-off-by: Rex Zhu Acked-by: Jammy Zhou Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 46 ++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 215 +++++++++++++++++++++------------ 2 files changed, 180 insertions(+), 81 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6f08d39a3232..d9ef4d25be79 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2264,20 +2264,54 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) #define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) #define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev)) -#define amdgpu_dpm_get_sclk(adev, l) (adev)->pm.funcs->get_sclk((adev), (l)) -#define amdgpu_dpm_get_mclk(adev, l) (adev)->pm.funcs->get_mclk((adev), (l)) #define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) -#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) -#define amdgpu_dpm_force_performance_level(adev, l) (adev)->pm.funcs->force_performance_level((adev), (l)) #define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) -#define amdgpu_dpm_powergate_uvd(adev, g) (adev)->pm.funcs->powergate_uvd((adev), (g)) -#define amdgpu_dpm_powergate_vce(adev, g) (adev)->pm.funcs->powergate_vce((adev), (g)) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) #define amdgpu_dpm_set_fan_control_mode(adev, m) (adev)->pm.funcs->set_fan_control_mode((adev), (m)) #define amdgpu_dpm_get_fan_control_mode(adev) (adev)->pm.funcs->get_fan_control_mode((adev)) #define amdgpu_dpm_set_fan_speed_percent(adev, s) (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) #define amdgpu_dpm_get_fan_speed_percent(adev, s) (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) +#define amdgpu_dpm_get_sclk(adev, l) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_sclk((adev), (l)) + +#define amdgpu_dpm_get_mclk(adev, l) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_mclk((adev), (l)) + + +#define amdgpu_dpm_force_performance_level(adev, l) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->force_performance_level((adev), (l)) + +#define amdgpu_dpm_powergate_uvd(adev, g) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_uvd((adev), (g)) + +#define amdgpu_dpm_powergate_vce(adev, g) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_vce((adev), (g)) + +#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) + +#define amdgpu_dpm_get_current_power_state(adev) \ + (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_get_performance_level(adev) \ + (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ + (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) + #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) /* Common functions */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index eea1933947ae..235fae54724b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -30,10 +30,16 @@ #include #include +#include "amd_powerplay.h" + static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) { + if (amdgpu_powerplay) + /* TODO */ + return; + if (adev->pm.dpm_enabled) { mutex_lock(&adev->pm.mutex); if (power_supply_is_system_supplied() > 0) @@ -52,7 +58,12 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amd_pm_state_type pm = adev->pm.dpm.user_state; + enum amd_pm_state_type pm; + + if (amdgpu_powerplay) { + pm = amdgpu_dpm_get_current_power_state(adev); + } else + pm = adev->pm.dpm.user_state; return snprintf(buf, PAGE_SIZE, "%s\n", (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : @@ -66,40 +77,57 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; + enum amd_pm_state_type state; - mutex_lock(&adev->pm.mutex); if (strncmp("battery", buf, strlen("battery")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; + state = POWER_STATE_TYPE_BATTERY; else if (strncmp("balanced", buf, strlen("balanced")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + state = POWER_STATE_TYPE_BALANCED; else if (strncmp("performance", buf, strlen("performance")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_PERFORMANCE; + state = POWER_STATE_TYPE_PERFORMANCE; else { - mutex_unlock(&adev->pm.mutex); count = -EINVAL; goto fail; } - mutex_unlock(&adev->pm.mutex); - /* Can't set dpm state when the card is off */ - if (!(adev->flags & AMD_IS_PX) || - (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) - amdgpu_pm_compute_clocks(adev); + if (amdgpu_powerplay) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.user_state = state; + mutex_unlock(&adev->pm.mutex); + + /* Can't set dpm state when the card is off */ + if (!(adev->flags & AMD_IS_PX) || + (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) + amdgpu_pm_compute_clocks(adev); + } fail: return count; } static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level; - return snprintf(buf, PAGE_SIZE, "%s\n", - (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" : - (level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + if (amdgpu_powerplay) { + enum amd_dpm_forced_level level; + + level = amdgpu_dpm_get_performance_level(adev); + return snprintf(buf, PAGE_SIZE, "%s\n", + (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + } else { + enum amdgpu_dpm_forced_level level; + + level = adev->pm.dpm.forced_level; + return snprintf(buf, PAGE_SIZE, "%s\n", + (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + } } static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, @@ -112,7 +140,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, enum amdgpu_dpm_forced_level level; int ret = 0; - mutex_lock(&adev->pm.mutex); if (strncmp("low", buf, strlen("low")) == 0) { level = AMDGPU_DPM_FORCED_LEVEL_LOW; } else if (strncmp("high", buf, strlen("high")) == 0) { @@ -123,7 +150,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, count = -EINVAL; goto fail; } - if (adev->pm.funcs->force_performance_level) { + + if (amdgpu_powerplay) + amdgpu_dpm_force_performance_level(adev, level); + else { + mutex_lock(&adev->pm.mutex); if (adev->pm.dpm.thermal_active) { count = -EINVAL; goto fail; @@ -131,6 +162,9 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, ret = amdgpu_dpm_force_performance_level(adev, level); if (ret) count = -EINVAL; + else + adev->pm.dpm.forced_level = level; + mutex_unlock(&adev->pm.mutex); } fail: mutex_unlock(&adev->pm.mutex); @@ -197,7 +231,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err; int value; - if(!adev->pm.funcs->set_fan_control_mode) + if (!adev->pm.funcs->set_fan_control_mode) return -EINVAL; err = kstrtoint(buf, 10, &value); @@ -294,7 +328,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; - /* Skip attributes if DPM is not enabled */ + if (amdgpu_powerplay) + return 0; /* to do */ + + /* Skip limit attributes if DPM is not enabled */ if (!adev->pm.dpm_enabled && (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr || @@ -635,49 +672,54 @@ done: void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) { - if (adev->pm.funcs->powergate_uvd) { - mutex_lock(&adev->pm.mutex); - /* enable/disable UVD */ + if (amdgpu_powerplay) amdgpu_dpm_powergate_uvd(adev, !enable); - mutex_unlock(&adev->pm.mutex); - } else { - if (enable) { + else { + if (adev->pm.funcs->powergate_uvd) { mutex_lock(&adev->pm.mutex); - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + /* enable/disable UVD */ + amdgpu_dpm_powergate_uvd(adev, !enable); mutex_unlock(&adev->pm.mutex); } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.uvd_active = false; - mutex_unlock(&adev->pm.mutex); + if (enable) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + mutex_unlock(&adev->pm.mutex); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.uvd_active = false; + mutex_unlock(&adev->pm.mutex); + } + amdgpu_pm_compute_clocks(adev); } - amdgpu_pm_compute_clocks(adev); } } void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { - if (adev->pm.funcs->powergate_vce) { - mutex_lock(&adev->pm.mutex); - /* enable/disable VCE */ + if (amdgpu_powerplay) amdgpu_dpm_powergate_vce(adev, !enable); - - mutex_unlock(&adev->pm.mutex); - } else { - if (enable) { + else { + if (adev->pm.funcs->powergate_vce) { mutex_lock(&adev->pm.mutex); - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL; + amdgpu_dpm_powergate_vce(adev, !enable); mutex_unlock(&adev->pm.mutex); } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.vce_active = false; - mutex_unlock(&adev->pm.mutex); + if (enable) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL; + mutex_unlock(&adev->pm.mutex); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.vce_active = false; + mutex_unlock(&adev->pm.mutex); + } + amdgpu_pm_compute_clocks(adev); } - - amdgpu_pm_compute_clocks(adev); } } @@ -685,10 +727,13 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - printk("== power state %d ==\n", i); + if (amdgpu_powerplay) + /* TO DO */ + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - } + } int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) @@ -698,8 +743,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; - if (adev->pm.funcs->get_temperature == NULL) - return 0; + if (!amdgpu_powerplay) { + if (adev->pm.funcs->get_temperature == NULL) + return 0; + } + adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, DRIVER_NAME, adev, hwmon_groups); @@ -748,32 +796,43 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) if (!adev->pm.dpm_enabled) return; - mutex_lock(&adev->pm.mutex); + if (amdgpu_powerplay) { + int i = 0; + + amdgpu_display_bandwidth_update(adev); + mutex_lock(&adev->ring_lock); + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->ready) + amdgpu_fence_wait_empty(ring); + } + mutex_unlock(&adev->ring_lock); - /* update active crtc counts */ - adev->pm.dpm.new_active_crtcs = 0; - adev->pm.dpm.new_active_crtc_count = 0; - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { - adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); - adev->pm.dpm.new_active_crtc_count++; + amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.new_active_crtcs = 0; + adev->pm.dpm.new_active_crtc_count = 0; + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled) { + adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); + adev->pm.dpm.new_active_crtc_count++; + } } } - } - - /* update battery/ac status */ - if (power_supply_is_system_supplied() > 0) - adev->pm.dpm.ac_power = true; - else - adev->pm.dpm.ac_power = false; - - amdgpu_dpm_change_power_state_locked(adev); + /* update battery/ac status */ + if (power_supply_is_system_supplied() > 0) + adev->pm.dpm.ac_power = true; + else + adev->pm.dpm.ac_power = false; - mutex_unlock(&adev->pm.mutex); + amdgpu_dpm_change_power_state_locked(adev); + mutex_unlock(&adev->pm.mutex); + } } /* @@ -787,7 +846,13 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = dev->dev_private; - if (adev->pm.dpm_enabled) { + if (!adev->pm.dpm_enabled) { + seq_printf(m, "dpm not enabled\n"); + return 0; + } + if (amdgpu_powerplay) { + amdgpu_dpm_debugfs_print_current_performance_level(adev, m); + } else { mutex_lock(&adev->pm.mutex); if (adev->pm.funcs->debugfs_print_current_performance_level) amdgpu_dpm_debugfs_print_current_performance_level(adev, m); -- cgit v1.2.3 From 3af76f23a45b75441b8eac30aa5a7d957e699e73 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 15 Oct 2015 17:23:43 +0800 Subject: drm/amdgpu: export fan control functions to amdgpu Hook up the amdgpu thermal control callbacks for powerplay. Signed-off-by: Rex Zhu Reviewed-by: Jammy Zhou Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d9ef4d25be79..8b1ff13d50cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2259,7 +2259,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s)) #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) -#define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev)) #define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) #define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) #define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) @@ -2267,10 +2266,31 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) #define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) -#define amdgpu_dpm_set_fan_control_mode(adev, m) (adev)->pm.funcs->set_fan_control_mode((adev), (m)) -#define amdgpu_dpm_get_fan_control_mode(adev) (adev)->pm.funcs->get_fan_control_mode((adev)) -#define amdgpu_dpm_set_fan_speed_percent(adev, s) (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) -#define amdgpu_dpm_get_fan_speed_percent(adev, s) (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) + +#define amdgpu_dpm_get_temperature(adev) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_temperature((adev)) + +#define amdgpu_dpm_set_fan_control_mode(adev, m) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->set_fan_control_mode((adev), (m)) + +#define amdgpu_dpm_get_fan_control_mode(adev) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_fan_control_mode((adev)) + +#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) + +#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ + amdgpu_powerplay ? \ + (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) #define amdgpu_dpm_get_sclk(adev, l) \ amdgpu_powerplay ? \ -- cgit v1.2.3 From e61710c59dd205b48413762b2aedd46e86df3c45 Mon Sep 17 00:00:00 2001 From: Jammy Zhou Date: Tue, 10 Nov 2015 18:31:08 -0500 Subject: drm/amdgpu: support per device powerplay enablement (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The amdgu_powerplay variable is global for multiple GPU instances. v2: fold in Flora's module option change, protect adev reference in macros Signed-off-by: Jammy Zhou Reviewed-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 71 ++++++++++++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 30 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 15 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 2 +- 6 files changed, 65 insertions(+), 61 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 8b1ff13d50cc..637eff393bc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2040,6 +2040,7 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; + bool pp_enabled; /* dpm */ struct amdgpu_pm pm; @@ -2268,68 +2269,68 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) #define amdgpu_dpm_get_temperature(adev) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_temperature((adev)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_temperature((adev)) #define amdgpu_dpm_set_fan_control_mode(adev, m) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->set_fan_control_mode((adev), (m)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->set_fan_control_mode((adev), (m)) #define amdgpu_dpm_get_fan_control_mode(adev) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_fan_control_mode((adev)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_fan_control_mode((adev)) #define amdgpu_dpm_set_fan_speed_percent(adev, s) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) #define amdgpu_dpm_get_fan_speed_percent(adev, s) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) #define amdgpu_dpm_get_sclk(adev, l) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ (adev)->pm.funcs->get_sclk((adev), (l)) #define amdgpu_dpm_get_mclk(adev, l) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_mclk((adev), (l)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_mclk((adev), (l)) #define amdgpu_dpm_force_performance_level(adev, l) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->force_performance_level((adev), (l)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->force_performance_level((adev), (l)) #define amdgpu_dpm_powergate_uvd(adev, g) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_uvd((adev), (g)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_uvd((adev), (g)) #define amdgpu_dpm_powergate_vce(adev, g) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_vce((adev), (g)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_vce((adev), (g)) #define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) \ - amdgpu_powerplay ? \ - (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) #define amdgpu_dpm_get_current_power_state(adev) \ - (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) + (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) #define amdgpu_dpm_get_performance_level(adev) \ - (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) + (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) -#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ +#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a15ca4c7cf60..b5dbbb573491 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -82,7 +82,7 @@ int amdgpu_enable_scheduler = 1; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_enable_semaphores = 0; -int amdgpu_powerplay = 0; +int amdgpu_powerplay = -1; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); @@ -166,7 +166,7 @@ MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable, 0 = disable module_param_named(enable_semaphores, amdgpu_enable_semaphores, int, 0644); #ifdef CONFIG_DRM_AMD_POWERPLAY -MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable (default))"); +MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))"); module_param_named(powerplay, amdgpu_powerplay, int, 0444); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 40ae30530a01..3b78982abaf1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -36,7 +36,7 @@ static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) { - if (amdgpu_powerplay) + if (adev->pp_enabled) /* TODO */ return; @@ -60,7 +60,7 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; enum amd_pm_state_type pm; - if (amdgpu_powerplay) { + if (adev->pp_enabled) { pm = amdgpu_dpm_get_current_power_state(adev); } else pm = adev->pm.dpm.user_state; @@ -90,7 +90,7 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev, goto fail; } - if (amdgpu_powerplay) { + if (adev->pp_enabled) { amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); } else { mutex_lock(&adev->pm.mutex); @@ -113,7 +113,7 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (amdgpu_powerplay) { + if (adev->pp_enabled) { enum amd_dpm_forced_level level; level = amdgpu_dpm_get_performance_level(adev); @@ -151,7 +151,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, goto fail; } - if (amdgpu_powerplay) + if (adev->pp_enabled) amdgpu_dpm_force_performance_level(adev, level); else { mutex_lock(&adev->pm.mutex); @@ -184,7 +184,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, struct amdgpu_device *adev = dev_get_drvdata(dev); int temp; - if (!amdgpu_powerplay && !adev->pm.funcs->get_temperature) + if (!adev->pp_enabled && !adev->pm.funcs->get_temperature) temp = 0; else temp = amdgpu_dpm_get_temperature(adev); @@ -215,7 +215,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, struct amdgpu_device *adev = dev_get_drvdata(dev); u32 pwm_mode = 0; - if (!amdgpu_powerplay && !adev->pm.funcs->get_fan_control_mode) + if (!adev->pp_enabled && !adev->pm.funcs->get_fan_control_mode) return -EINVAL; pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); @@ -233,7 +233,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err; int value; - if (!amdgpu_powerplay && !adev->pm.funcs->set_fan_control_mode) + if (!adev->pp_enabled && !adev->pm.funcs->set_fan_control_mode) return -EINVAL; err = kstrtoint(buf, 10, &value); @@ -340,7 +340,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; - if (amdgpu_powerplay) + if (adev->pp_enabled) return effective_mode; /* Skip fan attributes if fan is not present */ @@ -674,7 +674,7 @@ done: void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) { - if (amdgpu_powerplay) + if (adev->pp_enabled) amdgpu_dpm_powergate_uvd(adev, !enable); else { if (adev->pm.funcs->powergate_uvd) { @@ -701,7 +701,7 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { - if (amdgpu_powerplay) + if (adev->pp_enabled) amdgpu_dpm_powergate_vce(adev, !enable); else { if (adev->pm.funcs->powergate_vce) { @@ -729,7 +729,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) { int i; - if (amdgpu_powerplay) + if (adev->pp_enabled) /* TO DO */ return; @@ -745,7 +745,7 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; - if (!amdgpu_powerplay) { + if (!adev->pp_enabled) { if (adev->pm.funcs->get_temperature == NULL) return 0; } @@ -798,7 +798,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) if (!adev->pm.dpm_enabled) return; - if (amdgpu_powerplay) { + if (adev->pp_enabled) { int i = 0; amdgpu_display_bandwidth_update(adev); @@ -852,7 +852,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) seq_printf(m, "dpm not enabled\n"); return 0; } - if (amdgpu_powerplay) { + if (adev->pp_enabled) { amdgpu_dpm_debugfs_print_current_performance_level(adev, m); } else { mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 1ff6fd54df61..6b46fbfd6be4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -40,7 +40,7 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) amd_pp = &(adev->powerplay); - if (amdgpu_powerplay) { + if (adev->pp_enabled) { #ifdef CONFIG_DRM_AMD_POWERPLAY struct amd_pp_init *pp_init; @@ -100,11 +100,14 @@ static int amdgpu_pp_early_init(void *handle) switch (adev->asic_type) { case CHIP_TONGA: case CHIP_FIJI: - amdgpu_powerplay = 1; + adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true; break; default: + adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; break; } +#else + adev->pp_enabled = false; #endif ret = amdgpu_powerplay_init(adev); @@ -127,7 +130,7 @@ static int amdgpu_pp_sw_init(void *handle) adev->powerplay.pp_handle); #ifdef CONFIG_DRM_AMD_POWERPLAY - if (amdgpu_powerplay) { + if (adev->pp_enabled) { adev->pm.dpm_enabled = true; amdgpu_pm_sysfs_init(adev); } @@ -148,7 +151,7 @@ static int amdgpu_pp_sw_fini(void *handle) return ret; #ifdef CONFIG_DRM_AMD_POWERPLAY - if (amdgpu_powerplay) { + if (adev->pp_enabled) { amdgpu_pm_sysfs_fini(adev); amd_powerplay_fini(adev->powerplay.pp_handle); } @@ -162,7 +165,7 @@ static int amdgpu_pp_hw_init(void *handle) int ret = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (amdgpu_powerplay && adev->firmware.smu_load) + if (adev->pp_enabled && adev->firmware.smu_load) amdgpu_ucode_init_bo(adev); if (adev->powerplay.ip_funcs->hw_init) @@ -181,7 +184,7 @@ static int amdgpu_pp_hw_fini(void *handle) ret = adev->powerplay.ip_funcs->hw_fini( adev->powerplay.pp_handle); - if (amdgpu_powerplay && adev->firmware.smu_load) + if (adev->pp_enabled && adev->firmware.smu_load) amdgpu_ucode_fini_bo(adev); return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index d90aae08445e..6c063a4a2c38 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -2902,7 +2902,7 @@ static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) gfx_v8_0_rlc_reset(adev); - if (!amdgpu_powerplay) { + if (!adev->pp_enabled) { if (!adev->firmware.smu_load) { /* legacy rlc firmware loading */ r = gfx_v8_0_rlc_load_microcode(adev); @@ -3804,7 +3804,7 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) if (!(adev->flags & AMD_IS_APU)) gfx_v8_0_enable_gui_idle_interrupt(adev, false); - if (!amdgpu_powerplay) { + if (!adev->pp_enabled) { if (!adev->firmware.smu_load) { /* legacy firmware loading */ r = gfx_v8_0_cp_gfx_load_microcode(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 8091c1c37c4e..c741c091bc9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -727,7 +727,7 @@ static int sdma_v3_0_start(struct amdgpu_device *adev) { int r, i; - if (!amdgpu_powerplay) { + if (!adev->pp_enabled) { if (!adev->firmware.smu_load) { r = sdma_v3_0_load_microcode(adev); if (r) -- cgit v1.2.3 From d0dd7f0cc345fc8757148004639e1993ba183bd6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Nov 2015 19:45:06 -0500 Subject: drm/amdgpu: store pcie gen mask and link width We'll need this later for pcie dpm. Reviewed-by: Jammy Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 78 ++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/cik.c | 24 ++++----- drivers/gpu/drm/amd/amdgpu/vi.c | 13 ++--- 4 files changed, 99 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 637eff393bc7..26d9134f7c0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1637,8 +1637,12 @@ struct amdgpu_pm { const struct firmware *fw; /* SMC firmware */ uint32_t fw_version; const struct amdgpu_dpm_funcs *funcs; + uint32_t pcie_gen_mask; + uint32_t pcie_mlw_mask; }; +void amdgpu_get_pcie_info(struct amdgpu_device *adev); + /* * UVD */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 587ff7145361..65531463f88e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -38,6 +38,7 @@ #include "amdgpu_i2c.h" #include "atom.h" #include "amdgpu_atombios.h" +#include "amd_pcie.h" #ifdef CONFIG_DRM_AMDGPU_CIK #include "cik.h" #endif @@ -1932,6 +1933,83 @@ retry: return r; } +void amdgpu_get_pcie_info(struct amdgpu_device *adev) +{ + u32 mask; + int ret; + + if (pci_is_root_bus(adev->pdev->bus)) + return; + + if (amdgpu_pcie_gen2 == 0) + return; + + if (adev->flags & AMD_IS_APU) + return; + + ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); + if (!ret) { + adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3); + + if (mask & DRM_PCIE_SPEED_25) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1; + if (mask & DRM_PCIE_SPEED_50) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2; + if (mask & DRM_PCIE_SPEED_80) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3; + } + ret = drm_pcie_get_max_link_width(adev->ddev, &mask); + if (!ret) { + switch (mask) { + case 32: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 16: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 12: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 8: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 4: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 2: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 1: + adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1; + break; + default: + break; + } + } +} /* * Debugfs diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index c7c298b88170..fd9c9588ef46 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -32,6 +32,7 @@ #include "amdgpu_vce.h" #include "cikd.h" #include "atom.h" +#include "amd_pcie.h" #include "cik.h" #include "gmc_v7_0.h" @@ -1595,8 +1596,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) { struct pci_dev *root = adev->pdev->bus->self; int bridge_pos, gpu_pos; - u32 speed_cntl, mask, current_data_rate; - int ret, i; + u32 speed_cntl, current_data_rate; + int i; u16 tmp16; if (pci_is_root_bus(adev->pdev->bus)) @@ -1608,23 +1609,20 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) if (adev->flags & AMD_IS_APU) return; - ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) return; speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL); current_data_rate = (speed_cntl & PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - if (mask & DRM_PCIE_SPEED_80) { + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { if (current_data_rate == 2) { DRM_INFO("PCIE gen 3 link speeds already enabled\n"); return; } DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); - } else if (mask & DRM_PCIE_SPEED_50) { + } else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) { if (current_data_rate == 1) { DRM_INFO("PCIE gen 2 link speeds already enabled\n"); return; @@ -1640,7 +1638,7 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) if (!gpu_pos) return; - if (mask & DRM_PCIE_SPEED_80) { + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { /* re-try equalization if gen3 is not already enabled */ if (current_data_rate != 2) { u16 bridge_cfg, gpu_cfg; @@ -1735,9 +1733,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); tmp16 &= ~0xf; - if (mask & DRM_PCIE_SPEED_80) + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) tmp16 |= 3; /* gen3 */ - else if (mask & DRM_PCIE_SPEED_50) + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) tmp16 |= 2; /* gen2 */ else tmp16 |= 1; /* gen1 */ @@ -2450,6 +2448,8 @@ static int cik_common_early_init(void *handle) return -EINVAL; } + amdgpu_get_pcie_info(adev); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index e51070e9697a..25d620790607 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -31,6 +31,7 @@ #include "amdgpu_vce.h" #include "amdgpu_ucode.h" #include "atom.h" +#include "amd_pcie.h" #include "gmc/gmc_8_1_d.h" #include "gmc/gmc_8_1_sh_mask.h" @@ -1052,9 +1053,6 @@ static int vi_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk) static void vi_pcie_gen3_enable(struct amdgpu_device *adev) { - u32 mask; - int ret; - if (pci_is_root_bus(adev->pdev->bus)) return; @@ -1064,11 +1062,8 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev) if (adev->flags & AMD_IS_APU) return; - ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) return; /* todo */ @@ -1473,6 +1468,8 @@ static int vi_common_early_init(void *handle) if (amdgpu_smc_load_fw && smc_enabled) adev->firmware.smu_load = true; + amdgpu_get_pcie_info(adev); + return 0; } -- cgit v1.2.3 From 7fb72a1fc01cc1a8de533abc80b9eaf0120e8529 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 19 Nov 2015 13:35:30 +0800 Subject: drm/amd/powerplay: export interface to DAL to init/change display configuration. Signed-off-by: Rex Zhu Signed-off-by: David Rokhvarg Reviewed-by: Alex Deucher Reviewed-by: Jammy Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 9 +++++++++ drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h | 3 +++ 5 files changed, 45 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 26d9134f7c0d..a3fc43e52483 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1639,6 +1639,7 @@ struct amdgpu_pm { const struct amdgpu_dpm_funcs *funcs; uint32_t pcie_gen_mask; uint32_t pcie_mlw_mask; + struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ }; void amdgpu_get_pcie_info(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 10385c0fb60d..215757e0ad76 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -603,3 +603,19 @@ int amd_powerplay_fini(void *handle) return 0; } + +/* export this function to DAL */ + +int amd_powerplay_display_configuration_change(void *handle, const void *input) +{ + struct pp_hwmgr *hwmgr; + const struct amd_pp_display_configuration *display_config = input; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + phm_store_dal_configuration_data(hwmgr, display_config); + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c index f2d603cff47d..d6d28497d7d9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -26,6 +26,7 @@ #include "power_state.h" #include "pp_acpi.h" #include "amd_acpi.h" +#include "amd_powerplay.h" void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr) { @@ -244,3 +245,18 @@ int phm_check_states_equal(struct pp_hwmgr *hwmgr, return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal); } + +int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config) +{ + if (hwmgr == NULL || hwmgr->hwmgr_func->store_cc6_data == NULL) + return -EINVAL; + + /* to do pass other display configuration in furture */ + return hwmgr->hwmgr_func->store_cc6_data(hwmgr, + display_config->cpu_pstate_separation_time, + display_config->cpu_cc6_disable, + display_config->cpu_pstate_disable, + display_config->nb_pstate_switch_disable); + +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 40ded6795ba4..efa23c182bd0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -131,6 +131,13 @@ struct amd_pp_init { uint32_t rev_id; }; +struct amd_pp_display_configuration { + bool nb_pstate_switch_disable;/* controls NB PState switch */ + bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ + bool cpu_pstate_disable; + uint32_t cpu_pstate_separation_time; +}; + enum { PP_GROUP_UNKNOWN = 0, PP_GROUP_GFX = 1, @@ -203,4 +210,6 @@ int amd_powerplay_init(struct amd_pp_init *pp_init, struct amd_powerplay *amd_pp); int amd_powerplay_fini(void *handle); +int amd_powerplay_display_configuration_change(void *handle, const void *input); + #endif /* _AMD_POWERPLAY_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index a3f7bd27a2fb..7b721e8ea531 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -353,5 +353,8 @@ extern int phm_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate2, bool *equal); +extern int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config); + #endif /* _HARDWARE_MANAGER_H_ */ -- cgit v1.2.3 From eceb8a1562db6fc3e1c21cd54a4be0189aa1d0e3 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 Jan 2016 15:35:21 +0100 Subject: drm/amdgpu: move VM page tables to the LRU end on CS v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it less likely to run into an ENOMEM because VM page tables are evicted last. v2: move the BOs in the LRU tail after validation Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 7 ++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu.h') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 003959f99251..313b0cc8d676 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -987,6 +987,8 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates); +void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, + struct amdgpu_vm *vm); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index ce0254d4dcd7..1fffc338f69d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -428,8 +428,10 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates); error_validate: - if (r) + if (r) { + amdgpu_vm_move_pt_bos_in_lru(p->adev, &fpriv->vm); ttm_eu_backoff_reservation(&p->ticket, &p->validated); + } error_reserve: if (need_mmap_lock) @@ -473,8 +475,11 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a, **/ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) { + struct amdgpu_fpriv *fpriv = parser->filp->driver_priv; unsigned i; + amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm); + if (!error) { /* Sort the buffer list from the smallest to largest buffer, * which affects the order of buffers in the LRU list. diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 8f7688e598a1..aefc668e6b5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -119,6 +119,33 @@ void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates) list_add(&entry->tv.head, duplicates); } + +} + +/** + * amdgpu_vm_move_pt_bos_in_lru - move the PT BOs to the LRU tail + * + * @adev: amdgpu device instance + * @vm: vm providing the BOs + * + * Move the PT BOs to the tail of the LRU. + */ +void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, + struct amdgpu_vm *vm) +{ + struct ttm_bo_global *glob = adev->mman.bdev.glob; + unsigned i; + + spin_lock(&glob->lru_lock); + for (i = 0; i <= vm->max_pde_used; ++i) { + struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + + if (!entry->robj) + continue; + + ttm_bo_move_to_lru_tail(&entry->robj->tbo); + } + spin_unlock(&glob->lru_lock); } /** -- cgit v1.2.3