Skip to content

Commit

Permalink
pci: add the prog-if (register level programming interface) to pci de…
Browse files Browse the repository at this point in the history
…vice attributes

It's the 3rd byte of the class, useful in some corner cases.

It'll be assumed 0 when importing from pre-3.x XMLs.

Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
  • Loading branch information
bgoglin committed Dec 12, 2022
1 parent bf44f30 commit 704c316
Show file tree
Hide file tree
Showing 26 changed files with 463 additions and 449 deletions.
2 changes: 2 additions & 0 deletions NEWS
Expand Up @@ -21,6 +21,8 @@ Version 3.0.0
-------------
* API
+ PCI domains are now always 32bits.
+ The "programming interface" of PCI devices is now exposed
in PCI object attributes.


Version 2.9.0
Expand Down
10 changes: 8 additions & 2 deletions hwloc/topology-linux.c
Expand Up @@ -6864,6 +6864,7 @@ hwloc_linuxfs_pci_look_pcidevices(struct hwloc_backend *backend)
unsigned domain, bus, dev, func;
unsigned secondary_bus, subordinate_bus;
unsigned short class_id;
unsigned char prog_if;
hwloc_obj_type_t type;
hwloc_obj_t obj;
struct hwloc_pcidev_attr_s *attr;
Expand All @@ -6884,10 +6885,14 @@ hwloc_linuxfs_pci_look_pcidevices(struct hwloc_backend *backend)
}

class_id = HWLOC_PCI_CLASS_NOT_DEFINED;
prog_if = 0;
err = snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/class", dirent->d_name);
if ((size_t) err < sizeof(path)
&& hwloc_read_path_by_length(path, value, sizeof(value), root_fd) > 0)
class_id = strtoul(value, NULL, 16) >> 8;
&& hwloc_read_path_by_length(path, value, sizeof(value), root_fd) > 0) {
unsigned long fullclass = strtoul(value, NULL, 16);
class_id = fullclass >> 8;
prog_if = fullclass & 0xff;
}

type = hwloc_pcidisc_check_bridge_type(class_id, config_space_cache);
/* only HWLOC_OBJ_BRIDGE for bridges to-PCI */
Expand Down Expand Up @@ -6943,6 +6948,7 @@ hwloc_linuxfs_pci_look_pcidevices(struct hwloc_backend *backend)
attr->vendor_id = 0;
attr->device_id = 0;
attr->class_id = class_id;
attr->prog_if = prog_if;
attr->revision = 0;
attr->subvendor_id = 0;
attr->subdevice_id = 0;
Expand Down
4 changes: 2 additions & 2 deletions hwloc/topology-nvml.c
Expand Up @@ -90,9 +90,9 @@ hwloc__nvml_get_peer_obj_by_pci(struct hwloc_topology *topology, hwloc_obj_t gpu
default: {
static int warned = 0;
if (!warned && HWLOC_SHOW_ALL_ERRORS())
fprintf(stderr, "hwloc failed to recognize NVLink peer %04x:%02x:%02x class %04x vendor %04x device %04x\n",
fprintf(stderr, "hwloc failed to recognize NVLink peer %04x:%02x:%02x class %04x prog-if %02x vendor %04x device %04x\n",
peer_bdf.domain, peer_bdf.bus, peer_bdf.device,
obj->attr->pcidev.class_id, obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id);
obj->attr->pcidev.class_id, obj->attr->pcidev.prog_if, obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id);
warned = 1;
return NULL;
}
Expand Down
8 changes: 5 additions & 3 deletions hwloc/topology-pci.c
Expand Up @@ -193,7 +193,7 @@ hwloc_look_pci(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)
struct hwloc_obj *obj;
unsigned domain, bus, dev, func;
unsigned secondary_bus, subordinate_bus;
unsigned device_class;
unsigned device_class, prog_if;
unsigned short tmp16;
unsigned offset;

Expand All @@ -209,6 +209,7 @@ hwloc_look_pci(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)

/* try to read the device_class */
device_class = pcidev->device_class >> 8;
prog_if = pcidev->device_class & 0xff;

/* bridge or pci dev? */
type = hwloc_pcidisc_check_bridge_type(device_class, config_space_cache);
Expand Down Expand Up @@ -297,6 +298,7 @@ hwloc_look_pci(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)
obj->attr->pcidev.vendor_id = pcidev->vendor_id;
obj->attr->pcidev.device_id = pcidev->device_id;
obj->attr->pcidev.class_id = device_class;
obj->attr->pcidev.prog_if = prog_if;
obj->attr->pcidev.revision = config_space_cache[PCI_REVISION_ID];

/* bridge specific attributes */
Expand Down Expand Up @@ -358,9 +360,9 @@ hwloc_look_pci(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)
*/
}

hwloc_debug(" %04x:%02x:%02x.%01x %04x %04x:%04x\n",
hwloc_debug(" %04x:%02x:%02x.%01x %04x %02x %04x:%04x\n",
domain, bus, dev, func,
device_class, pcidev->vendor_id, pcidev->device_id);
device_class, prog_if, pcidev->vendor_id, pcidev->device_id);

hwloc_pci_get_obj_names(obj, &m);
hwloc_pcidisc_tree_insert_by_busid(&tree, obj);
Expand Down
13 changes: 8 additions & 5 deletions hwloc/topology-xml.c
Expand Up @@ -291,14 +291,17 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology,
switch (obj->type) {
case HWLOC_OBJ_PCI_DEVICE:
case HWLOC_OBJ_BRIDGE: {
unsigned classid, vendor, device, subvendor, subdevice, revision;
if (sscanf(value, "%x [%04x:%04x] [%04x:%04x] %02x",
&classid, &vendor, &device, &subvendor, &subdevice, &revision) != 6) {
unsigned classid, vendor, device, subvendor, subdevice, revision, prog_if = 0;
if (sscanf(value, "%x [%04x:%04x] [%04x:%04x] %02x %02x",
&classid, &vendor, &device, &subvendor, &subdevice, &revision, &prog_if) != 7
&& sscanf(value, "%x [%04x:%04x] [%04x:%04x] %02x", /* hwloc < 3.x didn't export the prog-if */
&classid, &vendor, &device, &subvendor, &subdevice, &revision) != 6) {
if (hwloc__xml_verbose())
fprintf(stderr, "%s: ignoring invalid pci_type format string %s\n",
state->global->msgprefix, value);
} else {
obj->attr->pcidev.class_id = classid;
obj->attr->pcidev.prog_if = prog_if;
obj->attr->pcidev.vendor_id = vendor;
obj->attr->pcidev.device_id = device;
obj->attr->pcidev.subvendor_id = subvendor;
Expand Down Expand Up @@ -2586,11 +2589,11 @@ hwloc__xml_export_object_contents (hwloc__xml_export_state_t state, hwloc_topolo
(unsigned) obj->attr->pcidev.dev,
(unsigned) obj->attr->pcidev.func);
state->new_prop(state, "pci_busid", tmp);
sprintf(tmp, "%04x [%04x:%04x] [%04x:%04x] %02x",
sprintf(tmp, "%04x [%04x:%04x] [%04x:%04x] %02x %02x",
(unsigned) obj->attr->pcidev.class_id,
(unsigned) obj->attr->pcidev.vendor_id, (unsigned) obj->attr->pcidev.device_id,
(unsigned) obj->attr->pcidev.subvendor_id, (unsigned) obj->attr->pcidev.subdevice_id,
(unsigned) obj->attr->pcidev.revision);
(unsigned) obj->attr->pcidev.revision, (unsigned) obj->attr->pcidev.prog_if);
state->new_prop(state, "pci_type", tmp);
sprintf(tmp, "%f", obj->attr->pcidev.linkspeed);
state->new_prop(state, "pci_link_speed", tmp);
Expand Down
3 changes: 2 additions & 1 deletion include/hwloc.h
Expand Up @@ -93,7 +93,7 @@ extern "C" {
* Two stable releases of the same series usually have the same ::HWLOC_API_VERSION
* even if their HWLOC_VERSION are different.
*/
#define HWLOC_API_VERSION 0x00020800
#define HWLOC_API_VERSION 0x00030000

/** \brief Indicate at runtime which hwloc API version was used at build time.
*
Expand Down Expand Up @@ -633,6 +633,7 @@ union hwloc_obj_attr_u {
struct hwloc_pcidev_attr_s {
unsigned int domain;
unsigned char bus, dev, func;
unsigned char prog_if; /* the register-level programming interface */
unsigned short class_id;
unsigned short vendor_id, device_id, subvendor_id, subdevice_id;
unsigned char revision;
Expand Down

0 comments on commit 704c316

Please sign in to comment.