gpu: host1x: Program context stream ID on submission

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>
This commit is contained in:
Mikko Perttunen 2022-06-27 17:19:49 +03:00 committed by Thierry Reding
parent 8aa5bcb616
commit 2486254781
4 changed files with 76 additions and 4 deletions

View 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 */

View 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;

View 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;

View 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,