[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