diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 134 | 
1 files changed, 108 insertions, 26 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 7fe8fd884f06..69b66b9e7f57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -157,7 +157,8 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)  	r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,  			     AMDGPU_GEM_DOMAIN_VRAM, -			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, +			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | +			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,  			     NULL, NULL, &adev->vce.vcpu_bo);  	if (r) {  		dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r); @@ -395,12 +396,12 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)   * Open up a stream for HW test   */  int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, -			      struct fence **fence) +			      struct dma_fence **fence)  {  	const unsigned ib_size_dw = 1024;  	struct amdgpu_job *job;  	struct amdgpu_ib *ib; -	struct fence *f = NULL; +	struct dma_fence *f = NULL;  	uint64_t dummy;  	int i, r; @@ -450,14 +451,14 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,  		ib->ptr[i] = 0x0;  	r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); -	job->fence = fence_get(f); +	job->fence = dma_fence_get(f);  	if (r)  		goto err;  	amdgpu_job_free(job);  	if (fence) -		*fence = fence_get(f); -	fence_put(f); +		*fence = dma_fence_get(f); +	dma_fence_put(f);  	return 0;  err: @@ -476,12 +477,12 @@ err:   * Close up a stream for HW test or if userspace failed to do so   */  int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, -			       bool direct, struct fence **fence) +			       bool direct, struct dma_fence **fence)  {  	const unsigned ib_size_dw = 1024;  	struct amdgpu_job *job;  	struct amdgpu_ib *ib; -	struct fence *f = NULL; +	struct dma_fence *f = NULL;  	int i, r;  	r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -513,7 +514,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,  	if (direct) {  		r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); -		job->fence = fence_get(f); +		job->fence = dma_fence_get(f);  		if (r)  			goto err; @@ -526,8 +527,8 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,  	}  	if (fence) -		*fence = fence_get(f); -	fence_put(f); +		*fence = dma_fence_get(f); +	dma_fence_put(f);  	return 0;  err: @@ -641,6 +642,9 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)  	uint32_t *size = &tmp;  	int i, r, idx = 0; +	p->job->vm = NULL; +	ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); +  	r = amdgpu_cs_sysvm_access_required(p);  	if (r)  		return r; @@ -788,6 +792,96 @@ out:  }  /** + * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode + * + * @p: parser context + * + */ +int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx) +{ +	struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; +	int session_idx = -1; +	uint32_t destroyed = 0; +	uint32_t created = 0; +	uint32_t allocated = 0; +	uint32_t tmp, handle = 0; +	int i, r = 0, idx = 0; + +	while (idx < ib->length_dw) { +		uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); +		uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); + +		if ((len < 8) || (len & 3)) { +			DRM_ERROR("invalid VCE command length (%d)!\n", len); +			r = -EINVAL; +			goto out; +		} + +		switch (cmd) { +		case 0x00000001: /* session */ +			handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); +			session_idx = amdgpu_vce_validate_handle(p, handle, +								 &allocated); +			if (session_idx < 0) { +				r = session_idx; +				goto out; +			} +			break; + +		case 0x01000001: /* create */ +			created |= 1 << session_idx; +			if (destroyed & (1 << session_idx)) { +				destroyed &= ~(1 << session_idx); +				allocated |= 1 << session_idx; + +			} else if (!(allocated & (1 << session_idx))) { +				DRM_ERROR("Handle already in use!\n"); +				r = -EINVAL; +				goto out; +			} + +			break; + +		case 0x02000001: /* destroy */ +			destroyed |= 1 << session_idx; +			break; + +		default: +			break; +		} + +		if (session_idx == -1) { +			DRM_ERROR("no session command at start of IB\n"); +			r = -EINVAL; +			goto out; +		} + +		idx += len / 4; +	} + +	if (allocated & ~created) { +		DRM_ERROR("New session without create command!\n"); +		r = -ENOENT; +	} + +out: +	if (!r) { +		/* No error, free all destroyed handle slots */ +		tmp = destroyed; +		amdgpu_ib_free(p->adev, ib, NULL); +	} else { +		/* Error during parsing, free all allocated handle slots */ +		tmp = allocated; +	} + +	for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) +		if (tmp & (1 << i)) +			atomic_set(&p->adev->vce.handles[i], 0); + +	return r; +} + +/**   * amdgpu_vce_ring_emit_ib - execute indirect buffer   *   * @ring: engine to use @@ -823,18 +917,6 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,  	amdgpu_ring_write(ring, VCE_CMD_END);  } -unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring) -{ -	return -		4; /* amdgpu_vce_ring_emit_ib */ -} - -unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring) -{ -	return -		6; /* amdgpu_vce_ring_emit_fence  x1 no user fence */ -} -  /**   * amdgpu_vce_ring_test_ring - test if VCE ring is working   * @@ -883,7 +965,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)   */  int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)  { -	struct fence *fence = NULL; +	struct dma_fence *fence = NULL;  	long r;  	/* skip vce ring1/2 ib test for now, since it's not reliable */ @@ -902,7 +984,7 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)  		goto error;  	} -	r = fence_wait_timeout(fence, false, timeout); +	r = dma_fence_wait_timeout(fence, false, timeout);  	if (r == 0) {  		DRM_ERROR("amdgpu: IB test timed out.\n");  		r = -ETIMEDOUT; @@ -913,6 +995,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)  		r = 0;  	}  error: -	fence_put(fence); +	dma_fence_put(fence);  	return r;  }  | 
