libamdgpu_top/xdna/
xdna_device_path.rs

1// ref: https://github.com/amd/xdna-driver/blob/main/src/driver/amdxdna/amdxdna_drm.c
2// ref: https://github.com/amd/xdna-driver/blob/main/src/driver/amdxdna/amdxdna_pci_drv.c
3
4use std::{fs, io};
5use std::sync::{Arc, Mutex};
6use std::path::PathBuf;
7use crate::{DeviceType, DevicePath, PCI};
8
9pub fn find_xdna_device() -> Option<DevicePath> {
10    let [accel, sysfs_path] = find_accel_path_and_sysfs_path()?;
11    let pci: PCI::BUS_INFO = sysfs_path.file_name()?.to_str()?.parse().ok()?;
12    let render = PathBuf::new();
13    let card = PathBuf::new();
14    let [device_id, revision_id] = [pci.get_device_id(), pci.get_revision_id()];
15    let device_name = fs::read_to_string(sysfs_path.join("vbnv"))
16        .map(|mut s| {
17            let _ = s.pop(); // trim '\n'
18            s
19        })
20        .unwrap_or_default();
21    let arc_proc_index = Arc::new(Mutex::new(Vec::new()));
22    let config_pm = sysfs_path.join("power").exists();
23
24    Some(DevicePath {
25        libdrm_amdgpu: None,
26        render,
27        card,
28        accel,
29        pci,
30        sysfs_path,
31        device_id,
32        revision_id,
33        device_name,
34        arc_proc_index,
35        config_pm,
36        device_type: DeviceType::AMDXDNA,
37    })
38}
39
40fn find_accel_path_and_sysfs_path() -> Option<[PathBuf; 2]> {
41    const ACCEL_MAJOR: usize = 261;
42    const MAX_MINOR: usize = 64;
43
44    for i in 0..MAX_MINOR {
45        let accel_path = PathBuf::from(format!("/dev/accel/accel{i}"));
46        // let sysfs_path = PathBuf::from(format!("/sys/class/accel/accel{i}"));
47
48        if !accel_path.exists() {
49            continue;
50        }
51
52        // ref: https://github.com/intel/linux-npu-driver/blob/93fb54b9d42e7f0f6590f9134aaac92bbf226909/umd/vpu_driver/source/os_interface/vpu_driver_api.cpp#L357
53        let sysfs_path = PathBuf::from(format!("/sys/dev/char/{ACCEL_MAJOR}:{i}/device/"));
54        let sysfs_path = fs::canonicalize(sysfs_path).ok()?;
55        let device_type_path = sysfs_path.join("device_type");
56        let vbnv_path = sysfs_path.join("vbnv");
57
58        // ref: https://github.com/amd/xdna-driver/blob/main/src/shim/pcidrv.cpp
59        if device_type_path.exists() && vbnv_path.exists() {
60            return Some([accel_path, sysfs_path]);
61        }
62    }
63
64    None
65}
66
67impl DevicePath {
68    pub fn get_xdna_fw_version(&self) -> io::Result<String> {
69        std::fs::read_to_string(self.sysfs_path.join("fw_version"))
70            .map(|mut s| {
71                let _ = s.pop(); // trim '\n'
72                s
73            })
74    }
75}