diff --git a/device/pcie/pci_device.cpp b/device/pcie/pci_device.cpp index 1db58674e..c592b0520 100644 --- a/device/pcie/pci_device.cpp +++ b/device/pcie/pci_device.cpp @@ -37,6 +37,38 @@ static const uint32_t BH_BAR0_WC_MAPPING_SIZE = 188<<21; static const uint32_t BH_NOC_NODE_ID_OFFSET = 0x1FD04044; static const uint32_t GS_WH_ARC_SCRATCH_6_OFFSET = 0x1FF30078; +static constexpr semver_t MINIMUM_SUPPORTED_KMD_VERSION{1, 27, 1}; + +static semver_t read_kmd_version() { + static const std::string path = "/sys/module/tenstorrent/version"; + std::ifstream file(path); + + if (!file.is_open()) { + TT_THROW("Failed to open: {}; could not determine tenstorrent driver version", path); + } + + std::string version_str; + std::getline(file, version_str); + + std::istringstream iss(version_str); + std::string token; + semver_t semver{}; + + if (std::getline(iss, token, '.')) { + semver.major = std::stoul(token); + + if (std::getline(iss, token, '.')) { + semver.minor = std::stoul(token); + + if (std::getline(iss, token, '.')) { + semver.patch = std::stoul(token); + } + } + } + + return semver; +} + template static T read_sysfs(const PciDeviceInfo &device_info, const std::string &attribute_name) { const auto sysfs_path = fmt::format("/sys/bus/pci/devices/{:04x}:{:02x}:{:02x}.{:x}/{}", @@ -68,6 +100,12 @@ static T read_sysfs(const PciDeviceInfo &device_info, const std::string &attribu static PciDeviceInfo read_device_info(int fd) { + const semver_t kmd_version = read_kmd_version(); + if (kmd_version < MINIMUM_SUPPORTED_KMD_VERSION) { + TT_THROW("Unsupported tenstorrent driver version: {}. Please upgrade to at least {}.", + kmd_version.to_string(), MINIMUM_SUPPORTED_KMD_VERSION.to_string()); + } + tenstorrent_get_device_info info{}; info.in.output_size_bytes = sizeof(info.out); diff --git a/device/pcie/pci_device.hpp b/device/pcie/pci_device.hpp index e0a5230cc..35683dba6 100644 --- a/device/pcie/pci_device.hpp +++ b/device/pcie/pci_device.hpp @@ -43,11 +43,51 @@ struct PciDeviceInfo uint16_t pci_function; }; +// TODO: probably belongs in common.hpp +struct semver_t { + uint32_t major; + uint32_t minor; + uint32_t patch; + + // TODO: there's a neater, C++20 way to do these comparisons. + // Start using it once we move off of Ubuntu 20.04 to a distro that ships a + // modern compiler. + + bool operator<(const semver_t& other) const { + return std::tie(major, minor, patch) < std::tie(other.major, other.minor, other.patch); + } + + bool operator>(const semver_t& other) const { + return other < *this; + } + + bool operator==(const semver_t& other) const { + return std::tie(major, minor, patch) == std::tie(other.major, other.minor, other.patch); + } + + bool operator!=(const semver_t& other) const { + return !(*this == other); + } + + bool operator<=(const semver_t& other) const { + return !(other < *this); + } + + bool operator>=(const semver_t& other) const { + return !(*this < other); + } + + std::string to_string() const { + return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch); + } +}; + + class PCIDevice { const std::string device_path; // Path to character device: /dev/tenstorrent/N - const int pci_device_num; // N in /dev/tenstorrent/N + const int pci_device_num; // N in /dev/tenstorrent/N const int logical_id; // Unique identifier for each device in entire network topology - const int pci_device_file_desc; // Character device file descriptor + const int pci_device_file_desc; // Character device file descriptor const PciDeviceInfo info; // PCI device info const int numa_node; // -1 if non-NUMA const int revision; // PCI revision value from sysfs