diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 189 | 
1 files changed, 130 insertions, 59 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index ea00090b3fb3..be45650250fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -67,7 +67,8 @@  #include "smuio_v11_0_6.h"  #include "smuio_v13_0.h" -MODULE_FIRMWARE("amdgpu/ip_discovery.bin"); +#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" +MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);  #define mmRCC_CONFIG_MEMSIZE	0xde3  #define mmMM_INDEX		0x0 @@ -179,7 +180,7 @@ static int hw_id_map[MAX_HWIP] = {  	[DCI_HWIP]	= DCI_HWID,  }; -static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary) +static int amdgpu_discovery_read_binary_from_vram(struct amdgpu_device *adev, uint8_t *binary)  {  	uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;  	uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET; @@ -189,6 +190,34 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin  	return 0;  } +static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary) +{ +	const struct firmware *fw; +	const char *fw_name; +	int r; + +	switch (amdgpu_discovery) { +	case 2: +		fw_name = FIRMWARE_IP_DISCOVERY; +		break; +	default: +		dev_warn(adev->dev, "amdgpu_discovery is not set properly\n"); +		return -EINVAL; +	} + +	r = request_firmware(&fw, fw_name, adev->dev); +	if (r) { +		dev_err(adev->dev, "can't load firmware \"%s\"\n", +			fw_name); +		return r; +	} + +	memcpy((u8 *)binary, (u8 *)fw->data, adev->mman.discovery_tmr_size); +	release_firmware(fw); + +	return 0; +} +  static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)  {  	uint16_t checksum = 0; @@ -206,13 +235,20 @@ static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size  	return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);  } +static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary) +{ +	struct binary_header *bhdr; +	bhdr = (struct binary_header *)binary; + +	return (le32_to_cpu(bhdr->binary_signature) == BINARY_SIGNATURE); +} +  static int amdgpu_discovery_init(struct amdgpu_device *adev)  {  	struct table_info *info;  	struct binary_header *bhdr;  	struct ip_discovery_header *ihdr;  	struct gpu_info_header *ghdr; -	const struct firmware *fw;  	uint16_t offset;  	uint16_t size;  	uint16_t checksum; @@ -223,31 +259,32 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)  	if (!adev->mman.discovery_bin)  		return -ENOMEM; -	if (amdgpu_discovery == 2) { -		r = request_firmware(&fw, "amdgpu/ip_discovery.bin", adev->dev); -		if (r) -			goto get_from_vram; -		dev_info(adev->dev, "Using IP discovery from file\n"); -		memcpy((u8 *)adev->mman.discovery_bin, (u8 *)fw->data, -		       adev->mman.discovery_tmr_size); -		release_firmware(fw); -	} else { -get_from_vram: -		r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin); +	r = amdgpu_discovery_read_binary_from_vram(adev, adev->mman.discovery_bin); +	if (r) { +		dev_err(adev->dev, "failed to read ip discovery binary from vram\n"); +		r = -EINVAL; +		goto out; +	} + +	if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { +		dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n"); +		/* retry read ip discovery binary from file */ +		r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);  		if (r) { -			DRM_ERROR("failed to read ip discovery binary\n"); +			dev_err(adev->dev, "failed to read ip discovery binary from file\n"); +			r = -EINVAL; +			goto out; +		} +		/* check the ip discovery binary signature */ +		if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { +			dev_warn(adev->dev, "get invalid ip discovery binary signature from file\n"); +			r = -EINVAL;  			goto out;  		}  	}  	bhdr = (struct binary_header *)adev->mman.discovery_bin; -	if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) { -		DRM_ERROR("invalid ip discovery binary signature\n"); -		r = -EINVAL; -		goto out; -	} -  	offset = offsetof(struct binary_header, binary_checksum) +  		sizeof(bhdr->binary_checksum);  	size = le16_to_cpu(bhdr->binary_size) - offset; @@ -255,7 +292,7 @@ get_from_vram:  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  					      size, checksum)) { -		DRM_ERROR("invalid ip discovery binary checksum\n"); +		dev_err(adev->dev, "invalid ip discovery binary checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -266,14 +303,14 @@ get_from_vram:  	ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);  	if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) { -		DRM_ERROR("invalid ip discovery data table signature\n"); +		dev_err(adev->dev, "invalid ip discovery data table signature\n");  		r = -EINVAL;  		goto out;  	}  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  					      le16_to_cpu(ihdr->size), checksum)) { -		DRM_ERROR("invalid ip discovery data table checksum\n"); +		dev_err(adev->dev, "invalid ip discovery data table checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -285,7 +322,7 @@ get_from_vram:  	if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,  				              le32_to_cpu(ghdr->size), checksum)) { -		DRM_ERROR("invalid gc data table checksum\n"); +		dev_err(adev->dev, "invalid gc data table checksum\n");  		r = -EINVAL;  		goto out;  	} @@ -379,8 +416,18 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)  				  ip->major, ip->minor,  				  ip->revision); -			if (le16_to_cpu(ip->hw_id) == VCN_HWID) +			if (le16_to_cpu(ip->hw_id) == VCN_HWID) { +				/* Bit [5:0]: original revision value +				 * Bit [7:6]: en/decode capability: +				 *     0b00 : VCN function normally +				 *     0b10 : encode is disabled +				 *     0b01 : decode is disabled +				 */ +				adev->vcn.vcn_config[adev->vcn.num_vcn_inst] = +					ip->revision & 0xc0; +				ip->revision &= ~0xc0;  				adev->vcn.num_vcn_inst++; +			}  			if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||  			    le16_to_cpu(ip->hw_id) == SDMA1_HWID ||  			    le16_to_cpu(ip->hw_id) == SDMA2_HWID || @@ -472,14 +519,6 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n  	return -EINVAL;  } - -int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance, -				     int *major, int *minor, int *revision) -{ -	return amdgpu_discovery_get_ip_version(adev, VCN_HWID, -					       vcn_instance, major, minor, revision); -} -  void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)  {  	struct binary_header *bhdr; @@ -511,7 +550,8 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)  	}  	/* some IP discovery tables on Navy Flounder don't have this set correctly */  	if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) && -	    (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2))) +	    (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2)) && +	    (adev->pdev->revision != 0xFF))  		adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;  	if (vcn_harvest_count == adev->vcn.num_vcn_inst) {  		adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK; @@ -526,10 +566,15 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)  	}  } +union gc_info { +	struct gc_info_v1_0 v1; +	struct gc_info_v2_0 v2; +}; +  int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)  {  	struct binary_header *bhdr; -	struct gc_info_v1_0 *gc_info; +	union gc_info *gc_info;  	if (!adev->mman.discovery_bin) {  		DRM_ERROR("ip discovery uninitialized\n"); @@ -537,28 +582,55 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)  	}  	bhdr = (struct binary_header *)adev->mman.discovery_bin; -	gc_info = (struct gc_info_v1_0 *)(adev->mman.discovery_bin + +	gc_info = (union gc_info *)(adev->mman.discovery_bin +  			le16_to_cpu(bhdr->table_list[GC].offset)); - -	adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->gc_num_se); -	adev->gfx.config.max_cu_per_sh = 2 * (le32_to_cpu(gc_info->gc_num_wgp0_per_sa) + -					      le32_to_cpu(gc_info->gc_num_wgp1_per_sa)); -	adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->gc_num_sa_per_se); -	adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->gc_num_rb_per_se); -	adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->gc_num_gl2c); -	adev->gfx.config.max_gprs = le32_to_cpu(gc_info->gc_num_gprs); -	adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->gc_num_max_gs_thds); -	adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->gc_gs_table_depth); -	adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->gc_gsprim_buff_depth); -	adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->gc_double_offchip_lds_buffer); -	adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->gc_wave_size); -	adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->gc_max_waves_per_simd); -	adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->gc_max_scratch_slots_per_cu); -	adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->gc_lds_size); -	adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->gc_num_sc_per_se) / -					 le32_to_cpu(gc_info->gc_num_sa_per_se); -	adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->gc_num_packer_per_sc); - +	switch (gc_info->v1.header.version_major) { +	case 1: +		adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v1.gc_num_se); +		adev->gfx.config.max_cu_per_sh = 2 * (le32_to_cpu(gc_info->v1.gc_num_wgp0_per_sa) + +						      le32_to_cpu(gc_info->v1.gc_num_wgp1_per_sa)); +		adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->v1.gc_num_sa_per_se); +		adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->v1.gc_num_rb_per_se); +		adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->v1.gc_num_gl2c); +		adev->gfx.config.max_gprs = le32_to_cpu(gc_info->v1.gc_num_gprs); +		adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->v1.gc_num_max_gs_thds); +		adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->v1.gc_gs_table_depth); +		adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->v1.gc_gsprim_buff_depth); +		adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->v1.gc_double_offchip_lds_buffer); +		adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->v1.gc_wave_size); +		adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->v1.gc_max_waves_per_simd); +		adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->v1.gc_max_scratch_slots_per_cu); +		adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->v1.gc_lds_size); +		adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v1.gc_num_sc_per_se) / +			le32_to_cpu(gc_info->v1.gc_num_sa_per_se); +		adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v1.gc_num_packer_per_sc); +		break; +	case 2: +		adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v2.gc_num_se); +		adev->gfx.config.max_cu_per_sh = le32_to_cpu(gc_info->v2.gc_num_cu_per_sh); +		adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->v2.gc_num_sh_per_se); +		adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->v2.gc_num_rb_per_se); +		adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->v2.gc_num_tccs); +		adev->gfx.config.max_gprs = le32_to_cpu(gc_info->v2.gc_num_gprs); +		adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->v2.gc_num_max_gs_thds); +		adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->v2.gc_gs_table_depth); +		adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->v2.gc_gsprim_buff_depth); +		adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->v2.gc_double_offchip_lds_buffer); +		adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->v2.gc_wave_size); +		adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->v2.gc_max_waves_per_simd); +		adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->v2.gc_max_scratch_slots_per_cu); +		adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->v2.gc_lds_size); +		adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v2.gc_num_sc_per_se) / +			le32_to_cpu(gc_info->v2.gc_num_sh_per_se); +		adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v2.gc_num_packer_per_sc); +		break; +	default: +		dev_err(adev->dev, +			"Unhandled GC info table %d.%d\n", +			gc_info->v1.header.version_major, +			gc_info->v1.header.version_minor); +		return -EINVAL; +	}  	return 0;  } @@ -917,7 +989,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)  			break;  		case IP_VERSION(3, 0, 0):  		case IP_VERSION(3, 0, 16): -		case IP_VERSION(3, 0, 64):  		case IP_VERSION(3, 1, 1):  		case IP_VERSION(3, 0, 2):  		case IP_VERSION(3, 0, 192): @@ -954,7 +1025,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)  		amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);  		break;  	default: -		break;; +		break;  	}  	return 0;  }  |