drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
Extension
.c
Size
30877 bytes
Lines
1150
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

down_read_trylock(&dev->adev->reset_domain->sem)) {
		amdgpu_mes_flush_shader_debugger(dev->adev,
						 pdd->proc_ctx_gpu_addr,
						 ffs(pdd->dev->xcc_mask) - 1);
		up_read(&dev->adev->reset_domain->sem);
	}
	pdd->already_dequeued = true;
}

int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
			void *gws)
{
	struct mqd_update_info minfo = {0};
	struct kfd_node *dev = NULL;
	struct process_queue_node *pqn;
	struct kfd_process_device *pdd;
	struct kgd_mem *mem = NULL;
	int ret;

	pqn = get_queue_by_qid(pqm, qid);
	if (!pqn) {
		pr_err("Queue id does not match any known queue\n");
		return -EINVAL;
	}

	if (pqn->q)
		dev = pqn->q->device;
	if (WARN_ON(!dev))
		return -ENODEV;

	pdd = kfd_get_process_device_data(dev, pqm->process);
	if (!pdd) {
		pr_err("Process device data doesn't exist\n");
		return -EINVAL;
	}

	/* Only allow one queue per process can have GWS assigned */
	if (gws && pdd->qpd.num_gws)
		return -EBUSY;

	if (!gws && pdd->qpd.num_gws == 0)
		return -EINVAL;

	if ((KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3) &&
	     KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 4) &&
	     KFD_GC_VERSION(dev) != IP_VERSION(9, 5, 0)) &&
	    !dev->kfd->shared_resources.enable_mes) {
		if (gws)
			ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info,
				gws, &mem);
		else
			ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info,
				pqn->q->gws);
		if (unlikely(ret))
			return ret;
		pqn->q->gws = mem;
	} else {
		/*
		 * Intentionally set GWS to a non-NULL value
		 * for devices that do not use GWS for global wave
		 * synchronization but require the formality
		 * of setting GWS for cooperative groups.
		 */
		pqn->q->gws = gws ? ERR_PTR(-ENOMEM) : NULL;
	}

	pdd->qpd.num_gws = gws ? dev->adev->gds.gws_size : 0;
	minfo.update_flag = gws ? UPDATE_FLAG_IS_GWS : 0;

	return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
							pqn->q, &minfo);
}

void kfd_process_dequeue_from_all_devices(struct kfd_process *p)
{
	int i;

	for (i = 0; i < p->n_pdds; i++)
		kfd_process_dequeue_from_device(p->pdds[i]);
}

int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p)
{
	INIT_LIST_HEAD(&pqm->queues);
	pqm->queue_slot_bitmap = bitmap_zalloc(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS,
					       GFP_KERNEL);
	if (!pqm->queue_slot_bitmap)
		return -ENOMEM;
	pqm->process = p;

Annotation

Implementation Notes