diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 65 | 
1 files changed, 50 insertions, 15 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5cc95f1a7dab..0f0b38191fac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -228,6 +228,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,  	ucode->mc_addr = mc_addr;  	ucode->kaddr = kptr; +	if (ucode->ucode_id == AMDGPU_UCODE_ID_STORAGE) +		return 0; +  	header = (const struct common_firmware_header *)ucode->fw->data;  	memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +  		le32_to_cpu(header->ucode_array_offset_bytes)), @@ -236,6 +239,31 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,  	return 0;  } +static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode, +				uint64_t mc_addr, void *kptr) +{ +	const struct gfx_firmware_header_v1_0 *header = NULL; +	const struct common_firmware_header *comm_hdr = NULL; +	uint8_t* src_addr = NULL; +	uint8_t* dst_addr = NULL; + +	if (NULL == ucode->fw) +		return 0; + +	comm_hdr = (const struct common_firmware_header *)ucode->fw->data; +	header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; +	dst_addr = ucode->kaddr + +			   ALIGN(le32_to_cpu(comm_hdr->ucode_size_bytes), +			   PAGE_SIZE); +	src_addr = (uint8_t *)ucode->fw->data + +			   le32_to_cpu(comm_hdr->ucode_array_offset_bytes) + +			   (le32_to_cpu(header->jt_offset) * 4); +	memcpy(dst_addr, src_addr, le32_to_cpu(header->jt_size) * 4); + +	return 0; +} + +  int amdgpu_ucode_init_bo(struct amdgpu_device *adev)  {  	struct amdgpu_bo **bo = &adev->firmware.fw_buf; @@ -247,53 +275,60 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)  	const struct common_firmware_header *header = NULL;  	err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, -			AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo); +				amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, +				0, NULL, NULL, bo);  	if (err) {  		dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err); -		err = -ENOMEM;  		goto failed;  	}  	err = amdgpu_bo_reserve(*bo, false);  	if (err) { -		amdgpu_bo_unref(bo);  		dev_err(adev->dev, "(%d) Firmware buffer reserve failed\n", err); -		goto failed; +		goto failed_reserve;  	} -	err = amdgpu_bo_pin(*bo, AMDGPU_GEM_DOMAIN_GTT, &fw_mc_addr); +	err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, +				&fw_mc_addr);  	if (err) { -		amdgpu_bo_unreserve(*bo); -		amdgpu_bo_unref(bo);  		dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err); -		goto failed; +		goto failed_pin;  	}  	err = amdgpu_bo_kmap(*bo, &fw_buf_ptr);  	if (err) {  		dev_err(adev->dev, "(%d) Firmware buffer kmap failed\n", err); -		amdgpu_bo_unpin(*bo); -		amdgpu_bo_unreserve(*bo); -		amdgpu_bo_unref(bo); -		goto failed; +		goto failed_kmap;  	}  	amdgpu_bo_unreserve(*bo); -	fw_offset = 0;  	for (i = 0; i < AMDGPU_UCODE_ID_MAXIMUM; i++) {  		ucode = &adev->firmware.ucode[i];  		if (ucode->fw) {  			header = (const struct common_firmware_header *)ucode->fw->data;  			amdgpu_ucode_init_single_fw(ucode, fw_mc_addr + fw_offset,  						    fw_buf_ptr + fw_offset); +			if (i == AMDGPU_UCODE_ID_CP_MEC1) { +				const struct gfx_firmware_header_v1_0 *cp_hdr; +				cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; +				amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset, +						    fw_buf_ptr + fw_offset); +				fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE); +			}  			fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);  		}  	} +	return 0; +failed_kmap: +	amdgpu_bo_unpin(*bo); +failed_pin: +	amdgpu_bo_unreserve(*bo); +failed_reserve: +	amdgpu_bo_unref(bo);  failed: -	if (err) -		adev->firmware.smu_load = false; +	adev->firmware.smu_load = false;  	return err;  }  | 
