[PATCH 1/3] lib/amdgpu: Extract PCI device address from file descriptor

vitaly.prosyak at amd.com vitaly.prosyak at amd.com
Sun Jan 5 07:15:49 UTC 2025


From: "Jesse.zhang at amd.com" <Jesse.zhang at amd.com>

Extract the PCI domain, device, and function numbers from
the file descriptor associated with the amdgpu device.

Cc: Vitaly Prosyak <vitaly.prosyak at amd.com>
Cc: Christian Koenig <christian.koenig at amd.com>
Cc: Alexander Deucher <alexander.deucher at amd.com>

v2 : improve commit message, formatting and some coding (Vitaly)

Suggest-by: Vitaly Prosyak <vitaly.prosyak at amd.com>
Signed-off-by: Jesse Zhang  <jesse.zhang at amd.com>
Reviewed-by: Vitaly Prosyak <vitaly.prosyak at amd.com>
---
 lib/amdgpu/amd_ip_blocks.c | 143 ++++++++++++++++++++++++++-----------
 lib/amdgpu/amd_ip_blocks.h |  17 +++++
 2 files changed, 118 insertions(+), 42 deletions(-)

diff --git a/lib/amdgpu/amd_ip_blocks.c b/lib/amdgpu/amd_ip_blocks.c
index cc4163bfc..9749e2072 100644
--- a/lib/amdgpu/amd_ip_blocks.c
+++ b/lib/amdgpu/amd_ip_blocks.c
@@ -810,10 +810,9 @@ int setup_amdgpu_ip_blocks(uint32_t major, uint32_t minor, struct amdgpu_gpu_inf
 		igt_info("amdgpu: unknown (family_id, chip_external_rev): (%u, %u)\n",
 			 amdinfo->family_id, amdinfo->chip_external_rev);
 		return -1;
-	} else {
-		igt_info("amdgpu: %s (family_id, chip_external_rev): (%u, %u)\n",
-				info->name, amdinfo->family_id, amdinfo->chip_external_rev);
 	}
+	igt_info("amdgpu: %s (family_id, chip_external_rev): (%u, %u)\n",
+				info->name, amdinfo->family_id, amdinfo->chip_external_rev);
 
 	if (info->family >= CHIP_GFX1100) {
 		info->chip_class = GFX11;
@@ -1007,43 +1006,103 @@ asic_rings_readness(amdgpu_device_handle device_handle, uint32_t mask,
 bool
 is_reset_enable(enum amd_ip_block_type ip_type, uint32_t reset_type)
 {
-        char cmd[256];
-        FILE *fp, *fp2;
-        char buffer[100];
-        bool enable = false;
-        char reset_mask[100];
-
-        if(ip_type == AMD_IP_GFX)
-                snprintf(reset_mask, sizeof(reset_mask) - 1, "gfx_reset_mask");
-        else if (ip_type == AMD_IP_COMPUTE)
-                snprintf(reset_mask, sizeof(reset_mask) - 1, "compute_reset_mask");
-        else
-                snprintf(reset_mask, sizeof(reset_mask) - 1, "sdma_reset_mask");
-
-        snprintf(cmd, sizeof(cmd) - 1, "sudo cat /sys/kernel/debug/dri/0/name |grep -oP '(?<=dev=)[0-9:.]+'");
-        fp = popen(cmd, "r");
-        if (fp == NULL)
-                return false;
-
-        if (fgets(buffer, 13, fp) != NULL) {
-                snprintf(cmd,sizeof(cmd) - 1,"sudo cat /sys/bus/pci/devices/%s/%s | grep -oP '%s'",
-                        buffer,reset_mask,
-			reset_type & AMDGPU_RESET_TYPE_FULL ? "full":
-			reset_type & AMDGPU_RESET_TYPE_SOFT_RESET ? "soft":
-			reset_type & AMDGPU_RESET_TYPE_PER_QUEUE ? "queue": "pipe");
-
-                fp2 = popen(cmd, "r");
-                if (fp2 == NULL) {
-                        pclose(fp);
-                        return false;
-                }
-
-                if (fgets(buffer, 13, fp2) != NULL) {
-                        enable = true;
-                }
-                pclose(fp2);
-        }
-        pclose(fp);
-
-        return enable;
+	char cmd[256];
+	FILE *fp, *fp2;
+	char buffer[100];
+	bool enable = false;
+	char reset_mask[100];
+
+	if (ip_type == AMD_IP_GFX)
+		snprintf(reset_mask, sizeof(reset_mask) - 1, "gfx_reset_mask");
+	else if (ip_type == AMD_IP_COMPUTE)
+		snprintf(reset_mask, sizeof(reset_mask) - 1, "compute_reset_mask");
+	else
+		snprintf(reset_mask, sizeof(reset_mask) - 1, "sdma_reset_mask");
+
+	snprintf(cmd, sizeof(cmd) - 1, "sudo cat /sys/kernel/debug/dri/0/name |grep -oP '(?<=dev=)[0-9:.]+'");
+	fp = popen(cmd, "r");
+	if (fp == NULL)
+		return false;
+
+	if (fgets(buffer, 13, fp) != NULL) {
+		snprintf(cmd, sizeof(cmd) - 1, "sudo cat /sys/bus/pci/devices/%s/%s | grep -oP '%s'",
+			buffer, reset_mask,
+			reset_type & AMDGPU_RESET_TYPE_FULL ? "full" :
+			reset_type & AMDGPU_RESET_TYPE_SOFT_RESET ? "soft" :
+			reset_type & AMDGPU_RESET_TYPE_PER_QUEUE ? "queue" : "pipe");
+
+		fp2 = popen(cmd, "r");
+		if (fp2 == NULL) {
+			pclose(fp);
+			return false;
+		}
+
+		if (fgets(buffer, 13, fp2) != NULL)
+			enable = true;
+		pclose(fp2);
+	}
+	pclose(fp);
+
+	return enable;
+}
+
+/**
+ * get_pci_addr_from_fd - Extracts the PCI device address from a file descriptor.
+ * @fd: The file descriptor to extract the address from.
+ * @pci: Pointer to a pci_addr struct to store the extracted address.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int get_pci_addr_from_fd(int fd, struct pci_addr *pci)
+{
+	char path[80];
+	struct stat st;
+	char link[20], pci_path[256];
+	char *buf;
+	int len, sysfs;
+	int ret;
+
+	// Check if the file descriptor is a character device and can be accessed
+	if (fstat(fd, &st) < 0 || !S_ISCHR(st.st_mode))
+		return -1;
+
+	snprintf(path, sizeof(path), "/sys/dev/char/%d:%d",
+			major(st.st_rdev), minor(st.st_rdev));
+
+	// Check if the sysfs path exists
+	if (access(path, F_OK) < 0)
+		return -1;
+
+	// Open the sysfs directory
+	sysfs = open(path, O_RDONLY);
+	if (sysfs < 0)
+		return -1;
+
+	// Read the "device" link from the sysfs directory
+	snprintf(link, sizeof(link), "device");
+	len = readlinkat(sysfs, link, pci_path, sizeof(pci_path) - 1);
+	if (len == -1) {
+		close(sysfs);
+		return -ENOENT;
+	}
+	close(sysfs);
+ // Null-terminate the extracted path
+	pci_path[len] = '\0';
+
+	// Find the last occurrence of '/' in the extracted path
+	buf = strrchr(pci_path, '/');
+	if (!buf)
+		return -ENOENT;
+
+	// Extract the PCI device address from the path using sscanf
+	ret = sscanf(buf, "/%4x:%2x:%2x.%2x", &pci->domain, &pci->bus,
+			&pci->device, &pci->function);
+
+	if (ret != 4) {
+		igt_info("error %s Unable to extract PCI device address from '%s\n",
+				__FUNCTION__, buf);
+		return -ENOENT;
+	}
+
+	return 0;
 }
diff --git a/lib/amdgpu/amd_ip_blocks.h b/lib/amdgpu/amd_ip_blocks.h
index 337ef3c25..dc4d87151 100644
--- a/lib/amdgpu/amd_ip_blocks.h
+++ b/lib/amdgpu/amd_ip_blocks.h
@@ -8,6 +8,13 @@
 #define AMD_IP_BLOCKS_H
 
 #include <amdgpu_drm.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
 
 #include "amd_registers.h"
 #include "amd_family.h"
@@ -183,6 +190,13 @@ struct chip_info {
 	amdgpu_device_handle dev;
 };
 
+struct pci_addr {
+    unsigned int domain;
+    unsigned int bus;
+    unsigned int device;
+    unsigned int function;
+};
+
 extern  struct amdgpu_ip_blocks_device amdgpu_ips;
 extern const struct chip_info  *g_pChip;
 int
@@ -220,4 +234,7 @@ asic_rings_readness(amdgpu_device_handle device_handle, uint32_t mask, bool arr[
 
 bool
 is_reset_enable(enum amd_ip_block_type ip_type, uint32_t reset_type);
+
+int
+get_pci_addr_from_fd(int fd, struct pci_addr *pci);
 #endif
-- 
2.34.1



More information about the igt-dev mailing list