drivers/gpu/drm/v3d/v3d_submit.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/v3d/v3d_submit.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/v3d/v3d_submit.c
Extension
.c
Size
34288 bytes
Lines
1420
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 (se->in_sync_count && se->wait_stage == queue) {
			struct drm_v3d_sem __user *handle = u64_to_user_ptr(se->in_syncs);

			for (i = 0; i < se->in_sync_count; i++) {
				struct drm_v3d_sem in;

				if (copy_from_user(&in, handle++, sizeof(in))) {
					ret = -EFAULT;
					drm_dbg(&v3d->drm, "Failed to copy wait dep handle.\n");
					goto fail_job_init;
				}
				ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0);

				// TODO: Investigate why this was filtered out for the IOCTL.
				if (ret && ret != -ENOENT)
					goto fail_job_init;
			}
		}
	} else {
		ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0);

		// TODO: Investigate why this was filtered out for the IOCTL.
		if (ret && ret != -ENOENT)
			goto fail_job_init;
	}

	/* CPU jobs don't require hardware resources */
	if (queue != V3D_CPU) {
		ret = v3d_pm_runtime_get(v3d);
		if (ret)
			goto fail_job_init;
		job->has_pm_ref = true;
	}

	kref_init(&job->refcount);

	job->client_stats = v3d_stats_get(v3d_priv->stats[queue]);
	job->global_stats = v3d_stats_get(v3d->queue[queue].stats);

	return 0;

fail_job_init:
	drm_sched_job_cleanup(&job->base);
	return ret;
}

static void
v3d_push_job(struct v3d_job *job)
{
	drm_sched_job_arm(&job->base);

	job->done_fence = dma_fence_get(&job->base.s_fence->finished);

	/* put by scheduler job completion */
	kref_get(&job->refcount);

	drm_sched_entity_push_job(&job->base);
}

static void
v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
					 struct v3d_job *job,
					 struct ww_acquire_ctx *acquire_ctx,
					 u32 out_sync,
					 struct v3d_submit_ext *se,
					 struct dma_fence *done_fence)
{
	struct drm_syncobj *sync_out;
	bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC);
	int i;

	for (i = 0; i < job->bo_count; i++) {
		/* XXX: Use shared fences for read-only objects. */
		dma_resv_add_fence(job->bo[i]->resv, job->done_fence,
				   DMA_RESV_USAGE_WRITE);
	}

	drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx);

	/* Update the return sync object for the job */
	/* If it only supports a single signal semaphore*/
	if (!has_multisync) {
		sync_out = drm_syncobj_find(file_priv, out_sync);
		if (sync_out) {
			drm_syncobj_replace_fence(sync_out, done_fence);
			drm_syncobj_put(sync_out);
		}
		return;
	}

Annotation

Implementation Notes