diff options
author | Sarah Walker <sarah.walker@imgtec.com> | 2023-11-22 19:34:38 +0300 |
---|---|---|
committer | Maxime Ripard <mripard@kernel.org> | 2023-11-23 11:01:47 +0300 |
commit | eaf01ee5ba28b97f96a3d3eec4c5fbfb37ee4cde (patch) | |
tree | 1c497dabfd6ee393f053559382b01c2351c50e5f /drivers/gpu/drm/imagination/pvr_drv.c | |
parent | d2d79d29bb98a32c511f7339a8e93b47544fdeac (diff) | |
download | linux-eaf01ee5ba28b97f96a3d3eec4c5fbfb37ee4cde.tar.xz |
drm/imagination: Implement job submission and scheduling
Implement job submission ioctl. Job scheduling is implemented using
drm_sched.
Jobs are submitted in a stream format. This is intended to allow the UAPI
data format to be independent of the actual FWIF structures in use, which
vary depending on the GPU in use.
The stream formats are documented at:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/f8d2b42ae65c2f16f36a43e0ae39d288431e4263/src/imagination/csbgen/rogue_kmd_stream.xml
Changes since v8:
- Updated for upstreamed DRM scheduler changes
- Removed workaround code for the pending_list previously being updated
after run_job() returned
- Fixed null deref in pvr_queue_cleanup_fw_context() for bad stream ptr
given to create_context ioctl
- Corrected license identifiers
Changes since v7:
- Updated for v8 "DRM scheduler changes for XE" patchset
Changes since v6:
- Fix fence handling in pvr_sync_signal_array_add()
- Add handling for SUBMIT_JOB_FRAG_CMD_DISABLE_PIXELMERGE flag
- Fix missing dma_resv locking in job submit path
Changes since v5:
- Fix leak in job creation error path
Changes since v4:
- Use a regular workqueue for job scheduling
Changes since v3:
- Support partial render jobs
- Add job timeout handler
- Split sync handling out of job code
- Use drm_dev_{enter,exit}
Changes since v2:
- Use drm_sched for job scheduling
Co-developed-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Co-developed-by: Donald Robson <donald.robson@imgtec.com>
Signed-off-by: Donald Robson <donald.robson@imgtec.com>
Signed-off-by: Sarah Walker <sarah.walker@imgtec.com>
Link: https://lore.kernel.org/r/c98dab7a5f5fb891fbed7e4990d19b5d13964365.1700668843.git.donald.robson@imgtec.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/imagination/pvr_drv.c')
-rw-r--r-- | drivers/gpu/drm/imagination/pvr_drv.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c index e76363f7dbf7..a6f1d52aaebb 100644 --- a/drivers/gpu/drm/imagination/pvr_drv.c +++ b/drivers/gpu/drm/imagination/pvr_drv.c @@ -7,6 +7,7 @@ #include "pvr_free_list.h" #include "pvr_gem.h" #include "pvr_hwrt.h" +#include "pvr_job.h" #include "pvr_mmu.h" #include "pvr_power.h" #include "pvr_rogue_defs.h" @@ -32,6 +33,8 @@ #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/xarray.h> /** * DOC: PowerVR (Series 6 and later) and IMG Graphics Driver @@ -397,7 +400,8 @@ pvr_dev_query_runtime_info_get(struct pvr_device *pvr_dev, return 0; } - runtime_info.free_list_min_pages = 0; /* FIXME */ + runtime_info.free_list_min_pages = + pvr_get_free_list_min_pages(pvr_dev); runtime_info.free_list_max_pages = ROGUE_PM_MAX_FREELIST_SIZE / ROGUE_PM_PAGE_SIZE; runtime_info.common_store_alloc_region_size = @@ -1137,7 +1141,20 @@ static int pvr_ioctl_submit_jobs(struct drm_device *drm_dev, void *raw_args, struct drm_file *file) { - return -ENOTTY; + struct drm_pvr_ioctl_submit_jobs_args *args = raw_args; + struct pvr_device *pvr_dev = to_pvr_device(drm_dev); + struct pvr_file *pvr_file = to_pvr_file(file); + int idx; + int err; + + if (!drm_dev_enter(drm_dev, &idx)) + return -EIO; + + err = pvr_submit_jobs(pvr_dev, pvr_file, args); + + drm_dev_exit(idx); + + return err; } int @@ -1353,7 +1370,8 @@ pvr_drm_driver_postclose(__always_unused struct drm_device *drm_dev, DEFINE_DRM_GEM_FOPS(pvr_drm_driver_fops); static struct drm_driver pvr_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_GEM_GPUVA | DRIVER_RENDER, + .driver_features = DRIVER_GEM | DRIVER_GEM_GPUVA | DRIVER_RENDER | + DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE, .open = pvr_drm_driver_open, .postclose = pvr_drm_driver_postclose, .ioctls = pvr_drm_driver_ioctls, @@ -1386,8 +1404,15 @@ pvr_probe(struct platform_device *plat_dev) drm_dev = &pvr_dev->base; platform_set_drvdata(plat_dev, drm_dev); + + init_rwsem(&pvr_dev->reset_sem); + pvr_context_device_init(pvr_dev); + err = pvr_queue_device_init(pvr_dev); + if (err) + goto err_context_fini; + devm_pm_runtime_enable(&plat_dev->dev); pm_runtime_mark_last_busy(&plat_dev->dev); @@ -1404,6 +1429,7 @@ pvr_probe(struct platform_device *plat_dev) goto err_device_fini; xa_init_flags(&pvr_dev->free_list_ids, XA_FLAGS_ALLOC1); + xa_init_flags(&pvr_dev->job_ids, XA_FLAGS_ALLOC1); return 0; @@ -1413,6 +1439,11 @@ err_device_fini: err_watchdog_fini: pvr_watchdog_fini(pvr_dev); + pvr_queue_device_fini(pvr_dev); + +err_context_fini: + pvr_context_device_fini(pvr_dev); + return err; } @@ -1422,14 +1453,17 @@ pvr_remove(struct platform_device *plat_dev) struct drm_device *drm_dev = platform_get_drvdata(plat_dev); struct pvr_device *pvr_dev = to_pvr_device(drm_dev); + WARN_ON(!xa_empty(&pvr_dev->job_ids)); WARN_ON(!xa_empty(&pvr_dev->free_list_ids)); + xa_destroy(&pvr_dev->job_ids); xa_destroy(&pvr_dev->free_list_ids); pm_runtime_suspend(drm_dev->dev); pvr_device_fini(pvr_dev); drm_dev_unplug(drm_dev); pvr_watchdog_fini(pvr_dev); + pvr_queue_device_fini(pvr_dev); pvr_context_device_fini(pvr_dev); return 0; |