Applied thanks! Cheers, Tom On 23/06/17 04:33 PM, Jean-Francois Thibert wrote: > This allows selecting the GPU by its PCI device both with and > without kernel mode support. The instance is populated automatically > so that the proper corresponding debugfs files are used if present. > > Signed-off-by: Jean-Francois Thibert <jfthibert at google.com> > --- > doc/umr.1 | 4 +++ > src/app/main.c | 9 ++++++ > src/lib/discover.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- > src/umr.h | 6 ++++ > 4 files changed, 103 insertions(+), 3 deletions(-) > > diff --git a/doc/umr.1 b/doc/umr.1 > index 5c4bd01..a03dfb8 100644 > --- a/doc/umr.1 > +++ b/doc/umr.1 > @@ -17,6 +17,10 @@ Select a GFX INSTANCE/SH/SE bank in decimal. Can use 'x' to denote a broadcast > .IP "--force -f <number>" > Force a PCIE Device ID in hex or by asic name. This is used in case the amdgpu driver > is not yet loaded or a display is not yet attached. > +.IP "--pci <device>" > +Force a specific PCI device using the domain:bus:slot.function format in hex. > +This is useful when more than one GPU is available. If the amdgpu driver is > +loaded the corresponding instance will be automatically detected. > .IP "--print, -p" > Enable scanning and printing all registers. Defaults to off as it can > be very verbose. > diff --git a/src/app/main.c b/src/app/main.c > index 1d9ef9e..067b472 100644 > --- a/src/app/main.c > +++ b/src/app/main.c > @@ -174,6 +174,15 @@ int main(int argc, char **argv) > printf("--force requires a number/name\n"); > return EXIT_FAILURE; > } > + } else if (!strcmp(argv[i], "--pci")) { > + if (i + 1 < argc && sscanf(argv[i+1], "%04x:%02x:%02x.%01x", > + &options.pci.domain, &options.pci.bus, &options.pci.slot, > + &options.pci.func ) >= 4) { > + ++i; > + } else { > + printf("--pci requires domain:bus:slot.function\n"); > + return EXIT_FAILURE; > + } > } else if (!strcmp(argv[i], "--print") || !strcmp(argv[i], "-p")) { > options.print = 1; > options.need_scan = 1; > diff --git a/src/lib/discover.c b/src/lib/discover.c > index 9662d05..a95fe57 100644 > --- a/src/lib/discover.c > +++ b/src/lib/discover.c > @@ -22,6 +22,9 @@ > * Authors: Tom St Denis <tom.stdenis at amd.com> > * > */ > +#include <dirent.h> > +#include <sys/types.h> > + > #include "umr.h" > > static int is_did_match(struct umr_asic *asic, unsigned did) > @@ -44,6 +47,44 @@ static int is_did_match(struct umr_asic *asic, unsigned did) > return r; > } > > +static int find_pci_instance(const char* pci_string) { > + DIR* dir; > + dir = opendir("/sys/kernel/debug/dri"); > + if (dir == NULL) { > + perror("Couldn't open DRI under debugfs"); > + return -1; > + } > + struct dirent *dir_entry; > + while ((dir_entry = readdir(dir)) != NULL) { > + char device[256], name[256]; > + int parsed_device; > + // ignore . and .. > + if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, > + "..") == 0) { > + continue; > + } > + snprintf(name, sizeof(name), "/sys/kernel/debug/dri/%s/name", > + dir_entry->d_name); > + FILE *f = fopen(name, "r"); > + if (!f) { > + continue; > + } > + device[sizeof(device) - 1] = 0; > + parsed_device = fscanf(f, "%*s %255s", device); > + fclose(f); > + if (parsed_device != 1) > + continue; > + // strip off dev= for kernels > 4.7 > + if (strstr(device, "dev=")) > + memmove(device, device+4, strlen(device)-3); > + if (strcmp(pci_string, device) == 0) { > + closedir(dir); > + return atoi(dir_entry->d_name); > + } > + } > + closedir(dir); > + return -1; > +} > > struct umr_asic *umr_discover_asic(struct umr_options *options) > { > @@ -53,6 +94,30 @@ struct umr_asic *umr_discover_asic(struct umr_options *options) > struct umr_asic *asic; > long trydid = options->forcedid; > > + // Try to map to instance if we have a specific pci device > + if (options->pci.domain || options->pci.bus || > + options->pci.slot || options->pci.func) { > + char pci_string[16]; > + int parsed_did; > + snprintf(pci_string, sizeof(pci_string), "%04x:%02x:%02x.%x", > + options->pci.domain, options->pci.bus, options->pci.slot, > + options->pci.func); > + if (!options->no_kernel) { > + options->instance = find_pci_instance(pci_string); > + } > + snprintf(driver, sizeof(driver), "/sys/bus/pci/devices/%s/device", pci_string); > + f = fopen(driver, "r"); > + if (!f) { > + if (!options->quiet) perror("Cannot open PCI device name under sysfs (is a display attached?)"); > + return NULL; > + } > + parsed_did = fscanf(f, "0x%04lx", &trydid); > + fclose(f); > + if (parsed_did != 1) { > + if (!options->quiet) printf("Could not read device id"); > + return NULL; > + } > + } > // try to scan via debugfs > asic = calloc(1, sizeof *asic); > if (asic) { > @@ -64,7 +129,6 @@ struct umr_asic *umr_discover_asic(struct umr_options *options) > umr_free_asic(asic); > asic = NULL; > } > - > if (trydid < 0) { > snprintf(name, sizeof(name)-1, "/sys/kernel/debug/dri/%d/name", options->instance); > f = fopen(name, "r"); > @@ -86,8 +150,12 @@ struct umr_asic *umr_discover_asic(struct umr_options *options) > } > return NULL; > } > - fscanf(f, "%s %s %s\n", driver, name, driver); > + int parsed_pci_id = fscanf(f, "%*s %s", name); > fclose(f); > + if (parsed_pci_id != 1) { > + if (!options->quiet) printf("Cannot read pci device id\n"); > + return NULL; > + } > > // strip off dev= for kernels > 4.7 > if (strstr(name, "dev=")) > @@ -99,8 +167,12 @@ struct umr_asic *umr_discover_asic(struct umr_options *options) > if (!options->quiet) perror("Cannot open PCI device name under sysfs (is a display attached?)"); > return NULL; > } > - fscanf(f, "0x%04x", &did); > + int parsed_did = fscanf(f, "0x%04x", &did); > fclose(f); > + if (parsed_did != 1) { > + if (!options->quiet) printf("Could not read device id"); > + return NULL; > + } > asic = umr_discover_asic_by_did(options, did); > } else { > if (options->dev_name[0]) > @@ -158,6 +230,15 @@ struct umr_asic *umr_discover_asic(struct umr_options *options) > } > do { > asic->pci.pdevice = pci_device_next(pci_iter); > + if (options->pci.domain || options->pci.bus || options->pci.slot || options->pci.func) { > + while (asic->pci.pdevice && ( > + options->pci.domain != asic->pci.pdevice->domain || > + options->pci.bus != asic->pci.pdevice->bus || > + options->pci.slot != asic->pci.pdevice->dev || > + options->pci.func != asic->pci.pdevice->func)) { > + asic->pci.pdevice = pci_device_next(pci_iter); > + } > + } > } while (asic->pci.pdevice && !(asic->pci.pdevice->vendor_id == 0x1002 && is_did_match(asic, asic->pci.pdevice->device_id))); > > if (!asic->pci.pdevice) { > diff --git a/src/umr.h b/src/umr.h > index ccfac5d..2a69017 100644 > --- a/src/umr.h > +++ b/src/umr.h > @@ -181,6 +181,12 @@ struct umr_options { > long forcedid; > char *scanblock; > char dev_name[32]; > + struct { > + int domain, > + bus, > + slot, > + func; > + } pci; > }; > > struct umr_asic { >