diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 249 | 
1 files changed, 141 insertions, 108 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index bcf68f80bbf0..e5a6db6beab7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -53,11 +53,11 @@  /* Firmware Names */  #ifdef CONFIG_DRM_AMDGPU_CIK -#define FIRMWARE_BONAIRE	"radeon/bonaire_uvd.bin" -#define FIRMWARE_KABINI	"radeon/kabini_uvd.bin" -#define FIRMWARE_KAVERI	"radeon/kaveri_uvd.bin" -#define FIRMWARE_HAWAII	"radeon/hawaii_uvd.bin" -#define FIRMWARE_MULLINS	"radeon/mullins_uvd.bin" +#define FIRMWARE_BONAIRE	"amdgpu/bonaire_uvd.bin" +#define FIRMWARE_KABINI	"amdgpu/kabini_uvd.bin" +#define FIRMWARE_KAVERI	"amdgpu/kaveri_uvd.bin" +#define FIRMWARE_HAWAII	"amdgpu/hawaii_uvd.bin" +#define FIRMWARE_MULLINS	"amdgpu/mullins_uvd.bin"  #endif  #define FIRMWARE_TONGA		"amdgpu/tonga_uvd.bin"  #define FIRMWARE_CARRIZO	"amdgpu/carrizo_uvd.bin" @@ -122,15 +122,13 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work);  int amdgpu_uvd_sw_init(struct amdgpu_device *adev)  { -	struct amdgpu_ring *ring; -	struct drm_sched_rq *rq;  	unsigned long bo_size;  	const char *fw_name;  	const struct common_firmware_header *hdr; -	unsigned version_major, version_minor, family_id; +	unsigned family_id;  	int i, j, r; -	INIT_DELAYED_WORK(&adev->uvd.inst->idle_work, amdgpu_uvd_idle_work_handler); +	INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);  	switch (adev->asic_type) {  #ifdef CONFIG_DRM_AMDGPU_CIK @@ -208,29 +206,46 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)  	hdr = (const struct common_firmware_header *)adev->uvd.fw->data;  	family_id = le32_to_cpu(hdr->ucode_version) & 0xff; -	version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; -	version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; -	DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n", -		version_major, version_minor, family_id); - -	/* -	 * Limit the number of UVD handles depending on microcode major -	 * and minor versions. The firmware version which has 40 UVD -	 * instances support is 1.80. So all subsequent versions should -	 * also have the same support. -	 */ -	if ((version_major > 0x01) || -	    ((version_major == 0x01) && (version_minor >= 0x50))) -		adev->uvd.max_handles = AMDGPU_MAX_UVD_HANDLES; -	adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) | -				(family_id << 8)); +	if (adev->asic_type < CHIP_VEGA20) { +		unsigned version_major, version_minor; -	if ((adev->asic_type == CHIP_POLARIS10 || -	     adev->asic_type == CHIP_POLARIS11) && -	    (adev->uvd.fw_version < FW_1_66_16)) -		DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n", -			  version_major, version_minor); +		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff; +		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; +		DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n", +			version_major, version_minor, family_id); + +		/* +		 * Limit the number of UVD handles depending on microcode major +		 * and minor versions. The firmware version which has 40 UVD +		 * instances support is 1.80. So all subsequent versions should +		 * also have the same support. +		 */ +		if ((version_major > 0x01) || +		    ((version_major == 0x01) && (version_minor >= 0x50))) +			adev->uvd.max_handles = AMDGPU_MAX_UVD_HANDLES; + +		adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) | +					(family_id << 8)); + +		if ((adev->asic_type == CHIP_POLARIS10 || +		     adev->asic_type == CHIP_POLARIS11) && +		    (adev->uvd.fw_version < FW_1_66_16)) +			DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n", +				  version_major, version_minor); +	} else { +		unsigned int enc_major, enc_minor, dec_minor; + +		dec_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff; +		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 24) & 0x3f; +		enc_major = (le32_to_cpu(hdr->ucode_version) >> 30) & 0x3; +		DRM_INFO("Found UVD firmware ENC: %hu.%hu DEC: .%hu Family ID: %hu\n", +			enc_major, enc_minor, dec_minor, family_id); + +		adev->uvd.max_handles = AMDGPU_MAX_UVD_HANDLES; + +		adev->uvd.fw_version = le32_to_cpu(hdr->ucode_version); +	}  	bo_size = AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE  		  +  AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles; @@ -238,7 +253,8 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)  		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);  	for (j = 0; j < adev->uvd.num_uvd_inst; j++) { - +		if (adev->uvd.harvest_config & (1 << j)) +			continue;  		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,  					    AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.inst[j].vcpu_bo,  					    &adev->uvd.inst[j].gpu_addr, &adev->uvd.inst[j].cpu_addr); @@ -246,21 +262,13 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)  			dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);  			return r;  		} +	} -		ring = &adev->uvd.inst[j].ring; -		rq = &ring->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL]; -		r = drm_sched_entity_init(&ring->sched, &adev->uvd.inst[j].entity, -					  rq, NULL); -		if (r != 0) { -			DRM_ERROR("Failed setting up UVD(%d) run queue.\n", j); -			return r; -		} - -		for (i = 0; i < adev->uvd.max_handles; ++i) { -			atomic_set(&adev->uvd.inst[j].handles[i], 0); -			adev->uvd.inst[j].filp[i] = NULL; -		} +	for (i = 0; i < adev->uvd.max_handles; ++i) { +		atomic_set(&adev->uvd.handles[i], 0); +		adev->uvd.filp[i] = NULL;  	} +  	/* from uvd v5.0 HW addressing capacity increased to 64 bits */  	if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))  		adev->uvd.address_64_bit = true; @@ -289,10 +297,12 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)  {  	int i, j; -	for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { -		kfree(adev->uvd.inst[j].saved_bo); +	drm_sched_entity_destroy(&adev->uvd.entity); -		drm_sched_entity_fini(&adev->uvd.inst[j].ring.sched, &adev->uvd.inst[j].entity); +	for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { +		if (adev->uvd.harvest_config & (1 << j)) +			continue; +		kvfree(adev->uvd.inst[j].saved_bo);  		amdgpu_bo_free_kernel(&adev->uvd.inst[j].vcpu_bo,  				      &adev->uvd.inst[j].gpu_addr, @@ -308,32 +318,57 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)  	return 0;  } +/** + * amdgpu_uvd_entity_init - init entity + * + * @adev: amdgpu_device pointer + * + */ +int amdgpu_uvd_entity_init(struct amdgpu_device *adev) +{ +	struct amdgpu_ring *ring; +	struct drm_sched_rq *rq; +	int r; + +	ring = &adev->uvd.inst[0].ring; +	rq = &ring->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL]; +	r = drm_sched_entity_init(&adev->uvd.entity, &rq, 1, NULL); +	if (r) { +		DRM_ERROR("Failed setting up UVD kernel entity.\n"); +		return r; +	} + +	return 0; +} +  int amdgpu_uvd_suspend(struct amdgpu_device *adev)  {  	unsigned size;  	void *ptr;  	int i, j; -	for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { -		if (adev->uvd.inst[j].vcpu_bo == NULL) -			continue; +	cancel_delayed_work_sync(&adev->uvd.idle_work); -		cancel_delayed_work_sync(&adev->uvd.inst[j].idle_work); +	/* only valid for physical mode */ +	if (adev->asic_type < CHIP_POLARIS10) { +		for (i = 0; i < adev->uvd.max_handles; ++i) +			if (atomic_read(&adev->uvd.handles[i])) +				break; -		/* only valid for physical mode */ -		if (adev->asic_type < CHIP_POLARIS10) { -			for (i = 0; i < adev->uvd.max_handles; ++i) -				if (atomic_read(&adev->uvd.inst[j].handles[i])) -					break; +		if (i == adev->uvd.max_handles) +			return 0; +	} -			if (i == adev->uvd.max_handles) -				continue; -		} +	for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { +		if (adev->uvd.harvest_config & (1 << j)) +			continue; +		if (adev->uvd.inst[j].vcpu_bo == NULL) +			continue;  		size = amdgpu_bo_size(adev->uvd.inst[j].vcpu_bo);  		ptr = adev->uvd.inst[j].cpu_addr; -		adev->uvd.inst[j].saved_bo = kmalloc(size, GFP_KERNEL); +		adev->uvd.inst[j].saved_bo = kvmalloc(size, GFP_KERNEL);  		if (!adev->uvd.inst[j].saved_bo)  			return -ENOMEM; @@ -349,6 +384,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)  	int i;  	for (i = 0; i < adev->uvd.num_uvd_inst; i++) { +		if (adev->uvd.harvest_config & (1 << i)) +			continue;  		if (adev->uvd.inst[i].vcpu_bo == NULL)  			return -EINVAL; @@ -357,7 +394,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)  		if (adev->uvd.inst[i].saved_bo != NULL) {  			memcpy_toio(ptr, adev->uvd.inst[i].saved_bo, size); -			kfree(adev->uvd.inst[i].saved_bo); +			kvfree(adev->uvd.inst[i].saved_bo);  			adev->uvd.inst[i].saved_bo = NULL;  		} else {  			const struct common_firmware_header *hdr; @@ -381,30 +418,27 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)  void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)  { -	struct amdgpu_ring *ring; -	int i, j, r; - -	for (j = 0; j < adev->uvd.num_uvd_inst; j++) { -		ring = &adev->uvd.inst[j].ring; +	struct amdgpu_ring *ring = &adev->uvd.inst[0].ring; +	int i, r; -		for (i = 0; i < adev->uvd.max_handles; ++i) { -			uint32_t handle = atomic_read(&adev->uvd.inst[j].handles[i]); -			if (handle != 0 && adev->uvd.inst[j].filp[i] == filp) { -				struct dma_fence *fence; - -				r = amdgpu_uvd_get_destroy_msg(ring, handle, -							       false, &fence); -				if (r) { -					DRM_ERROR("Error destroying UVD(%d) %d!\n", j, r); -					continue; -				} +	for (i = 0; i < adev->uvd.max_handles; ++i) { +		uint32_t handle = atomic_read(&adev->uvd.handles[i]); -				dma_fence_wait(fence, false); -				dma_fence_put(fence); +		if (handle != 0 && adev->uvd.filp[i] == filp) { +			struct dma_fence *fence; -				adev->uvd.inst[j].filp[i] = NULL; -				atomic_set(&adev->uvd.inst[j].handles[i], 0); +			r = amdgpu_uvd_get_destroy_msg(ring, handle, false, +						       &fence); +			if (r) { +				DRM_ERROR("Error destroying UVD %d!\n", r); +				continue;  			} + +			dma_fence_wait(fence, false); +			dma_fence_put(fence); + +			adev->uvd.filp[i] = NULL; +			atomic_set(&adev->uvd.handles[i], 0);  		}  	}  } @@ -459,7 +493,7 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)  		if (cmd == 0x0 || cmd == 0x3) {  			/* yes, force it into VRAM */  			uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM; -			amdgpu_ttm_placement_from_domain(bo, domain); +			amdgpu_bo_placement_from_domain(bo, domain);  		}  		amdgpu_uvd_force_into_uvd_segment(bo); @@ -679,16 +713,15 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,  	void *ptr;  	long r;  	int i; -	uint32_t ip_instance = ctx->parser->job->ring->me;  	if (offset & 0x3F) { -		DRM_ERROR("UVD(%d) messages must be 64 byte aligned!\n", ip_instance); +		DRM_ERROR("UVD messages must be 64 byte aligned!\n");  		return -EINVAL;  	}  	r = amdgpu_bo_kmap(bo, &ptr);  	if (r) { -		DRM_ERROR("Failed mapping the UVD(%d) message (%ld)!\n", ip_instance, r); +		DRM_ERROR("Failed mapping the UVD) message (%ld)!\n", r);  		return r;  	} @@ -698,7 +731,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,  	handle = msg[2];  	if (handle == 0) { -		DRM_ERROR("Invalid UVD(%d) handle!\n", ip_instance); +		DRM_ERROR("Invalid UVD handle!\n");  		return -EINVAL;  	} @@ -709,18 +742,19 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,  		/* try to alloc a new handle */  		for (i = 0; i < adev->uvd.max_handles; ++i) { -			if (atomic_read(&adev->uvd.inst[ip_instance].handles[i]) == handle) { -				DRM_ERROR("(%d)Handle 0x%x already in use!\n", ip_instance, handle); +			if (atomic_read(&adev->uvd.handles[i]) == handle) { +				DRM_ERROR(")Handle 0x%x already in use!\n", +					  handle);  				return -EINVAL;  			} -			if (!atomic_cmpxchg(&adev->uvd.inst[ip_instance].handles[i], 0, handle)) { -				adev->uvd.inst[ip_instance].filp[i] = ctx->parser->filp; +			if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) { +				adev->uvd.filp[i] = ctx->parser->filp;  				return 0;  			}  		} -		DRM_ERROR("No more free UVD(%d) handles!\n", ip_instance); +		DRM_ERROR("No more free UVD handles!\n");  		return -ENOSPC;  	case 1: @@ -732,27 +766,27 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,  		/* validate the handle */  		for (i = 0; i < adev->uvd.max_handles; ++i) { -			if (atomic_read(&adev->uvd.inst[ip_instance].handles[i]) == handle) { -				if (adev->uvd.inst[ip_instance].filp[i] != ctx->parser->filp) { -					DRM_ERROR("UVD(%d) handle collision detected!\n", ip_instance); +			if (atomic_read(&adev->uvd.handles[i]) == handle) { +				if (adev->uvd.filp[i] != ctx->parser->filp) { +					DRM_ERROR("UVD handle collision detected!\n");  					return -EINVAL;  				}  				return 0;  			}  		} -		DRM_ERROR("Invalid UVD(%d) handle 0x%x!\n", ip_instance, handle); +		DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);  		return -ENOENT;  	case 2:  		/* it's a destroy msg, free the handle */  		for (i = 0; i < adev->uvd.max_handles; ++i) -			atomic_cmpxchg(&adev->uvd.inst[ip_instance].handles[i], handle, 0); +			atomic_cmpxchg(&adev->uvd.handles[i], handle, 0);  		amdgpu_bo_kunmap(bo);  		return 0;  	default: -		DRM_ERROR("Illegal UVD(%d) message type (%d)!\n", ip_instance, msg_type); +		DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);  		return -EINVAL;  	}  	BUG(); @@ -1000,7 +1034,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,  	if (!ring->adev->uvd.address_64_bit) {  		struct ttm_operation_ctx ctx = { true, false }; -		amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); +		amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);  		amdgpu_uvd_force_into_uvd_segment(bo);  		r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);  		if (r) @@ -1045,19 +1079,16 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,  		if (r < 0)  			goto err_free; -		r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); -		job->fence = dma_fence_get(f); +		r = amdgpu_job_submit_direct(job, ring, &f);  		if (r)  			goto err_free; - -		amdgpu_job_free(job);  	} else {  		r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv,  				     AMDGPU_FENCE_OWNER_UNDEFINED, false);  		if (r)  			goto err_free; -		r = amdgpu_job_submit(job, ring, &adev->uvd.inst[ring->me].entity, +		r = amdgpu_job_submit(job, &adev->uvd.entity,  				      AMDGPU_FENCE_OWNER_UNDEFINED, &f);  		if (r)  			goto err_free; @@ -1145,10 +1176,12 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,  static void amdgpu_uvd_idle_work_handler(struct work_struct *work)  {  	struct amdgpu_device *adev = -		container_of(work, struct amdgpu_device, uvd.inst->idle_work.work); +		container_of(work, struct amdgpu_device, uvd.idle_work.work);  	unsigned fences = 0, i, j;  	for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { +		if (adev->uvd.harvest_config & (1 << i)) +			continue;  		fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);  		for (j = 0; j < adev->uvd.num_enc_rings; ++j) {  			fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]); @@ -1167,7 +1200,7 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)  							       AMD_CG_STATE_GATE);  		}  	} else { -		schedule_delayed_work(&adev->uvd.inst->idle_work, UVD_IDLE_TIMEOUT); +		schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT);  	}  } @@ -1179,7 +1212,7 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)  	if (amdgpu_sriov_vf(adev))  		return; -	set_clocks = !cancel_delayed_work_sync(&adev->uvd.inst->idle_work); +	set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work);  	if (set_clocks) {  		if (adev->pm.dpm_enabled) {  			amdgpu_dpm_enable_uvd(adev, true); @@ -1196,7 +1229,7 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)  void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring)  {  	if (!amdgpu_sriov_vf(ring->adev)) -		schedule_delayed_work(&ring->adev->uvd.inst->idle_work, UVD_IDLE_TIMEOUT); +		schedule_delayed_work(&ring->adev->uvd.idle_work, UVD_IDLE_TIMEOUT);  }  /** @@ -1259,7 +1292,7 @@ uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev)  		 * necessarily linear. So we need to count  		 * all non-zero handles.  		 */ -		if (atomic_read(&adev->uvd.inst->handles[i])) +		if (atomic_read(&adev->uvd.handles[i]))  			used_handles++;  	} |