drivers/gpu/drm/scheduler/tests/mock_scheduler.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/scheduler/tests/mock_scheduler.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/scheduler/tests/mock_scheduler.c
Extension
.c
Size
10197 bytes
Lines
370
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!list_empty(&sched->job_list)) {
			struct drm_mock_sched_job *prev =
				list_last_entry(&sched->job_list, typeof(*prev),
						link);

			prev_finish_at = prev->finish_at;
		}

		if (!prev_finish_at)
			prev_finish_at = ktime_get();

		job->finish_at = ktime_add_us(prev_finish_at, job->duration_us);
	}
	list_add_tail(&job->link, &sched->job_list);
	if (job->finish_at)
		hrtimer_start(&job->timer, job->finish_at, HRTIMER_MODE_ABS);
	spin_unlock_irq(&sched->lock);

	return &job->hw_fence;
}

/*
 * Normally, drivers would take appropriate measures in this callback, such as
 * killing the entity the faulty job is associated with, resetting the hardware
 * and / or resubmitting non-faulty jobs.
 *
 * For the mock scheduler, there are no hardware rings to be resetted nor jobs
 * to be resubmitted. Thus, this function merely ensures that
 *   a) timedout fences get signaled properly and removed from the pending list
 *   b) the mock scheduler framework gets informed about the timeout via a flag
 *   c) The drm_sched_job, not longer needed, gets freed
 */
static enum drm_gpu_sched_stat
mock_sched_timedout_job(struct drm_sched_job *sched_job)
{
	struct drm_mock_scheduler *sched = drm_sched_to_mock_sched(sched_job->sched);
	struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
	unsigned long flags;

	if (job->flags & DRM_MOCK_SCHED_JOB_DONT_RESET) {
		job->flags |= DRM_MOCK_SCHED_JOB_RESET_SKIPPED;
		return DRM_GPU_SCHED_STAT_NO_HANG;
	}

	spin_lock_irqsave(&sched->lock, flags);
	if (!dma_fence_is_signaled_locked(&job->hw_fence)) {
		list_del(&job->link);
		job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
		dma_fence_set_error(&job->hw_fence, -ETIMEDOUT);
		dma_fence_signal_locked(&job->hw_fence);
	}
	spin_unlock_irqrestore(&sched->lock, flags);

	dma_fence_put(&job->hw_fence);
	drm_sched_job_cleanup(sched_job);
	/* Mock job itself is freed by the kunit framework. */

	return DRM_GPU_SCHED_STAT_RESET;
}

static void mock_sched_free_job(struct drm_sched_job *sched_job)
{
	struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);

	dma_fence_put(&job->hw_fence);
	drm_sched_job_cleanup(sched_job);

	/* Mock job itself is freed by the kunit framework. */
}

static void mock_sched_cancel_job(struct drm_sched_job *sched_job)
{
	struct drm_mock_scheduler *sched = drm_sched_to_mock_sched(sched_job->sched);
	struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
	unsigned long flags;

	hrtimer_cancel(&job->timer);

	spin_lock_irqsave(&sched->lock, flags);
	if (!dma_fence_is_signaled_locked(&job->hw_fence)) {
		list_del(&job->link);
		dma_fence_set_error(&job->hw_fence, -ECANCELED);
		dma_fence_signal_locked(&job->hw_fence);
	}
	spin_unlock_irqrestore(&sched->lock, flags);

	/*
	 * The GPU Scheduler will call drm_sched_backend_ops.free_job(), still.
	 * Mock job itself is freed by the kunit framework.
	 */

Annotation

Implementation Notes