diff options
| author | Rafael J. Wysocki <[email protected]> | 2015-12-04 14:01:02 +0100 | 
|---|---|---|
| committer | Rafael J. Wysocki <[email protected]> | 2015-12-04 14:01:02 +0100 | 
| commit | c09c9dd2e9c732658c744a802101d5c34fedde22 (patch) | |
| tree | 89f930ede811e66e7a70761aaca079d779fed38a /drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |
| parent | 727ae8be30b428082d3519817f4fb98b712d457d (diff) | |
| parent | 06bf403de344a8a0811ebd24992d2a08022c5225 (diff) | |
Merge branches 'acpi-pci' and 'pm-pci'
* acpi-pci:
  x86/PCI/ACPI: Fix regression caused by commit 4d6b4e69a245
* pm-pci:
  PCI / PM: Tune down retryable runtime suspend error messages
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 223 | 
1 files changed, 100 insertions, 123 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index cb3c274edb0a..1d44d508d4d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -104,10 +104,11 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,  		}  		break;  	case AMDGPU_HW_IP_DMA: -		if (ring < 2) { -			*out_ring = &adev->sdma[ring].ring; +		if (ring < adev->sdma.num_instances) { +			*out_ring = &adev->sdma.instance[ring].ring;  		} else { -			DRM_ERROR("only two SDMA rings are supported\n"); +			DRM_ERROR("only %d SDMA rings are supported\n", +				  adev->sdma.num_instances);  			return -EINVAL;  		}  		break; @@ -126,30 +127,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,  	return 0;  } -struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev, -                                               struct drm_file *filp, -                                               struct amdgpu_ctx *ctx, -                                               struct amdgpu_ib *ibs, -                                               uint32_t num_ibs) -{ -	struct amdgpu_cs_parser *parser; -	int i; - -	parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL); -	if (!parser) -		return NULL; - -	parser->adev = adev; -	parser->filp = filp; -	parser->ctx = ctx; -	parser->ibs = ibs; -	parser->num_ibs = num_ibs; -	for (i = 0; i < num_ibs; i++) -		ibs[i].ctx = ctx; - -	return parser; -} -  int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)  {  	union drm_amdgpu_cs *cs = data; @@ -177,7 +154,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)  	/* get chunks */  	INIT_LIST_HEAD(&p->validated); -	chunk_array_user = (uint64_t __user *)(cs->in.chunks); +	chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);  	if (copy_from_user(chunk_array, chunk_array_user,  			   sizeof(uint64_t)*cs->in.num_chunks)) {  		ret = -EFAULT; @@ -197,7 +174,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)  		struct drm_amdgpu_cs_chunk user_chunk;  		uint32_t __user *cdata; -		chunk_ptr = (void __user *)chunk_array[i]; +		chunk_ptr = (void __user *)(unsigned long)chunk_array[i];  		if (copy_from_user(&user_chunk, chunk_ptr,  				       sizeof(struct drm_amdgpu_cs_chunk))) {  			ret = -EFAULT; @@ -208,7 +185,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)  		p->chunks[i].length_dw = user_chunk.length_dw;  		size = p->chunks[i].length_dw; -		cdata = (void __user *)user_chunk.chunk_data; +		cdata = (void __user *)(unsigned long)user_chunk.chunk_data;  		p->chunks[i].user_ptr = cdata;  		p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t)); @@ -462,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,  	return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;  } -static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff) +/** + * cs_parser_fini() - clean parser states + * @parser:	parser structure holding parsing context. + * @error:	error number + * + * If error is set than unvalidate buffer, otherwise just free memory + * used by parsing context. + **/ +static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)  { +	unsigned i; +  	if (!error) {  		/* Sort the buffer list from the smallest to largest buffer,  		 * which affects the order of buffers in the LRU list. @@ -478,17 +465,14 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err  		list_sort(NULL, &parser->validated, cmp_size_smaller_first);  		ttm_eu_fence_buffer_objects(&parser->ticket, -				&parser->validated, -				&parser->ibs[parser->num_ibs-1].fence->base); +					    &parser->validated, +					    parser->fence);  	} else if (backoff) {  		ttm_eu_backoff_reservation(&parser->ticket,  					   &parser->validated);  	} -} +	fence_put(parser->fence); -static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser) -{ -	unsigned i;  	if (parser->ctx)  		amdgpu_ctx_put(parser->ctx);  	if (parser->bo_list) @@ -498,31 +482,12 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)  	for (i = 0; i < parser->nchunks; i++)  		drm_free_large(parser->chunks[i].kdata);  	kfree(parser->chunks); -	if (!amdgpu_enable_scheduler) -	{ -		if (parser->ibs) -			for (i = 0; i < parser->num_ibs; i++) -				amdgpu_ib_free(parser->adev, &parser->ibs[i]); -		kfree(parser->ibs); -		if (parser->uf.bo) -			drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base); -	} - -	kfree(parser); -} - -/** - * cs_parser_fini() - clean parser states - * @parser:	parser structure holding parsing context. - * @error:	error number - * - * If error is set than unvalidate buffer, otherwise just free memory - * used by parsing context. - **/ -static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) -{ -       amdgpu_cs_parser_fini_early(parser, error, backoff); -       amdgpu_cs_parser_fini_late(parser); +	if (parser->ibs) +		for (i = 0; i < parser->num_ibs; i++) +			amdgpu_ib_free(parser->adev, &parser->ibs[i]); +	kfree(parser->ibs); +	if (parser->uf.bo) +		drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);  }  static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, @@ -567,9 +532,24 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,  			if (r)  				return r;  		} +  	} -	return amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync); +	r = amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync); + +	if (amdgpu_vm_debug && p->bo_list) { +		/* Invalidate all BOs to test for userspace bugs */ +		for (i = 0; i < p->bo_list->num_entries; i++) { +			/* ignore duplicates */ +			bo = p->bo_list->array[i].robj; +			if (!bo) +				continue; + +			amdgpu_vm_bo_invalidate(adev, bo); +		} +	} + +	return r;  }  static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, @@ -593,18 +573,10 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,  		}  	} -	mutex_lock(&vm->mutex);  	r = amdgpu_bo_vm_update_pte(parser, vm); -	if (r) { -		goto out; -	} -	amdgpu_cs_sync_rings(parser); -	if (!amdgpu_enable_scheduler) -		r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs, -				       parser->filp); +	if (!r) +		amdgpu_cs_sync_rings(parser); -out: -	mutex_unlock(&vm->mutex);  	return r;  } @@ -812,40 +784,35 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  {  	struct amdgpu_device *adev = dev->dev_private;  	union drm_amdgpu_cs *cs = data; -	struct amdgpu_cs_parser *parser; +	struct amdgpu_cs_parser parser = {};  	bool reserved_buffers = false;  	int i, r; -	down_read(&adev->exclusive_lock); -	if (!adev->accel_working) { -		up_read(&adev->exclusive_lock); +	if (!adev->accel_working)  		return -EBUSY; -	} -	parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0); -	if (!parser) -		return -ENOMEM; -	r = amdgpu_cs_parser_init(parser, data); +	parser.adev = adev; +	parser.filp = filp; + +	r = amdgpu_cs_parser_init(&parser, data);  	if (r) {  		DRM_ERROR("Failed to initialize parser !\n"); -		kfree(parser); -		up_read(&adev->exclusive_lock); +		amdgpu_cs_parser_fini(&parser, r, false);  		r = amdgpu_cs_handle_lockup(adev, r);  		return r;  	} - -	r = amdgpu_cs_parser_relocs(parser); +	r = amdgpu_cs_parser_relocs(&parser);  	if (r == -ENOMEM)  		DRM_ERROR("Not enough memory for command submission!\n");  	else if (r && r != -ERESTARTSYS)  		DRM_ERROR("Failed to process the buffer list %d!\n", r);  	else if (!r) {  		reserved_buffers = true; -		r = amdgpu_cs_ib_fill(adev, parser); +		r = amdgpu_cs_ib_fill(adev, &parser);  	}  	if (!r) { -		r = amdgpu_cs_dependencies(adev, parser); +		r = amdgpu_cs_dependencies(adev, &parser);  		if (r)  			DRM_ERROR("Failed in the dependencies handling %d!\n", r);  	} @@ -853,61 +820,71 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  	if (r)  		goto out; -	for (i = 0; i < parser->num_ibs; i++) -		trace_amdgpu_cs(parser, i); +	for (i = 0; i < parser.num_ibs; i++) +		trace_amdgpu_cs(&parser, i); -	r = amdgpu_cs_ib_vm_chunk(adev, parser); +	r = amdgpu_cs_ib_vm_chunk(adev, &parser);  	if (r)  		goto out; -	if (amdgpu_enable_scheduler && parser->num_ibs) { +	if (amdgpu_enable_scheduler && parser.num_ibs) { +		struct amdgpu_ring * ring = parser.ibs->ring; +		struct amd_sched_fence *fence;  		struct amdgpu_job *job; -		struct amdgpu_ring * ring =  parser->ibs->ring; +  		job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL); -		if (!job) -			return -ENOMEM; +		if (!job) { +			r = -ENOMEM; +			goto out; +		} +  		job->base.sched = &ring->sched; -		job->base.s_entity = &parser->ctx->rings[ring->idx].entity; -		job->adev = parser->adev; -		job->ibs = parser->ibs; -		job->num_ibs = parser->num_ibs; -		job->base.owner = parser->filp; -		mutex_init(&job->job_lock); +		job->base.s_entity = &parser.ctx->rings[ring->idx].entity; +		job->adev = parser.adev; +		job->owner = parser.filp; +		job->free_job = amdgpu_cs_free_job; + +		job->ibs = parser.ibs; +		job->num_ibs = parser.num_ibs; +		parser.ibs = NULL; +		parser.num_ibs = 0; +  		if (job->ibs[job->num_ibs - 1].user) { -			memcpy(&job->uf,  &parser->uf, -			       sizeof(struct amdgpu_user_fence)); +			job->uf = parser.uf;  			job->ibs[job->num_ibs - 1].user = &job->uf; +			parser.uf.bo = NULL;  		} -		job->free_job = amdgpu_cs_free_job; -		mutex_lock(&job->job_lock); -		r = amd_sched_entity_push_job(&job->base); -		if (r) { -			mutex_unlock(&job->job_lock); +		fence = amd_sched_fence_create(job->base.s_entity, +					       parser.filp); +		if (!fence) { +			r = -ENOMEM;  			amdgpu_cs_free_job(job);  			kfree(job);  			goto out;  		} -		cs->out.handle = -			amdgpu_ctx_add_fence(parser->ctx, ring, -					     &job->base.s_fence->base); -		parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle; +		job->base.s_fence = fence; +		parser.fence = fence_get(&fence->base); -		list_sort(NULL, &parser->validated, cmp_size_smaller_first); -		ttm_eu_fence_buffer_objects(&parser->ticket, -				&parser->validated, -				&job->base.s_fence->base); +		cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring, +						      &fence->base); +		job->ibs[job->num_ibs - 1].sequence = cs->out.handle; -		mutex_unlock(&job->job_lock); -		amdgpu_cs_parser_fini_late(parser); -		up_read(&adev->exclusive_lock); -		return 0; +		trace_amdgpu_cs_ioctl(job); +		amd_sched_entity_push_job(&job->base); + +	} else { +		struct amdgpu_fence *fence; + +		r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs, +				       parser.filp); +		fence = parser.ibs[parser.num_ibs - 1].fence; +		parser.fence = fence_get(&fence->base); +		cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;  	} -	cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;  out: -	amdgpu_cs_parser_fini(parser, r, reserved_buffers); -	up_read(&adev->exclusive_lock); +	amdgpu_cs_parser_fini(&parser, r, reserved_buffers);  	r = amdgpu_cs_handle_lockup(adev, r);  	return r;  } |