drivers/gpu/drm/xe/xe_devcoredump.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_devcoredump.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_devcoredump.c
Extension
.c
Size
14901 bytes
Lines
518
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 (ss->hwe[i]) {
			xe_hw_engine_snapshot_free(ss->hwe[i]);
			ss->hwe[i] = NULL;
		}

	xe_vm_snapshot_free(ss->vm);
	ss->vm = NULL;
}

#define XE_DEVCOREDUMP_CHUNK_MAX	(SZ_512M + SZ_1G)

/**
 * xe_devcoredump_read() - Read data from the Xe device coredump snapshot
 * @buffer: Destination buffer to copy the coredump data into
 * @offset: Offset in the coredump data to start reading from
 * @count: Number of bytes to read
 * @data: Pointer to the xe_devcoredump structure
 * @datalen: Length of the data (unused)
 *
 * Reads a chunk of the coredump snapshot data into the provided buffer.
 * If the devcoredump is smaller than 1.5 GB (XE_DEVCOREDUMP_CHUNK_MAX),
 * it is read directly from a pre-written buffer. For larger devcoredumps,
 * the pre-written buffer must be periodically repopulated from the snapshot
 * state due to kmalloc size limitations.
 *
 * Return: Number of bytes copied on success, or a negative error code on failure.
 */
static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
				   size_t count, void *data, size_t datalen)
{
	struct xe_devcoredump *coredump = data;
	struct xe_devcoredump_snapshot *ss;
	ssize_t byte_copied = 0;
	u32 chunk_offset;
	ssize_t new_chunk_position;
	bool pm_needed = false;
	int ret = 0;

	if (!coredump)
		return -ENODEV;

	ss = &coredump->snapshot;

	/* Ensure delayed work is captured before continuing */
	flush_work(&ss->work);

	pm_needed = ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX;
	if (pm_needed)
		xe_pm_runtime_get(gt_to_xe(ss->gt));

	mutex_lock(&coredump->lock);

	if (!ss->read.buffer) {
		ret = -ENODEV;
		goto unlock;
	}

	if (offset >= ss->read.size)
		goto unlock;

	new_chunk_position = div_u64_rem(offset,
					 XE_DEVCOREDUMP_CHUNK_MAX,
					 &chunk_offset);

	if (offset >= ss->read.chunk_position + XE_DEVCOREDUMP_CHUNK_MAX ||
	    offset < ss->read.chunk_position) {
		ss->read.chunk_position = new_chunk_position *
			XE_DEVCOREDUMP_CHUNK_MAX;

		__xe_devcoredump_read(ss->read.buffer,
				      XE_DEVCOREDUMP_CHUNK_MAX,
				      ss->read.chunk_position, coredump);
	}

	byte_copied = count < ss->read.size - offset ? count :
		ss->read.size - offset;
	memcpy(buffer, ss->read.buffer + chunk_offset, byte_copied);

unlock:
	mutex_unlock(&coredump->lock);

	if (pm_needed)
		xe_pm_runtime_put(gt_to_xe(ss->gt));

	return byte_copied ? byte_copied : ret;
}

static void xe_devcoredump_free(void *data)
{
	struct xe_devcoredump *coredump = data;

Annotation

Implementation Notes