diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_cs.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 53 | 
1 files changed, 30 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index e7b0b5d51bc..c66beb1662b 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -118,6 +118,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority  static int radeon_cs_sync_rings(struct radeon_cs_parser *p)  {  	bool sync_to_ring[RADEON_NUM_RINGS] = { }; +	bool need_sync = false;  	int i, r;  	for (i = 0; i < p->nrelocs; i++) { @@ -126,36 +127,24 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p)  		if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) {  			struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj; -			if (!radeon_fence_signaled(fence)) { +			if (fence->ring != p->ring && !radeon_fence_signaled(fence)) {  				sync_to_ring[fence->ring] = true; +				need_sync = true;  			}  		}  	} -	for (i = 0; i < RADEON_NUM_RINGS; ++i) { -		/* no need to sync to our own or unused rings */ -		if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready) -			continue; - -		if (!p->ib->fence->semaphore) { -			r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore); -			if (r) -				return r; -		} - -		r = radeon_ring_lock(p->rdev, &p->rdev->ring[i], 3); -		if (r) -			return r; -		radeon_semaphore_emit_signal(p->rdev, i, p->ib->fence->semaphore); -		radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[i]); +	if (!need_sync) { +		return 0; +	} -		r = radeon_ring_lock(p->rdev, &p->rdev->ring[p->ring], 3); -		if (r) -			return r; -		radeon_semaphore_emit_wait(p->rdev, p->ring, p->ib->fence->semaphore); -		radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[p->ring]); +	r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore); +	if (r) { +		return r;  	} -	return 0; + +	return radeon_semaphore_sync_rings(p->rdev, p->ib->fence->semaphore, +					   sync_to_ring, p->ring);  }  int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) @@ -172,6 +161,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  	/* get chunks */  	INIT_LIST_HEAD(&p->validated);  	p->idx = 0; +	p->ib = NULL; +	p->const_ib = NULL;  	p->chunk_ib_idx = -1;  	p->chunk_relocs_idx = -1;  	p->chunk_flags_idx = -1; @@ -336,6 +327,9 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)  	kfree(parser->chunks);  	kfree(parser->chunks_array);  	radeon_ib_free(parser->rdev, &parser->ib); +	if (parser->const_ib) { +		radeon_ib_free(parser->rdev, &parser->const_ib); +	}  }  static int radeon_cs_ib_chunk(struct radeon_device *rdev, @@ -507,6 +501,16 @@ out:  	return r;  } +static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r) +{ +	if (r == -EDEADLK) { +		r = radeon_gpu_reset(rdev); +		if (!r) +			r = -EAGAIN; +	} +	return r; +} +  int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  {  	struct radeon_device *rdev = dev->dev_private; @@ -528,6 +532,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  	if (r) {  		DRM_ERROR("Failed to initialize parser !\n");  		radeon_cs_parser_fini(&parser, r); +		r = radeon_cs_handle_lockup(rdev, r);  		radeon_mutex_unlock(&rdev->cs_mutex);  		return r;  	} @@ -536,6 +541,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  		if (r != -ERESTARTSYS)  			DRM_ERROR("Failed to parse relocation %d!\n", r);  		radeon_cs_parser_fini(&parser, r); +		r = radeon_cs_handle_lockup(rdev, r);  		radeon_mutex_unlock(&rdev->cs_mutex);  		return r;  	} @@ -549,6 +555,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  	}  out:  	radeon_cs_parser_fini(&parser, r); +	r = radeon_cs_handle_lockup(rdev, r);  	radeon_mutex_unlock(&rdev->cs_mutex);  	return r;  }  |