diff options
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 48 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 45 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 17 | 
8 files changed, 125 insertions, 8 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 648c031942e9..b25b41f50213 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -286,6 +286,8 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,  					     void **kptr, uint64_t *size);  void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_mem *mem); +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_bo *bo); +  int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,  					    struct dma_fence **ef);  int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 8805bd1eed37..f3f9912fc51a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2113,6 +2113,54 @@ int amdgpu_amdkfd_gpuvm_sync_memory(  	return ret;  } +/** + * amdgpu_amdkfd_map_gtt_bo_to_gart - Map BO to GART and increment reference count + * @adev: Device to which allocated BO belongs + * @bo: Buffer object to be mapped + * + * Before return, bo reference count is incremented. To release the reference and unpin/ + * unmap the BO, call amdgpu_amdkfd_free_gtt_mem. + */ +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_bo *bo) +{ +	int ret; + +	ret = amdgpu_bo_reserve(bo, true); +	if (ret) { +		pr_err("Failed to reserve bo. ret %d\n", ret); +		goto err_reserve_bo_failed; +	} + +	ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT); +	if (ret) { +		pr_err("Failed to pin bo. ret %d\n", ret); +		goto err_pin_bo_failed; +	} + +	ret = amdgpu_ttm_alloc_gart(&bo->tbo); +	if (ret) { +		pr_err("Failed to bind bo to GART. ret %d\n", ret); +		goto err_map_bo_gart_failed; +	} + +	amdgpu_amdkfd_remove_eviction_fence( +		bo, bo->kfd_bo->process_info->eviction_fence); + +	amdgpu_bo_unreserve(bo); + +	bo = amdgpu_bo_ref(bo); + +	return 0; + +err_map_bo_gart_failed: +	amdgpu_bo_unpin(bo); +err_pin_bo_failed: +	amdgpu_bo_unreserve(bo); +err_reserve_bo_failed: + +	return ret; +} +  /** amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel() - Map a GTT BO for kernel CPU access   *   * @mem: Buffer object to be mapped for CPU access diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 42f5a61dd2ec..9c11219e925f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -33,6 +33,13 @@  #define AMDGPU_MES_MAX_GFX_PIPES            2  #define AMDGPU_MES_MAX_SDMA_PIPES           2 +#define AMDGPU_MES_API_VERSION_SHIFT	12 +#define AMDGPU_MES_FEAT_VERSION_SHIFT	24 + +#define AMDGPU_MES_VERSION_MASK		0x00000fff +#define AMDGPU_MES_API_VERSION_MASK	0x00fff000 +#define AMDGPU_MES_FEAT_VERSION_MASK	0xff000000 +  enum amdgpu_mes_priority_level {  	AMDGPU_MES_PRIORITY_LEVEL_LOW       = 0,  	AMDGPU_MES_PRIORITY_LEVEL_NORMAL    = 1, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 3bcf9bf29acb..d07588230ed6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -299,6 +299,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,  	struct kfd_process_device *pdd;  	struct queue_properties q_properties;  	uint32_t doorbell_offset_in_process = 0; +	struct amdgpu_bo *wptr_bo = NULL;  	memset(&q_properties, 0, sizeof(struct queue_properties)); @@ -326,12 +327,49 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,  		goto err_bind_process;  	} +	/* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work +	 * on unmapped queues for usermode queue oversubscription (no aggregated doorbell) +	 */ +	if (dev->shared_resources.enable_mes && +			((dev->adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK) +			>> AMDGPU_MES_API_VERSION_SHIFT) >= 2) { +		struct amdgpu_bo_va_mapping *wptr_mapping; +		struct amdgpu_vm *wptr_vm; + +		wptr_vm = drm_priv_to_vm(pdd->drm_priv); +		err = amdgpu_bo_reserve(wptr_vm->root.bo, false); +		if (err) +			goto err_wptr_map_gart; + +		wptr_mapping = amdgpu_vm_bo_lookup_mapping( +				wptr_vm, args->write_pointer_address >> PAGE_SHIFT); +		amdgpu_bo_unreserve(wptr_vm->root.bo); +		if (!wptr_mapping) { +			pr_err("Failed to lookup wptr bo\n"); +			err = -EINVAL; +			goto err_wptr_map_gart; +		} + +		wptr_bo = wptr_mapping->bo_va->base.bo; +		if (wptr_bo->tbo.base.size > PAGE_SIZE) { +			pr_err("Requested GART mapping for wptr bo larger than one page\n"); +			err = -EINVAL; +			goto err_wptr_map_gart; +		} + +		err = amdgpu_amdkfd_map_gtt_bo_to_gart(dev->adev, wptr_bo); +		if (err) { +			pr_err("Failed to map wptr bo to GART\n"); +			goto err_wptr_map_gart; +		} +	} +  	pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n",  			p->pasid,  			dev->id); -	err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, NULL, NULL, -			&doorbell_offset_in_process); +	err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, wptr_bo, +			NULL, NULL, NULL, &doorbell_offset_in_process);  	if (err != 0)  		goto err_create_queue; @@ -363,6 +401,9 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,  	return 0;  err_create_queue: +	if (wptr_bo) +		amdgpu_amdkfd_free_gtt_mem(dev->adev, wptr_bo); +err_wptr_map_gart:  err_bind_process:  err_pdd:  	mutex_unlock(&p->mutex); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 213246a5b4e4..299927a4959b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -177,6 +177,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,  	struct kfd_process_device *pdd = qpd_to_pdd(qpd);  	struct mes_add_queue_input queue_input;  	int r, queue_type; +	uint64_t wptr_addr_off;  	if (dqm->is_hws_hang)  		return -EIO; @@ -196,7 +197,13 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,  					AMDGPU_MES_PRIORITY_LEVEL_NORMAL;  	queue_input.doorbell_offset = q->properties.doorbell_off;  	queue_input.mqd_addr = q->gart_mqd_addr; -	queue_input.wptr_addr = (uint64_t)q->properties.write_ptr; + +	if (q->wptr_bo) { +		wptr_addr_off = (uint64_t)q->properties.write_ptr - (uint64_t)q->wptr_bo->kfd_bo->va; +		queue_input.wptr_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off; +	} else +		queue_input.wptr_addr = (uint64_t)q->properties.write_ptr; +  	queue_input.paging = false;  	queue_input.tba_addr = qpd->tba_addr;  	queue_input.tma_addr = qpd->tma_addr; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c index 4e0387f591be..b8e14c2cc295 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c @@ -377,6 +377,8 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,  	m->sdmax_rlcx_rb_base_hi = upper_32_bits(q->queue_address >> 8);  	m->sdmax_rlcx_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr);  	m->sdmax_rlcx_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr); +	m->sdmax_rlcx_rb_wptr_poll_addr_lo = lower_32_bits((uint64_t)q->write_ptr); +	m->sdmax_rlcx_rb_wptr_poll_addr_hi = upper_32_bits((uint64_t)q->write_ptr);  	m->sdmax_rlcx_doorbell_offset =  		q->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 2585d6e61d42..4c4bbd493caa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -571,6 +571,8 @@ struct queue {  	void *gang_ctx_bo;  	uint64_t gang_ctx_gpu_addr;  	void *gang_ctx_cpu_ptr; + +	struct amdgpu_bo *wptr_bo;  };  enum KFD_MQD_TYPE { @@ -1206,6 +1208,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,  			    struct file *f,  			    struct queue_properties *properties,  			    unsigned int *qid, +			    struct amdgpu_bo *wptr_bo,  			    const struct kfd_criu_queue_priv_data *q_data,  			    const void *restore_mqd,  			    const void *restore_ctl_stack, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 99f2a6412201..a46e2a37b4a6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -180,7 +180,8 @@ void pqm_uninit(struct process_queue_manager *pqm)  static int init_user_queue(struct process_queue_manager *pqm,  				struct kfd_dev *dev, struct queue **q,  				struct queue_properties *q_properties, -				struct file *f, unsigned int qid) +				struct file *f, struct amdgpu_bo *wptr_bo, +				unsigned int qid)  {  	int retval; @@ -210,6 +211,7 @@ static int init_user_queue(struct process_queue_manager *pqm,  			goto cleanup;  		}  		memset((*q)->gang_ctx_cpu_ptr, 0, AMDGPU_MES_GANG_CTX_SIZE); +		(*q)->wptr_bo = wptr_bo;  	}  	pr_debug("PQM After init queue"); @@ -226,6 +228,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,  			    struct file *f,  			    struct queue_properties *properties,  			    unsigned int *qid, +			    struct amdgpu_bo *wptr_bo,  			    const struct kfd_criu_queue_priv_data *q_data,  			    const void *restore_mqd,  			    const void *restore_ctl_stack, @@ -288,7 +291,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,  		 * allocate_sdma_queue() in create_queue() has the  		 * corresponding check logic.  		 */ -		retval = init_user_queue(pqm, dev, &q, properties, f, *qid); +		retval = init_user_queue(pqm, dev, &q, properties, f, wptr_bo, *qid);  		if (retval != 0)  			goto err_create_queue;  		pqn->q = q; @@ -309,7 +312,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,  			goto err_create_queue;  		} -		retval = init_user_queue(pqm, dev, &q, properties, f, *qid); +		retval = init_user_queue(pqm, dev, &q, properties, f, wptr_bo, *qid);  		if (retval != 0)  			goto err_create_queue;  		pqn->q = q; @@ -435,9 +438,13 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)  			pdd->qpd.num_gws = 0;  		} -		if (dev->shared_resources.enable_mes) +		if (dev->shared_resources.enable_mes) {  			amdgpu_amdkfd_free_gtt_mem(dev->adev,  						   pqn->q->gang_ctx_bo); +			if (pqn->q->wptr_bo) +				amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo); + +		}  		kfd_procfs_del_queue(pqn->q);  		uninit_queue(pqn->q);  	} @@ -844,7 +851,7 @@ int kfd_criu_restore_queue(struct kfd_process *p,  	print_queue_properties(&qp); -	ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, mqd, ctl_stack, +	ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, NULL, q_data, mqd, ctl_stack,  				NULL);  	if (ret) {  		pr_err("Failed to create new queue err:%d\n", ret);  | 
