Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7f6786e authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Add user command profiling with hw scheduling



User mode specifies a profiling buffer as part of the ib list.
This ib is passed on to the GMU as part of the HFI packet to issue
commands. The GMU will in turn create a special user profiling IB
to have the GPU write the command start and retire ticks into the
user specified buffer. The submit to HFI time is recorded in the
user specified buffer by kgsl.

Change-Id: I800b4a23876f6f0707fb7a942e97d70a2d712aeb
Signed-off-by: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent d8dec295
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -3201,6 +3201,45 @@ void adreno_cx_misc_regrmw(struct adreno_device *adreno_dev,
	adreno_cx_misc_regwrite(adreno_dev, offsetwords, val | bits);
}

void adreno_profile_submit_time(struct adreno_submit_time *time)
{
	struct kgsl_drawobj *drawobj;
	struct kgsl_drawobj_cmd *cmdobj;
	struct kgsl_mem_entry *entry;
	struct kgsl_drawobj_profiling_buffer *profile_buffer;

	drawobj = time->drawobj;
	if (drawobj == NULL)
		return;

	cmdobj = CMDOBJ(drawobj);
	entry = cmdobj->profiling_buf_entry;
	if (!entry)
		return;

	profile_buffer = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
			cmdobj->profiling_buffer_gpuaddr);

	if (profile_buffer == NULL)
		return;

	/* Return kernel clock time to the client if requested */
	if (drawobj->flags & KGSL_DRAWOBJ_PROFILING_KTIME) {
		u64 secs = time->ktime;

		profile_buffer->wall_clock_ns =
			do_div(secs, NSEC_PER_SEC);
		profile_buffer->wall_clock_s = secs;
	} else {
		profile_buffer->wall_clock_s = time->utime.tv_sec;
		profile_buffer->wall_clock_ns = time->utime.tv_nsec;
	}

	profile_buffer->gpu_ticks_queued = time->ticks;

	kgsl_memdesc_unmap(&entry->memdesc);
}

/**
 * adreno_waittimestamp - sleep while waiting for the specified timestamp
 * @device - pointer to a KGSL device structure
+10 −0
Original line number Diff line number Diff line
@@ -1925,4 +1925,14 @@ void gmu_fault_snapshot(struct kgsl_device *device);
 * Return: 0 on success or negative error on failure
 */
int adreno_suspend_context(struct kgsl_device *device);

/*
 * adreno_profile_submit_time - Populate profiling buffer with timestamps
 * @time: Container for the statistics
 *
 * Populate the draw object user profiling buffer with the timestamps
 * recored in the adreno_submit_time structure at the time of draw object
 * submission.
 */
void adreno_profile_submit_time(struct adreno_submit_time *time);
#endif /*__ADRENO_H */
+2 −0
Original line number Diff line number Diff line
@@ -529,6 +529,8 @@ struct hfi_submit_cmd {
	u32 ctxt_id;
	u32 flags;
	u32 ts;
	u32 profile_gpuaddr_lo;
	u32 profile_gpuaddr_hi;
	u32 numibs;
} __packed;

+26 −7
Original line number Diff line number Diff line
@@ -1084,7 +1084,23 @@ int a6xx_hwsched_submit_cmdobj(struct adreno_device *adreno_dev,
	cmd->ts = drawobj->timestamp;
	cmd->numibs = numibs;

	if (numibs) {
	if (!numibs)
		goto skipib;

	if ((drawobj->flags & KGSL_DRAWOBJ_PROFILING) &&
		!cmdobj->profiling_buf_entry) {

		time.drawobj = drawobj;

		cmd->profile_gpuaddr_lo =
			lower_32_bits(cmdobj->profiling_buffer_gpuaddr);
		cmd->profile_gpuaddr_hi =
			upper_32_bits(cmdobj->profiling_buffer_gpuaddr);

		/* Indicate to GMU to do user profiling for this submission */
		cmd->flags |= BIT(4);
	}

	issue_ib = (struct hfi_issue_ib *)&cmd[1];

	list_for_each_entry(ib, &cmdobj->cmdlist, node) {
@@ -1092,8 +1108,8 @@ int a6xx_hwsched_submit_cmdobj(struct adreno_device *adreno_dev,
		issue_ib->size = ib->size;
		issue_ib++;
	}
	}

skipib:
	ret = a6xx_hfi_queue_write(adreno_dev,
		HFI_DSP_ID_0 + drawobj->context->gmu_dispatch_queue,
		(u32 *)cmd);
@@ -1114,6 +1130,9 @@ int a6xx_hwsched_submit_cmdobj(struct adreno_device *adreno_dev,
	gmu_core_regwrite(KGSL_DEVICE(adreno_dev), A6XX_GMU_HOST2GMU_INTR_SET,
		DISPQ_IRQ_BIT(drawobj->context->gmu_dispatch_queue));

	/* Put the profiling information in the user profiling buffer */
	adreno_profile_submit_time(&time);

free:
	kvfree(cmd);

+0 −44
Original line number Diff line number Diff line
@@ -115,50 +115,6 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev,
	}
}

static void adreno_profile_submit_time(struct adreno_submit_time *time)
{
	struct kgsl_drawobj *drawobj;
	struct kgsl_drawobj_cmd *cmdobj;
	struct kgsl_mem_entry *entry;

	if (time == NULL)
		return;

	drawobj = time->drawobj;

	if (drawobj == NULL)
		return;

	cmdobj = CMDOBJ(drawobj);
	entry = cmdobj->profiling_buf_entry;

	if (entry) {
		struct kgsl_drawobj_profiling_buffer *profile_buffer;

		profile_buffer = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
					cmdobj->profiling_buffer_gpuaddr);

		if (profile_buffer == NULL)
			return;

		/* Return kernel clock time to the the client if requested */
		if (drawobj->flags & KGSL_DRAWOBJ_PROFILING_KTIME) {
			uint64_t secs = time->ktime;

			profile_buffer->wall_clock_ns =
				do_div(secs, NSEC_PER_SEC);
			profile_buffer->wall_clock_s = secs;
		} else {
			profile_buffer->wall_clock_s = time->utime.tv_sec;
			profile_buffer->wall_clock_ns = time->utime.tv_nsec;
		}

		profile_buffer->gpu_ticks_queued = time->ticks;

		kgsl_memdesc_unmap(&entry->memdesc);
	}
}

void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb,
		struct adreno_submit_time *time)
{