drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
Extension
.c
Size
36888 bytes
Lines
1410
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 (r) {
				gpu_reset = true;
				break;
			}
		}
	}

	if (gpu_reset) {
		struct amdgpu_reset_context reset_context;

		memset(&reset_context, 0, sizeof(reset_context));

		reset_context.method = AMD_RESET_METHOD_NONE;
		reset_context.reset_req_dev = adev;
		reset_context.src = AMDGPU_RESET_SRC_USERQ;
		set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
		/*set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);*/

		amdgpu_device_gpu_recover(adev, NULL, &reset_context);
	}
}

static void amdgpu_userq_hang_detect_work(struct work_struct *work)
{
	struct amdgpu_usermode_queue *queue =
		container_of(work, struct amdgpu_usermode_queue,
			     hang_detect_work.work);

	/*
	 * Don't schedule the work here! Scheduling or queue work from one reset
	 * handler to another is illegal if you don't take extra precautions!
	 */
	amdgpu_userq_mgr_reset_work(&queue->userq_mgr->reset_work);
}

/*
 * Start hang detection for a user queue fence. A delayed work will be scheduled
 * to reset the queues when the fence doesn't signal in time.
 */
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
{
	struct amdgpu_device *adev;
	unsigned long timeout_ms;

	adev = queue->userq_mgr->adev;
	/* Determine timeout based on queue type */
	switch (queue->queue_type) {
	case AMDGPU_RING_TYPE_GFX:
		timeout_ms = adev->gfx_timeout;
		break;
	case AMDGPU_RING_TYPE_COMPUTE:
		timeout_ms = adev->compute_timeout;
		break;
	case AMDGPU_RING_TYPE_SDMA:
		timeout_ms = adev->sdma_timeout;
		break;
	default:
		timeout_ms = adev->gfx_timeout;
		break;
	}

	queue_delayed_work(adev->reset_domain->wq, &queue->hang_detect_work,
			   msecs_to_jiffies(timeout_ms));
}

void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
{
	struct xarray *xa = &adev->userq_doorbell_xa;
	struct amdgpu_usermode_queue *queue;
	unsigned long flags;
	int r;

	xa_lock_irqsave(xa, flags);
	queue = xa_load(xa, doorbell);
	if (queue) {
		r = amdgpu_userq_fence_driver_process(queue->fence_drv);
		/*
		 * We are in interrupt context here, this *can't* wait for
		 * reset work to finish.
		 */
		if (r >= 0)
			cancel_delayed_work(&queue->hang_detect_work);

		/* Restart the timer when there are still fences pending */
		if (r == 1)
			amdgpu_userq_start_hang_detect_work(queue);
	}
	xa_unlock_irqrestore(xa, flags);
}

Annotation

Implementation Notes