drivers/gpu/drm/gud/gud_pipe.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/gud/gud_pipe.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/gud/gud_pipe.c
Extension
.c
Size
17794 bytes
Lines
659
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

struct gud_usb_bulk_context {
	struct timer_list timer;
	struct usb_sg_request sgr;
};

static void gud_usb_bulk_timeout(struct timer_list *t)
{
	struct gud_usb_bulk_context *ctx = timer_container_of(ctx, t, timer);

	usb_sg_cancel(&ctx->sgr);
}

static int gud_usb_bulk(struct gud_device *gdrm, size_t len)
{
	struct gud_usb_bulk_context ctx;
	int ret;

	ret = usb_sg_init(&ctx.sgr, gud_to_usb_device(gdrm), gdrm->bulk_pipe, 0,
			  gdrm->bulk_sgt.sgl, gdrm->bulk_sgt.nents, len, GFP_KERNEL);
	if (ret)
		return ret;

	timer_setup_on_stack(&ctx.timer, gud_usb_bulk_timeout, 0);
	mod_timer(&ctx.timer, jiffies + msecs_to_jiffies(3000));

	usb_sg_wait(&ctx.sgr);

	if (!timer_delete_sync(&ctx.timer))
		ret = -ETIMEDOUT;
	else if (ctx.sgr.status < 0)
		ret = ctx.sgr.status;
	else if (ctx.sgr.bytes != len)
		ret = -EIO;

	timer_destroy_on_stack(&ctx.timer);

	return ret;
}

static int gud_flush_rect(struct gud_device *gdrm, struct drm_framebuffer *fb,
			  const struct iosys_map *src, bool cached_reads,
			  const struct drm_format_info *format, struct drm_rect *rect,
			  struct drm_format_conv_state *fmtcnv_state)
{
	struct gud_set_buffer_req req;
	size_t len, trlen;
	int ret;

	drm_dbg(&gdrm->drm, "Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));

	ret = gud_prep_flush(gdrm, fb, src, cached_reads, format, rect, &req, fmtcnv_state);
	if (ret)
		return ret;

	len = le32_to_cpu(req.length);

	if (req.compression)
		trlen = le32_to_cpu(req.compressed_length);
	else
		trlen = len;

	gdrm->stats_length += len;
	/* Did it wrap around? */
	if (gdrm->stats_length <= len && gdrm->stats_actual_length) {
		gdrm->stats_length = len;
		gdrm->stats_actual_length = 0;
	}
	gdrm->stats_actual_length += trlen;

	if (!(gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE) || gdrm->prev_flush_failed) {
		ret = gud_usb_set(gdrm, GUD_REQ_SET_BUFFER, 0, &req, sizeof(req));
		if (ret)
			return ret;
	}

	ret = gud_usb_bulk(gdrm, trlen);
	if (ret)
		gdrm->stats_num_errors++;

	return ret;
}

void gud_clear_damage(struct gud_device *gdrm)
{
	gdrm->damage.x1 = INT_MAX;
	gdrm->damage.y1 = INT_MAX;
	gdrm->damage.x2 = 0;
	gdrm->damage.y2 = 0;
}

Annotation

Implementation Notes