summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imagination/pvr_device.c
diff options
context:
space:
mode:
authorSarah Walker <sarah.walker@imgtec.com>2023-11-22 19:34:38 +0300
committerMaxime Ripard <mripard@kernel.org>2023-11-23 11:01:47 +0300
commiteaf01ee5ba28b97f96a3d3eec4c5fbfb37ee4cde (patch)
tree1c497dabfd6ee393f053559382b01c2351c50e5f /drivers/gpu/drm/imagination/pvr_device.c
parentd2d79d29bb98a32c511f7339a8e93b47544fdeac (diff)
downloadlinux-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_device.c')
-rw-r--r--drivers/gpu/drm/imagination/pvr_device.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index 2d6db4715f85..199f812d1ee7 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -6,7 +6,9 @@
#include "pvr_fw.h"
#include "pvr_power.h"
+#include "pvr_queue.h"
#include "pvr_rogue_cr_defs.h"
+#include "pvr_stream.h"
#include "pvr_vm.h"
#include <drm/drm_print.h>
@@ -117,6 +119,32 @@ static int pvr_device_clk_init(struct pvr_device *pvr_dev)
return 0;
}
+/**
+ * pvr_device_process_active_queues() - Process all queue related events.
+ * @pvr_dev: PowerVR device to check
+ *
+ * This is called any time we receive a FW event. It iterates over all
+ * active queues and calls pvr_queue_process() on them.
+ */
+void pvr_device_process_active_queues(struct pvr_device *pvr_dev)
+{
+ struct pvr_queue *queue, *tmp_queue;
+ LIST_HEAD(active_queues);
+
+ mutex_lock(&pvr_dev->queues.lock);
+
+ /* Move all active queues to a temporary list. Queues that remain
+ * active after we're done processing them are re-inserted to
+ * the queues.active list by pvr_queue_process().
+ */
+ list_splice_init(&pvr_dev->queues.active, &active_queues);
+
+ list_for_each_entry_safe(queue, tmp_queue, &active_queues, node)
+ pvr_queue_process(queue);
+
+ mutex_unlock(&pvr_dev->queues.lock);
+}
+
static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
{
struct pvr_device *pvr_dev = data;
@@ -132,6 +160,7 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
if (pvr_dev->fw_dev.booted) {
pvr_fwccb_process(pvr_dev);
pvr_kccb_wake_up_waiters(pvr_dev);
+ pvr_device_process_active_queues(pvr_dev);
}
pm_runtime_mark_last_busy(from_pvr_device(pvr_dev)->dev);
@@ -398,6 +427,8 @@ pvr_device_gpu_init(struct pvr_device *pvr_dev)
else
return -EINVAL;
+ pvr_stream_create_musthave_masks(pvr_dev);
+
err = pvr_set_dma_info(pvr_dev);
if (err)
return err;