Skip to content

Commit cd72722

Browse files
jlawrynodanvet
authored andcommitted
accel/ivpu: Add command buffer submission logic
Each of the user contexts has two command queues, one for compute engine and one for the copy engine. Command queues are allocated and registered in the device when the first job (command buffer) is submitted from the user space to the VPU device. The userspace provides a list of GEM buffer object handles to submit to the VPU, the driver resolves buffer handles, pins physical memory if needed, increments ref count for each buffer and stores pointers to buffer objects in the ivpu_job objects that track jobs submitted to the device. The VPU signals job completion with an asynchronous message that contains the job id passed to firmware when the job was submitted. Currently, the driver supports simple scheduling logic where jobs submitted from user space are immediately pushed to the VPU device command queues. In the future, it will be extended to use hardware base scheduling and/or drm_sched. Co-developed-by: Andrzej Kacprowski <[email protected]> Signed-off-by: Andrzej Kacprowski <[email protected]> Signed-off-by: Jacek Lawrynowicz <[email protected]> Reviewed-by: Oded Gabbay <[email protected]> Reviewed-by: Jeffrey Hugo <[email protected]> Signed-off-by: Daniel Vetter <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 02d5b0a commit cd72722

File tree

8 files changed

+824
-4
lines changed

8 files changed

+824
-4
lines changed

drivers/accel/ivpu/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ intel_vpu-y := \
77
ivpu_gem.o \
88
ivpu_hw_mtl.o \
99
ivpu_ipc.o \
10+
ivpu_job.o \
1011
ivpu_jsm_msg.o \
1112
ivpu_mmu.o \
1213
ivpu_mmu_context.o

drivers/accel/ivpu/ivpu_drv.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ivpu_gem.h"
2121
#include "ivpu_hw.h"
2222
#include "ivpu_ipc.h"
23+
#include "ivpu_job.h"
2324
#include "ivpu_jsm_msg.h"
2425
#include "ivpu_mmu.h"
2526
#include "ivpu_mmu_context.h"
@@ -31,6 +32,8 @@
3132

3233
static const struct drm_driver driver;
3334

35+
static struct lock_class_key submitted_jobs_xa_lock_class_key;
36+
3437
int ivpu_dbg_mask;
3538
module_param_named(dbg_mask, ivpu_dbg_mask, int, 0644);
3639
MODULE_PARM_DESC(dbg_mask, "Driver debug mask. See IVPU_DBG_* macros.");
@@ -84,8 +87,11 @@ static void file_priv_release(struct kref *ref)
8487

8588
ivpu_dbg(vdev, FILE, "file_priv release: ctx %u\n", file_priv->ctx.id);
8689

90+
ivpu_cmdq_release_all(file_priv);
91+
ivpu_bo_remove_all_bos_from_context(&file_priv->ctx);
8792
ivpu_mmu_user_context_fini(vdev, &file_priv->ctx);
8893
drm_WARN_ON(&vdev->drm, xa_erase_irq(&vdev->context_xa, file_priv->ctx.id) != file_priv);
94+
mutex_destroy(&file_priv->lock);
8995
kfree(file_priv);
9096
}
9197

@@ -209,10 +215,11 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file)
209215
file_priv->vdev = vdev;
210216
file_priv->priority = DRM_IVPU_CONTEXT_PRIORITY_NORMAL;
211217
kref_init(&file_priv->ref);
218+
mutex_init(&file_priv->lock);
212219

213220
ret = ivpu_mmu_user_context_init(vdev, &file_priv->ctx, ctx_id);
214221
if (ret)
215-
goto err_free_file_priv;
222+
goto err_mutex_destroy;
216223

217224
old = xa_store_irq(&vdev->context_xa, ctx_id, file_priv, GFP_KERNEL);
218225
if (xa_is_err(old)) {
@@ -229,7 +236,8 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file)
229236

230237
err_ctx_fini:
231238
ivpu_mmu_user_context_fini(vdev, &file_priv->ctx);
232-
err_free_file_priv:
239+
err_mutex_destroy:
240+
mutex_destroy(&file_priv->lock);
233241
kfree(file_priv);
234242
err_xa_erase:
235243
xa_erase_irq(&vdev->context_xa, ctx_id);
@@ -252,6 +260,8 @@ static const struct drm_ioctl_desc ivpu_drm_ioctls[] = {
252260
DRM_IOCTL_DEF_DRV(IVPU_SET_PARAM, ivpu_set_param_ioctl, 0),
253261
DRM_IOCTL_DEF_DRV(IVPU_BO_CREATE, ivpu_bo_create_ioctl, 0),
254262
DRM_IOCTL_DEF_DRV(IVPU_BO_INFO, ivpu_bo_info_ioctl, 0),
263+
DRM_IOCTL_DEF_DRV(IVPU_SUBMIT, ivpu_submit_ioctl, 0),
264+
DRM_IOCTL_DEF_DRV(IVPU_BO_WAIT, ivpu_bo_wait_ioctl, 0),
255265
};
256266

257267
static int ivpu_wait_for_ready(struct ivpu_device *vdev)
@@ -458,6 +468,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
458468
vdev->context_xa_limit.max = IVPU_CONTEXT_LIMIT;
459469
atomic64_set(&vdev->unique_id_counter, 0);
460470
xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC);
471+
xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
472+
lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key);
461473

462474
ret = ivpu_pci_init(vdev);
463475
if (ret) {
@@ -509,38 +521,52 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
509521
goto err_fw_fini;
510522
}
511523

524+
ret = ivpu_job_done_thread_init(vdev);
525+
if (ret) {
526+
ivpu_err(vdev, "Failed to initialize job done thread: %d\n", ret);
527+
goto err_ipc_fini;
528+
}
529+
512530
ret = ivpu_fw_load(vdev);
513531
if (ret) {
514532
ivpu_err(vdev, "Failed to load firmware: %d\n", ret);
515-
goto err_fw_fini;
533+
goto err_job_done_thread_fini;
516534
}
517535

518536
ret = ivpu_boot(vdev);
519537
if (ret) {
520538
ivpu_err(vdev, "Failed to boot: %d\n", ret);
521-
goto err_fw_fini;
539+
goto err_job_done_thread_fini;
522540
}
523541

524542
return 0;
525543

544+
err_job_done_thread_fini:
545+
ivpu_job_done_thread_fini(vdev);
546+
err_ipc_fini:
547+
ivpu_ipc_fini(vdev);
526548
err_fw_fini:
527549
ivpu_fw_fini(vdev);
528550
err_mmu_gctx_fini:
529551
ivpu_mmu_global_context_fini(vdev);
530552
err_power_down:
531553
ivpu_hw_power_down(vdev);
532554
err_xa_destroy:
555+
xa_destroy(&vdev->submitted_jobs_xa);
533556
xa_destroy(&vdev->context_xa);
534557
return ret;
535558
}
536559

537560
static void ivpu_dev_fini(struct ivpu_device *vdev)
538561
{
539562
ivpu_shutdown(vdev);
563+
ivpu_job_done_thread_fini(vdev);
540564
ivpu_ipc_fini(vdev);
541565
ivpu_fw_fini(vdev);
542566
ivpu_mmu_global_context_fini(vdev);
543567

568+
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
569+
xa_destroy(&vdev->submitted_jobs_xa);
544570
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->context_xa));
545571
xa_destroy(&vdev->context_xa);
546572
}

drivers/accel/ivpu/ivpu_drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ struct ivpu_device {
9494
struct xarray context_xa;
9595
struct xa_limit context_xa_limit;
9696

97+
struct xarray submitted_jobs_xa;
98+
struct task_struct *job_done_thread;
99+
97100
atomic64_t unique_id_counter;
98101

99102
struct {
@@ -111,6 +114,8 @@ struct ivpu_device {
111114
struct ivpu_file_priv {
112115
struct kref ref;
113116
struct ivpu_device *vdev;
117+
struct mutex lock; /* Protects cmdq */
118+
struct ivpu_cmdq *cmdq[IVPU_NUM_ENGINES];
114119
struct ivpu_mmu_context ctx;
115120
u32 priority;
116121
bool has_mmu_faults;

drivers/accel/ivpu/ivpu_gem.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,32 @@ int ivpu_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file
678678
return ret;
679679
}
680680

681+
int ivpu_bo_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
682+
{
683+
struct drm_ivpu_bo_wait *args = data;
684+
struct drm_gem_object *obj;
685+
unsigned long timeout;
686+
long ret;
687+
688+
timeout = drm_timeout_abs_to_jiffies(args->timeout_ns);
689+
690+
obj = drm_gem_object_lookup(file, args->handle);
691+
if (!obj)
692+
return -EINVAL;
693+
694+
ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ, true, timeout);
695+
if (ret == 0) {
696+
ret = -ETIMEDOUT;
697+
} else if (ret > 0) {
698+
ret = 0;
699+
args->job_status = to_ivpu_bo(obj)->job_status;
700+
}
701+
702+
drm_gem_object_put(obj);
703+
704+
return ret;
705+
}
706+
681707
static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p)
682708
{
683709
unsigned long dma_refcount = 0;

drivers/accel/ivpu/ivpu_gem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct ivpu_bo {
3030
u32 handle;
3131
u32 flags;
3232
uintptr_t user_ptr;
33+
u32 job_status;
3334
};
3435

3536
enum ivpu_bo_type {

0 commit comments

Comments
 (0)