[PATCH] drm/amd/amdgpu: Add ip_discovery_text sysfs entry (v2)

Christian König ckoenig.leichtzumerken at gmail.com
Thu Jan 27 08:11:50 UTC 2022



Am 25.01.22 um 19:18 schrieb Tom St Denis:
> Newer hardware has a discovery table in hardware that the kernel will
> rely on instead of header files for things like IP offsets.  This
> sysfs entry adds a simple to parse table of IP instances and segment
> offsets.
>
> Produces output that looks like:
>
> $ cat ip_discovery_text
> ATHUB{0} v2.0.0: 00000c00 02408c00
> CLKA{0} v11.0.0: 00016c00 02401800
> CLKA{1} v11.0.0: 00016e00 02401c00
> CLKA{2} v11.0.0: 00017000 02402000
> CLKA{3} v11.0.0: 00017200 02402400
> CLKA{4} v11.0.0: 0001b000 0242d800
> CLKB{0} v11.0.0: 00017e00 0240bc00
> DBGU_NBIO{0} v3.0.0: 000001c0 02409000
> DBGU0{0} v3.0.0: 00000180 02409800
> DBGU1{0} v3.0.0: 000001a0 02409c00
> DF{0} v3.0.0: 00007000 0240b800
> DFX{0} v4.1.0: 00000580 02409400
> DFX_DAP{0} v2.0.0: 000005a0 00b80000 0240c400
> DMU{0} v2.0.2: 00000012 000000c0 000034c0 00009000 02403c00
> FUSE{0} v11.0.0: 00017400 02401400
> GC{0} v10.1.10: 00001260 0000a000 02402c00

Mhm, I'm also leaning more into Alex direction that this should probably 
better represented as directory structure in sysfs.

We could expose the IP discovery table as binary, but parsing it first 
and then not building proper sysfs structures is pretty clearly against 
the documented rules.

Regards,
Christian.

>
> (v2): Use a macro for buffer size and fix alignment in amdgpu.h
>
> Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |  1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 79 ++++++++++++++++++-
>   2 files changed, 79 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 3bc76759c143..43caeb4bdc07 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1019,6 +1019,7 @@ struct amdgpu_device {
>   	struct amdgpu_ip_block          ip_blocks[AMDGPU_MAX_IP_NUM];
>   	uint32_t		        harvest_ip_mask;
>   	int				num_ip_blocks;
> +	char            *ip_discovery_text;
>   	struct mutex	mn_lock;
>   	DECLARE_HASHTABLE(mn_hash, 7);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> index 07623634fdc2..d036977dab8a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
> @@ -267,6 +267,19 @@ static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev)
>   	}
>   }
>   
> +static ssize_t ip_discovery_text_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct drm_device *ddev = dev_get_drvdata(dev);
> +	struct amdgpu_device *adev = drm_to_adev(ddev);
> +
> +	return sysfs_emit(buf, "%s", adev->ip_discovery_text);
> +}
> +
> +static DEVICE_ATTR(ip_discovery_text, S_IRUGO,
> +				ip_discovery_text_show, NULL);
> +
> +
>   static int amdgpu_discovery_init(struct amdgpu_device *adev)
>   {
>   	struct table_info *info;
> @@ -351,6 +364,11 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
>   		goto out;
>   	}
>   
> +	// init sysfs for ip_discovery
> +	r = sysfs_create_file(&adev->dev->kobj, &dev_attr_ip_discovery_text.attr);
> +	if (r)
> +		dev_err(adev->dev, "Could not create amdgpu device attr\n");
> +
>   	return 0;
>   
>   out:
> @@ -363,7 +381,11 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
>   void amdgpu_discovery_fini(struct amdgpu_device *adev)
>   {
>   	kfree(adev->mman.discovery_bin);
> +	kfree(adev->ip_discovery_text);
> +	sysfs_remove_file(&adev->dev->kobj, &dev_attr_ip_discovery_text.attr);
> +
>   	adev->mman.discovery_bin = NULL;
> +	adev->ip_discovery_text = NULL;
>   }
>   
>   static int amdgpu_discovery_validate_ip(const struct ip *ip)
> @@ -382,6 +404,22 @@ static int amdgpu_discovery_validate_ip(const struct ip *ip)
>   	return 0;
>   }
>   
> +#define IP_DISCOVERY_BLOCK_SIZE 4096
> +
> +static int add_string(char **dst, unsigned *size, char *src)
> +{
> +	if (strlen(src) + strlen(*dst) >= *size) {
> +		void *tmp = krealloc(*dst, *size + IP_DISCOVERY_BLOCK_SIZE, GFP_KERNEL);
> +		if (!tmp) {
> +			return -1;
> +		}
> +		*dst = tmp;
> +		*size = *size + IP_DISCOVERY_BLOCK_SIZE;
> +	}
> +	strcat(*dst, src);
> +	return 0;
> +}
> +
>   int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   {
>   	struct binary_header *bhdr;
> @@ -396,6 +434,8 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   	int hw_ip;
>   	int i, j, k;
>   	int r;
> +	unsigned txt_size = IP_DISCOVERY_BLOCK_SIZE;
> +	char *linebuf;
>   
>   	r = amdgpu_discovery_init(adev);
>   	if (r) {
> @@ -410,6 +450,15 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   
>   	DRM_DEBUG("number of dies: %d\n", num_dies);
>   
> +	adev->ip_discovery_text = kzalloc(txt_size, GFP_KERNEL);
> +	linebuf = kzalloc(IP_DISCOVERY_BLOCK_SIZE, GFP_KERNEL);
> +	if (!adev->ip_discovery_text || !linebuf) {
> +		DRM_ERROR("Out of memory\n");
> +		kfree(linebuf);
> +		kfree(adev->ip_discovery_text);
> +		return -ENOMEM;
> +	}
> +
>   	for (i = 0; i < num_dies; i++) {
>   		die_offset = le16_to_cpu(ihdr->die_info[i].die_offset);
>   		dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset);
> @@ -419,6 +468,8 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   		if (le16_to_cpu(dhdr->die_id) != i) {
>   			DRM_ERROR("invalid die id %d, expected %d\n",
>   					le16_to_cpu(dhdr->die_id), i);
> +			kfree(linebuf);
> +			kfree(adev->ip_discovery_text);
>   			return -EINVAL;
>   		}
>   
> @@ -458,6 +509,19 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   			    le16_to_cpu(ip->hw_id) == SDMA3_HWID)
>   				adev->sdma.num_instances++;
>   
> +			snprintf(linebuf, IP_DISCOVERY_BLOCK_SIZE-1, "%s{%d} v%d.%d.%d: ",
> +				  hw_id_names[le16_to_cpu(ip->hw_id)],
> +				  ip->number_instance,
> +				  ip->major, ip->minor,
> +				  ip->revision);
> +			if (add_string(&adev->ip_discovery_text, &txt_size, linebuf)) {
> +				DRM_ERROR("Out of memory\n");
> +				kfree(linebuf);
> +				kfree(adev->ip_discovery_text);
> +				return -ENOMEM;
> +			}
> +
> +
>   			for (k = 0; k < num_base_address; k++) {
>   				/*
>   				 * convert the endianness of base addresses in place,
> @@ -465,6 +529,19 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   				 */
>   				ip->base_address[k] = le32_to_cpu(ip->base_address[k]);
>   				DRM_DEBUG("\t0x%08x\n", ip->base_address[k]);
> +				snprintf(linebuf, IP_DISCOVERY_BLOCK_SIZE-1, "%08lx ", (unsigned long)ip->base_address[k]);
> +				if (add_string(&adev->ip_discovery_text, &txt_size, linebuf)) {
> +					DRM_ERROR("Out of memory\n");
> +					kfree(linebuf);
> +					kfree(adev->ip_discovery_text);
> +					return -ENOMEM;
> +				}
> +			}
> +			if (add_string(&adev->ip_discovery_text, &txt_size, "\n")) {
> +				DRM_ERROR("Out of memory\n");
> +				kfree(linebuf);
> +				kfree(adev->ip_discovery_text);
> +				return -ENOMEM;
>   			}
>   
>   			for (hw_ip = 0; hw_ip < MAX_HWIP; hw_ip++) {
> @@ -491,7 +568,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
>   			ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
>   		}
>   	}
> -
> +	kfree(linebuf);
>   	return 0;
>   }
>   



More information about the amd-gfx mailing list