static int get_pci_device_speed()

in src/nccl_ofi_topo.cpp [1122:1233]


static int get_pci_device_speed(hwloc_obj_t node, bool is_nic,
				size_t *speed_idx, size_t *width)
{
	union hwloc_obj_attr_u attr = {};
	/* Override the following PCI width and speed of libfabric NICs with fallback values */
	const char *override_width = "255";
	const char *override_speed = "Unknown";
	size_t fallback_width = 8;
	size_t fallback_speed_idx = 3;

	if (node->type == HWLOC_OBJ_BRIDGE) {
		attr.pcidev = node->attr->bridge.upstream.pci;
	} else if (node->type == HWLOC_OBJ_PCI_DEVICE) {
		attr.pcidev = node->attr->pcidev;
	} else {
		NCCL_OFI_WARN("Expected topology node to be a PCI device or bridge");
		return -EINVAL;
	}

	int ret;
	char prop_str[MAX_DEV_PROPERTY_LENGTH + 1];
	/* Size of the PCI speed lookup table `pcie_gen` */
	size_t num_pcie_gens = sizeof(pcie_gen) / sizeof(pcie_gen[0]);

	/* Read link speed */
	if ((ret = get_device_property(attr.pcidev.domain,
				       attr.pcidev.bus,
				       attr.pcidev.dev,
				       attr.pcidev.func,
				       speed_name,
				       prop_str))) {
		return ret;
	}

	/* Search reported PCI speed in `pcie_gen` lookup table */
	*speed_idx = 0;
	while (*speed_idx < num_pcie_gens && strncmp(prop_str, pcie_gen[*speed_idx], strlen(pcie_gen[*speed_idx])) != 0) {
		++(*speed_idx);
	}

	if (is_nic && strncmp(override_speed, prop_str, strlen(override_speed)) == 0) {
		/* Override speed */
		*speed_idx = fallback_speed_idx;
		NCCL_OFI_INFO(
			NCCL_INIT,
			"Override link speed \"%s\" of NIC %04x:%02x:%02x.%01x with speed \"%s\"",
			prop_str,
			attr.pcidev.domain,
			attr.pcidev.bus,
			attr.pcidev.dev,
			attr.pcidev.func,
			pcie_gen[*speed_idx]);
	}
	if (*speed_idx == num_pcie_gens) {
		NCCL_OFI_WARN("Unknown link speed \"%s\" of device %04x:%02x:%02x.%01x",
			      prop_str,
			      attr.pcidev.domain,
			      attr.pcidev.bus,
			      attr.pcidev.dev,
			      attr.pcidev.func);
		return -EINVAL;
	}

	/* Read link width */
	if ((ret = get_device_property(attr.pcidev.domain,
				       attr.pcidev.bus,
				       attr.pcidev.dev,
				       attr.pcidev.func,
				       width_name,
				       prop_str))) {
		return ret;
	}

	if (is_nic && strncmp(override_width, prop_str, strlen(override_width)) == 0) {
		/* Override width */
		*width = fallback_width;
		NCCL_OFI_INFO(
			NCCL_INIT,
			"Override link width \"%s\" of NIC %04x:%02x:%02x.%01x with width \"%zu\"",
			prop_str,
			attr.pcidev.domain,
			attr.pcidev.bus,
			attr.pcidev.dev,
			attr.pcidev.func,
			*width);
	} else {
		*width = strtol(prop_str, NULL, 0);
	}
	if (errno == ERANGE) {
		NCCL_OFI_WARN(
			"Unable to convert link width \"%s\" of device %04x:%02x:%02x.%01x to a "
			"valid link width. "
			"Error: %s",
			prop_str,
			attr.pcidev.domain,
			attr.pcidev.bus,
			attr.pcidev.dev,
			attr.pcidev.func,
			strerror(errno));
		return -errno;
	} else if (*width == 0) {
		NCCL_OFI_WARN("Unknown link width \"%s\" of device %04x:%02x:%02x.%01x",
			      prop_str,
			      attr.pcidev.domain,
			      attr.pcidev.bus,
			      attr.pcidev.dev,
			      attr.pcidev.func);
		return -EINVAL;
	}

	return 0;
}