diff options
Diffstat (limited to 'drivers/accel/amdxdna/aie2_ctx.c')
| -rw-r--r-- | drivers/accel/amdxdna/aie2_ctx.c | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index baf9a8b90a4d..9c6b7353cbe9 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -7,6 +7,7 @@ #include <drm/drm_device.h> #include <drm/drm_gem.h> #include <drm/drm_gem_shmem_helper.h> +#include <drm/drm_managed.h> #include <drm/drm_print.h> #include <drm/drm_syncobj.h> #include <linux/hmm.h> @@ -99,9 +100,9 @@ static void aie2_job_put(struct amdxdna_sched_job *job) static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx, struct drm_sched_job *bad_job) { - drm_sched_stop(&hwctx->priv->sched, bad_job); + drm_sched_stop(hwctx->priv->sched, bad_job); aie2_destroy_context(xdna->dev_handle, hwctx); - drm_sched_start(&hwctx->priv->sched, 0); + drm_sched_start(hwctx->priv->sched, 0); } static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx) @@ -289,6 +290,7 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size) int ret = 0; u32 status; + amdxdna_io_stats_job_done(job->hwctx->client); cmd_abo = job->cmd_bo; if (unlikely(job->job_timeout)) { @@ -321,6 +323,8 @@ aie2_sched_drvcmd_resp_handler(void *handle, void __iomem *data, size_t size) struct amdxdna_sched_job *job = handle; int ret = 0; + amdxdna_io_stats_job_done(job->hwctx->client); + if (unlikely(!data || size != sizeof(u32))) { job->drv_cmd->result = U32_MAX; ret = -EINVAL; @@ -343,6 +347,7 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size) u32 cmd_status; int ret = 0; + amdxdna_io_stats_job_done(job->hwctx->client); cmd_abo = job->cmd_bo; if (unlikely(job->job_timeout)) { @@ -404,6 +409,7 @@ aie2_sched_job_run(struct drm_sched_job *sched_job) kref_get(&job->refcnt); fence = dma_fence_get(job->fence); + amdxdna_io_stats_job_start(job->hwctx->client); if (job->drv_cmd) { switch (job->drv_cmd->opcode) { case SYNC_DEBUG_BO: @@ -431,6 +437,7 @@ aie2_sched_job_run(struct drm_sched_job *sched_job) out: if (ret) { + amdxdna_io_stats_job_done(job->hwctx->client); dma_fence_put(job->fence); aie2_job_put(job); mmput(job->mm); @@ -659,10 +666,19 @@ static void aie2_ctx_syncobj_destroy(struct amdxdna_hwctx *hwctx) drm_syncobj_put(hwctx->priv->syncobj); } -int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) +void aie2_hwctx_sched_fini(struct amdxdna_dev_hdl *ndev) { - struct amdxdna_client *client = hwctx->client; - struct amdxdna_dev *xdna = client->xdna; + int i; + + for (i = 0; i < ndev->priv->hwctx_limit; i++) + drm_sched_fini(&ndev->hwctx_sched[i]); + + ida_destroy(&ndev->hwctx_sched_ida); +} + +int aie2_hwctx_sched_init(struct amdxdna_dev_hdl *ndev) +{ + struct amdxdna_dev *xdna = ndev->aie.xdna; const struct drm_sched_init_args args = { .ops = &sched_ops, .num_rqs = DRM_SCHED_PRIORITY_COUNT, @@ -673,7 +689,55 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) .name = "amdxdna_js", .dev = xdna->ddev.dev, }; - struct drm_gpu_scheduler *sched; + int i, ret; + + ndev->hwctx_sched = drmm_kcalloc(&xdna->ddev, ndev->priv->hwctx_limit, + sizeof(*ndev->hwctx_sched), GFP_KERNEL); + if (!ndev->hwctx_sched) + return -ENOMEM; + + for (i = 0; i < ndev->priv->hwctx_limit; i++) { + ret = drm_sched_init(&ndev->hwctx_sched[i], &args); + if (ret) { + XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret); + goto fini_sched; + } + } + + ida_init(&ndev->hwctx_sched_ida); + + return 0; + +fini_sched: + while (--i >= 0) + drm_sched_fini(&ndev->hwctx_sched[i]); + + return ret; +} + +static struct drm_gpu_scheduler *aie2_hwctx_sched_alloc(struct amdxdna_dev_hdl *ndev) +{ + int ret; + + ret = ida_alloc_range(&ndev->hwctx_sched_ida, 0, + ndev->priv->hwctx_limit - 1, GFP_KERNEL); + if (ret < 0) + return ERR_PTR(ret); + + return &ndev->hwctx_sched[ret]; +} + +static void aie2_hwctx_sched_free(struct amdxdna_dev_hdl *ndev, + struct drm_gpu_scheduler *sched) +{ + ida_free(&ndev->hwctx_sched_ida, sched - ndev->hwctx_sched); +} + +int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) +{ + struct amdxdna_client *client = hwctx->client; + struct amdxdna_dev *xdna = client->xdna; + struct amdxdna_dev_hdl *ndev = xdna->dev_handle; struct amdxdna_hwctx_priv *priv; struct amdxdna_gem_obj *heap; int i, ret; @@ -683,13 +747,26 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) return -ENOMEM; hwctx->priv = priv; + priv->sched = aie2_hwctx_sched_alloc(ndev); + if (IS_ERR(priv->sched)) { + ret = PTR_ERR(priv->sched); + goto free_priv; + } + + ret = drm_sched_entity_init(&priv->entity, DRM_SCHED_PRIORITY_NORMAL, + &priv->sched, 1, NULL); + if (ret) { + XDNA_ERR(xdna, "Failed to initial sched entity. ret %d", ret); + goto free_sched; + } + mutex_lock(&client->mm_lock); heap = xa_load(&client->dev_heap_xa, 0); if (!heap) { XDNA_ERR(xdna, "The client dev heap object not exist"); mutex_unlock(&client->mm_lock); ret = -ENOENT; - goto free_priv; + goto free_entity; } drm_gem_object_get(to_gobj(heap)); mutex_unlock(&client->mm_lock); @@ -722,30 +799,16 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) priv->cmd_buf[i] = abo; } - sched = &priv->sched; mutex_init(&priv->io_lock); fs_reclaim_acquire(GFP_KERNEL); might_lock(&priv->io_lock); fs_reclaim_release(GFP_KERNEL); - ret = drm_sched_init(sched, &args); - if (ret) { - XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret); - goto free_cmd_bufs; - } - - ret = drm_sched_entity_init(&priv->entity, DRM_SCHED_PRIORITY_NORMAL, - &sched, 1, NULL); - if (ret) { - XDNA_ERR(xdna, "Failed to initial sched entiry. ret %d", ret); - goto free_sched; - } - ret = aie2_hwctx_col_list(hwctx); if (ret) { XDNA_ERR(xdna, "Create col list failed, ret %d", ret); - goto free_entity; + goto free_cmd_bufs; } ret = amdxdna_pm_resume_get_locked(xdna); @@ -791,19 +854,20 @@ suspend_put: amdxdna_pm_suspend_put(xdna); free_col_list: kfree(hwctx->col_list); -free_entity: - drm_sched_entity_destroy(&priv->entity); -free_sched: - drm_sched_fini(&priv->sched); free_cmd_bufs: for (i = 0; i < ARRAY_SIZE(priv->cmd_buf); i++) { if (!priv->cmd_buf[i]) continue; + amdxdna_gem_heap_free(client, priv->cmd_buf[i]); drm_gem_object_put(to_gobj(priv->cmd_buf[i])); } amdxdna_gem_unpin(heap); put_heap: drm_gem_object_put(to_gobj(heap)); +free_entity: + drm_sched_entity_destroy(&priv->entity); +free_sched: + aie2_hwctx_sched_free(ndev, priv->sched); free_priv: kfree(priv); return ret; @@ -811,18 +875,20 @@ free_priv: void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) { + struct amdxdna_dev_hdl *ndev; struct amdxdna_dev *xdna; int idx; xdna = hwctx->client->xdna; + ndev = xdna->dev_handle; XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); aie2_hwctx_wait_for_idle(hwctx); /* Request fw to destroy hwctx and cancel the rest pending requests */ - drm_sched_stop(&hwctx->priv->sched, NULL); + drm_sched_stop(hwctx->priv->sched, NULL); aie2_release_resource(hwctx); - drm_sched_start(&hwctx->priv->sched, 0); + drm_sched_start(hwctx->priv->sched, 0); mutex_unlock(&xdna->dev_lock); drm_sched_entity_destroy(&hwctx->priv->entity); @@ -833,11 +899,17 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) atomic64_read(&hwctx->job_free_cnt)); mutex_lock(&xdna->dev_lock); - drm_sched_fini(&hwctx->priv->sched); + aie2_hwctx_sched_free(ndev, hwctx->priv->sched); aie2_ctx_syncobj_destroy(hwctx); - for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++) + for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++) { + /* + * The open/close will never be called for driver allocated + * dev bo. Call amdxdna_gem_heap_free explicitly. + */ + amdxdna_gem_heap_free(hwctx->client, hwctx->priv->cmd_buf[idx]); drm_gem_object_put(to_gobj(hwctx->priv->cmd_buf[idx])); + } amdxdna_gem_unpin(hwctx->priv->heap); drm_gem_object_put(to_gobj(hwctx->priv->heap)); |
