]> git.baikalelectronics.ru Git - kernel.git/commitdiff
gpu: host1x: Program context stream ID on submission
authorMikko Perttunen <mperttunen@nvidia.com>
Mon, 27 Jun 2022 14:19:49 +0000 (17:19 +0300)
committerThierry Reding <treding@nvidia.com>
Fri, 8 Jul 2022 14:27:52 +0000 (16:27 +0200)
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>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/host1x/hw/channel_hw.c
drivers/gpu/host1x/hw/host1x06_hardware.h
drivers/gpu/host1x/hw/host1x07_hardware.h
include/linux/host1x.h

index 6b40e9af1e8860b2b57f62347c46da258067d6d2..f84caf06621ab51902039b9e516d8695fea47ca5 100644 (file)
@@ -180,6 +180,45 @@ static void host1x_enable_gather_filter(struct host1x_channel *ch)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+       u32 fence;
+
+       if (!job->memory_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->memory_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;
@@ -236,18 +275,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 */
index 01a142a09800cf9e517446220db9308cb70fd4a1..5d515745eee7ed69dc3bdf19b1ca5c87e1c8cdf9 100644 (file)
@@ -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;
index e6582172ebfdb8c21e5b9bcdd1b5131d0dbf3238..82c0cc9bb0b5f5b30ff413269a77224b70d01b0c 100644 (file)
@@ -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;
index 32a82da13fedc4bb09db0b40c591ac4e2c6ba88a..cb2100d9b0ffe481d661bfcf1a051e0cba7c0507 100644 (file)
@@ -327,6 +327,14 @@ 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 */
+       /* Context device to use for job */
+       struct host1x_memory_context *memory_context;
+       /* Stream ID to use if context isolation is disabled (!memory_context) */
+       u32 engine_fallback_streamid;
+       /* Engine offset to program stream ID to */
+       u32 engine_streamid_offset;
 };
 
 struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,