Commit 24862547 authored by Mikko Perttunen's avatar Mikko Perttunen Committed by Thierry Reding
Browse files

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: default avatarMikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 8aa5bcb6
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -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 */
+10 −0
Original line number Diff line number Diff line
@@ -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;
+10 −0
Original line number Diff line number Diff line
@@ -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;
+8 −0
Original line number Diff line number Diff line
@@ -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,