diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 187 | 
1 files changed, 113 insertions, 74 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index d3ca73090e39..74f2038ac747 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -48,6 +48,7 @@  #endif  #define FIRMWARE_TONGA		"amdgpu/tonga_vce.bin"  #define FIRMWARE_CARRIZO	"amdgpu/carrizo_vce.bin" +#define FIRMWARE_FIJI		"amdgpu/fiji_vce.bin"  #ifdef CONFIG_DRM_AMDGPU_CIK  MODULE_FIRMWARE(FIRMWARE_BONAIRE); @@ -58,6 +59,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);  #endif  MODULE_FIRMWARE(FIRMWARE_TONGA);  MODULE_FIRMWARE(FIRMWARE_CARRIZO); +MODULE_FIRMWARE(FIRMWARE_FIJI);  static void amdgpu_vce_idle_work_handler(struct work_struct *work); @@ -101,6 +103,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)  	case CHIP_CARRIZO:  		fw_name = FIRMWARE_CARRIZO;  		break; +	case CHIP_FIJI: +		fw_name = FIRMWARE_FIJI; +		break;  	default:  		return -EINVAL; @@ -136,7 +141,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)  	/* allocate firmware, stack and heap BO */  	r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, -			     AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->vce.vcpu_bo); +			     AMDGPU_GEM_DOMAIN_VRAM, +			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, +			     NULL, NULL, &adev->vce.vcpu_bo);  	if (r) {  		dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);  		return r; @@ -334,6 +341,14 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)  	}  } +static int amdgpu_vce_free_job( +	struct amdgpu_job *job) +{ +	amdgpu_ib_free(job->adev, job->ibs); +	kfree(job->ibs); +	return 0; +} +  /**   * amdgpu_vce_get_create_msg - generate a VCE create msg   * @@ -345,59 +360,69 @@ 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 amdgpu_fence **fence) +			      struct fence **fence)  {  	const unsigned ib_size_dw = 1024; -	struct amdgpu_ib ib; +	struct amdgpu_ib *ib = NULL; +	struct fence *f = NULL; +	struct amdgpu_device *adev = ring->adev;  	uint64_t dummy;  	int i, r; -	r = amdgpu_ib_get(ring, NULL, ib_size_dw * 4, &ib); +	ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL); +	if (!ib) +		return -ENOMEM; +	r = amdgpu_ib_get(ring, NULL, ib_size_dw * 4, ib);  	if (r) {  		DRM_ERROR("amdgpu: failed to get ib (%d).\n", r); +		kfree(ib);  		return r;  	} -	dummy = ib.gpu_addr + 1024; +	dummy = ib->gpu_addr + 1024;  	/* stitch together an VCE create msg */ -	ib.length_dw = 0; -	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ -	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ -	ib.ptr[ib.length_dw++] = handle; - -	ib.ptr[ib.length_dw++] = 0x00000030; /* len */ -	ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */ -	ib.ptr[ib.length_dw++] = 0x00000000; -	ib.ptr[ib.length_dw++] = 0x00000042; -	ib.ptr[ib.length_dw++] = 0x0000000a; -	ib.ptr[ib.length_dw++] = 0x00000001; -	ib.ptr[ib.length_dw++] = 0x00000080; -	ib.ptr[ib.length_dw++] = 0x00000060; -	ib.ptr[ib.length_dw++] = 0x00000100; -	ib.ptr[ib.length_dw++] = 0x00000100; -	ib.ptr[ib.length_dw++] = 0x0000000c; -	ib.ptr[ib.length_dw++] = 0x00000000; - -	ib.ptr[ib.length_dw++] = 0x00000014; /* len */ -	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ -	ib.ptr[ib.length_dw++] = upper_32_bits(dummy); -	ib.ptr[ib.length_dw++] = dummy; -	ib.ptr[ib.length_dw++] = 0x00000001; - -	for (i = ib.length_dw; i < ib_size_dw; ++i) -		ib.ptr[i] = 0x0; - -	r = amdgpu_ib_schedule(ring->adev, 1, &ib, AMDGPU_FENCE_OWNER_UNDEFINED); -	if (r) { -		DRM_ERROR("amdgpu: failed to schedule ib (%d).\n", r); -	} - +	ib->length_dw = 0; +	ib->ptr[ib->length_dw++] = 0x0000000c; /* len */ +	ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ +	ib->ptr[ib->length_dw++] = handle; + +	ib->ptr[ib->length_dw++] = 0x00000030; /* len */ +	ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */ +	ib->ptr[ib->length_dw++] = 0x00000000; +	ib->ptr[ib->length_dw++] = 0x00000042; +	ib->ptr[ib->length_dw++] = 0x0000000a; +	ib->ptr[ib->length_dw++] = 0x00000001; +	ib->ptr[ib->length_dw++] = 0x00000080; +	ib->ptr[ib->length_dw++] = 0x00000060; +	ib->ptr[ib->length_dw++] = 0x00000100; +	ib->ptr[ib->length_dw++] = 0x00000100; +	ib->ptr[ib->length_dw++] = 0x0000000c; +	ib->ptr[ib->length_dw++] = 0x00000000; + +	ib->ptr[ib->length_dw++] = 0x00000014; /* len */ +	ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ +	ib->ptr[ib->length_dw++] = upper_32_bits(dummy); +	ib->ptr[ib->length_dw++] = dummy; +	ib->ptr[ib->length_dw++] = 0x00000001; + +	for (i = ib->length_dw; i < ib_size_dw; ++i) +		ib->ptr[i] = 0x0; + +	r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, +						 &amdgpu_vce_free_job, +						 AMDGPU_FENCE_OWNER_UNDEFINED, +						 &f); +	if (r) +		goto err;  	if (fence) -		*fence = amdgpu_fence_ref(ib.fence); - -	amdgpu_ib_free(ring->adev, &ib); - +		*fence = fence_get(f); +	fence_put(f); +	if (amdgpu_enable_scheduler) +		return 0; +err: +	amdgpu_ib_free(adev, ib); +	kfree(ib);  	return r;  } @@ -412,49 +437,59 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,   * 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, -			       struct amdgpu_fence **fence) +			       struct fence **fence)  {  	const unsigned ib_size_dw = 1024; -	struct amdgpu_ib ib; +	struct amdgpu_ib *ib = NULL; +	struct fence *f = NULL; +	struct amdgpu_device *adev = ring->adev;  	uint64_t dummy;  	int i, r; -	r = amdgpu_ib_get(ring, NULL, ib_size_dw * 4, &ib); +	ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL); +	if (!ib) +		return -ENOMEM; + +	r = amdgpu_ib_get(ring, NULL, ib_size_dw * 4, ib);  	if (r) { +		kfree(ib);  		DRM_ERROR("amdgpu: failed to get ib (%d).\n", r);  		return r;  	} -	dummy = ib.gpu_addr + 1024; +	dummy = ib->gpu_addr + 1024;  	/* stitch together an VCE destroy msg */ -	ib.length_dw = 0; -	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ -	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ -	ib.ptr[ib.length_dw++] = handle; - -	ib.ptr[ib.length_dw++] = 0x00000014; /* len */ -	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ -	ib.ptr[ib.length_dw++] = upper_32_bits(dummy); -	ib.ptr[ib.length_dw++] = dummy; -	ib.ptr[ib.length_dw++] = 0x00000001; - -	ib.ptr[ib.length_dw++] = 0x00000008; /* len */ -	ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */ - -	for (i = ib.length_dw; i < ib_size_dw; ++i) -		ib.ptr[i] = 0x0; - -	r = amdgpu_ib_schedule(ring->adev, 1, &ib, AMDGPU_FENCE_OWNER_UNDEFINED); -	if (r) { -		DRM_ERROR("amdgpu: failed to schedule ib (%d).\n", r); -	} - +	ib->length_dw = 0; +	ib->ptr[ib->length_dw++] = 0x0000000c; /* len */ +	ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ +	ib->ptr[ib->length_dw++] = handle; + +	ib->ptr[ib->length_dw++] = 0x00000014; /* len */ +	ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ +	ib->ptr[ib->length_dw++] = upper_32_bits(dummy); +	ib->ptr[ib->length_dw++] = dummy; +	ib->ptr[ib->length_dw++] = 0x00000001; + +	ib->ptr[ib->length_dw++] = 0x00000008; /* len */ +	ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */ + +	for (i = ib->length_dw; i < ib_size_dw; ++i) +		ib->ptr[i] = 0x0; +	r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, +						 &amdgpu_vce_free_job, +						 AMDGPU_FENCE_OWNER_UNDEFINED, +						 &f); +	if (r) +		goto err;  	if (fence) -		*fence = amdgpu_fence_ref(ib.fence); - -	amdgpu_ib_free(ring->adev, &ib); - +		*fence = fence_get(f); +	fence_put(f); +	if (amdgpu_enable_scheduler) +		return 0; +err: +	amdgpu_ib_free(adev, ib); +	kfree(ib);  	return r;  } @@ -800,9 +835,13 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)   */  int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring)  { -	struct amdgpu_fence *fence = NULL; +	struct fence *fence = NULL;  	int r; +	/* skip vce ring1 ib test for now, since it's not reliable */ +	if (ring == &ring->adev->vce.ring[1]) +		return 0; +  	r = amdgpu_vce_get_create_msg(ring, 1, NULL);  	if (r) {  		DRM_ERROR("amdgpu: failed to get create msg (%d).\n", r); @@ -815,13 +854,13 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring)  		goto error;  	} -	r = amdgpu_fence_wait(fence, false); +	r = fence_wait(fence, false);  	if (r) {  		DRM_ERROR("amdgpu: fence wait failed (%d).\n", r);  	} else {  		DRM_INFO("ib test on ring %d succeeded\n", ring->idx);  	}  error: -	amdgpu_fence_unref(&fence); +	fence_put(fence);  	return r;  } | 
