[PATCH v2 3/8] gpu: host1x: Program context stream ID on submission
From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2021-09-16 14:33:36
Also in:
dri-devel, linux-devicetree, linux-iommu, linux-tegra, lkml
Subsystem:
drm drivers, drm drivers for nvidia tegra, the rest · Maintainers:
David Airlie, Simona Vetter, Thierry Reding, Mikko Perttunen, Linus Torvalds
Add code to do stream ID switching at the beginning of a job. The stream ID is switched to the stream ID specified by the context passed in the job structure. Before switching the stream ID, an OP_DONE wait is done on the channel's engine to ensure that there is no residual ongoing work that might do DMA using the new stream ID. Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com> --- drivers/gpu/host1x/hw/channel_hw.c | 52 +++++++++++++++++++++-- drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +++++ drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +++++ include/linux/host1x.h | 4 ++ 4 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index 1999780a7203..d451f8437f62 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c@@ -159,6 +159,45 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel) #endif } +static void host1x_channel_program_engine_streamid(struct host1x_job *job) +{ +#if HOST1X_HW >= 6 + u32 fence; + + if (!job->context) + return; + + fence = host1x_syncpt_incr_max(job->syncpt, 1); + + /* First, increment a syncpoint on OP_DONE condition.. */ + + host1x_cdma_push(&job->channel->cdma, + host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1), + HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) | + HOST1X_UCLASS_INCR_SYNCPT_COND_F(1)); + + /* Wait for syncpoint to increment */ + + host1x_cdma_push(&job->channel->cdma, + host1x_opcode_setclass(HOST1X_CLASS_HOST1X, + host1x_uclass_wait_syncpt_r(), 1), + host1x_class_host_wait_syncpt(job->syncpt->id, fence)); + + /* + * Now that we know the engine is idle, return to class and + * change stream ID. + */ + + host1x_cdma_push(&job->channel->cdma, + host1x_opcode_setclass(job->class, 0, 0), + HOST1X_OPCODE_NOP); + + host1x_cdma_push(&job->channel->cdma, + host1x_opcode_setpayload(job->context->stream_id), + host1x_opcode_setstreamid(job->engine_streamid_offset / 4)); +#endif +} + static int channel_submit(struct host1x_job *job) { struct host1x_channel *ch = job->channel;
@@ -214,18 +253,23 @@ static int channel_submit(struct host1x_job *job) if (sp->base) synchronize_syncpt_base(job); - syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs); - host1x_hw_syncpt_assign_to_channel(host, sp, ch); - job->syncpt_end = syncval; - /* add a setclass for modules that require it */ if (job->class) host1x_cdma_push(&ch->cdma, host1x_opcode_setclass(job->class, 0, 0), HOST1X_OPCODE_NOP); + /* + * Ensure engine DMA is idle and set new stream ID. May increment + * syncpt max. + */ + host1x_channel_program_engine_streamid(job); + + syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs); + job->syncpt_end = syncval; + submit_gathers(job, syncval - user_syncpt_incrs); /* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count) return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count; } +static inline u32 host1x_opcode_setstreamid(unsigned streamid) +{ + return (7 << 28) | streamid; +} + +static inline u32 host1x_opcode_setpayload(unsigned payload) +{ + return (9 << 28) | payload; +} + static inline u32 host1x_opcode_gather_wide(unsigned count) { return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count) return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count; } +static inline u32 host1x_opcode_setstreamid(unsigned streamid) +{ + return (7 << 28) | streamid; +} + +static inline u32 host1x_opcode_setpayload(unsigned payload) +{ + return (9 << 28) | payload; +} + static inline u32 host1x_opcode_gather_wide(unsigned count) { return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index f3073738564a..eb0ca304ca92 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h@@ -277,6 +277,10 @@ struct host1x_job { /* Whether host1x-side firewall should be ran for this job or not */ bool enable_firewall; + + /* Options for configuring engine data stream ID */ + struct host1x_context *context; + u32 engine_streamid_offset; }; struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
--
2.32.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel