diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 74 | 
1 files changed, 52 insertions, 22 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 80d6e132e409..06f0a6534a94 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -434,8 +434,12 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,  			       struct dma_fence *fence)  {  	unsigned long flags; +	ktime_t deadline; -	ktime_t deadline = ktime_add_us(ktime_get(), 10000); +	if (unlikely(ring->adev->debug_disable_soft_recovery)) +		return false; + +	deadline = ktime_add_us(ktime_get(), 10000);  	if (amdgpu_sriov_vf(ring->adev) || !ring->funcs->soft_recovery || !fence)  		return false; @@ -520,46 +524,58 @@ static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf,  {  	struct amdgpu_ring *ring = file_inode(f)->i_private;  	volatile u32 *mqd; -	int r; +	u32 *kbuf; +	int r, i;  	uint32_t value, result;  	if (*pos & 3 || size & 3)  		return -EINVAL; -	result = 0; +	kbuf = kmalloc(ring->mqd_size, GFP_KERNEL); +	if (!kbuf) +		return -ENOMEM;  	r = amdgpu_bo_reserve(ring->mqd_obj, false);  	if (unlikely(r != 0)) -		return r; +		goto err_free;  	r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&mqd); -	if (r) { -		amdgpu_bo_unreserve(ring->mqd_obj); -		return r; -	} +	if (r) +		goto err_unreserve; + +	/* +	 * Copy to local buffer to avoid put_user(), which might fault +	 * and acquire mmap_sem, under reservation_ww_class_mutex. +	 */ +	for (i = 0; i < ring->mqd_size/sizeof(u32); i++) +		kbuf[i] = mqd[i]; +	amdgpu_bo_kunmap(ring->mqd_obj); +	amdgpu_bo_unreserve(ring->mqd_obj); + +	result = 0;  	while (size) {  		if (*pos >= ring->mqd_size) -			goto done; +			break; -		value = mqd[*pos/4]; +		value = kbuf[*pos/4];  		r = put_user(value, (uint32_t *)buf);  		if (r) -			goto done; +			goto err_free;  		buf += 4;  		result += 4;  		size -= 4;  		*pos += 4;  	} -done: -	amdgpu_bo_kunmap(ring->mqd_obj); -	mqd = NULL; -	amdgpu_bo_unreserve(ring->mqd_obj); -	if (r) -		return r; - +	kfree(kbuf);  	return result; + +err_unreserve: +	amdgpu_bo_unreserve(ring->mqd_obj); +err_free: +	kfree(kbuf); +	return r;  }  static const struct file_operations amdgpu_debugfs_mqd_fops = { @@ -631,6 +647,7 @@ int amdgpu_ring_test_helper(struct amdgpu_ring *ring)  			      ring->name);  	ring->sched.ready = !r; +  	return r;  } @@ -638,6 +655,10 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring *ring,  				    struct amdgpu_mqd_prop *prop)  {  	struct amdgpu_device *adev = ring->adev; +	bool is_high_prio_compute = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && +				    amdgpu_gfx_is_high_priority_compute_queue(adev, ring); +	bool is_high_prio_gfx = ring->funcs->type == AMDGPU_RING_TYPE_GFX && +				amdgpu_gfx_is_high_priority_graphics_queue(adev, ring);  	memset(prop, 0, sizeof(*prop)); @@ -655,10 +676,8 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring *ring,  	 */  	prop->hqd_active = ring->funcs->type == AMDGPU_RING_TYPE_KIQ; -	if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && -	     amdgpu_gfx_is_high_priority_compute_queue(adev, ring)) || -	    (ring->funcs->type == AMDGPU_RING_TYPE_GFX && -	     amdgpu_gfx_is_high_priority_graphics_queue(adev, ring))) { +	prop->allow_tunneling = is_high_prio_compute; +	if (is_high_prio_compute || is_high_prio_gfx) {  		prop->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_HIGH;  		prop->hqd_queue_priority = AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM;  	} @@ -711,3 +730,14 @@ void amdgpu_ring_ib_on_emit_de(struct amdgpu_ring *ring)  	if (ring->is_sw_ring)  		amdgpu_sw_ring_ib_mark_offset(ring, AMDGPU_MUX_OFFSET_TYPE_DE);  } + +bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring) +{ +	if (!ring) +		return false; + +	if (ring->no_scheduler || !drm_sched_wqueue_ready(&ring->sched)) +		return false; + +	return true; +} |