[PATCH i-g-t v2 2/3] lib/amdgpu: Extract PCI device address from file descriptor

Jesse.zhang@amd.com jesse.zhang at amd.com
Fri Jan 3 08:17:33 UTC 2025


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

Get the pci domain, device and function number from the amdgpu device's fd.

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

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

diff --git a/lib/amdgpu/amd_ip_blocks.c b/lib/amdgpu/amd_ip_blocks.c
index cc4163bfc..05e6e2622 100644
--- a/lib/amdgpu/amd_ip_blocks.c
+++ b/lib/amdgpu/amd_ip_blocks.c
@@ -1047,3 +1047,67 @@ is_reset_enable(enum amd_ip_block_type ip_type, uint32_t reset_type)
 
         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) {
+        perror("open");
+        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) {
+        printf("Unable to extract PCI device address from '%s'\n", 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.25.1



More information about the igt-dev mailing list