]> git.ipfire.org Git - thirdparty/pciutils.git/commitdiff
lspci: Retrieve prog if, subsystem ids and revision id via libpci
authorPali Rohár <pali@kernel.org>
Mon, 20 Dec 2021 21:39:42 +0000 (22:39 +0100)
committerMartin Mares <mj@ucw.cz>
Thu, 10 Feb 2022 12:49:35 +0000 (13:49 +0100)
Use pci_fill_info with CLASS_EXT and SUBSYS to fill this information.

lspci in some places reads class from what libpci provider fills in
dev->device_class and in some other places it reads directly from config
space. In dev->device_class is stored class possible different class as in
config space (e.g. if kernel is fixing class because device has bogus
information stored in config space).

With this change is class always read from dev->device_class which reflects
and respects lspci -b option (Bus-centric view). Same applies for subsystem
ids and revision id (note that prog if is part of class).

ls-kernel.c
lspci.c
lspci.h

index c47dc8301bef11a97f6f2f8864581e1671163423..69e344a2f494877ad8b5dfdf380ccda955dcd90f 100644 (file)
@@ -173,16 +173,14 @@ static int
 match_pcimap(struct device *d, struct pcimap_entry *e)
 {
   struct pci_dev *dev = d->dev;
-  unsigned int class = get_conf_long(d, PCI_REVISION_ID) >> 8;
-  word subv, subd;
+  unsigned int class = (((unsigned int)dev->device_class << 8) | dev->prog_if);
 
 #define MATCH(x, y) ((y) > 0xffff || (x) == (y))
-  get_subid(d, &subv, &subd);
   return
     MATCH(dev->vendor_id, e->vendor) &&
     MATCH(dev->device_id, e->device) &&
-    MATCH(subv, e->subvendor) &&
-    MATCH(subd, e->subdevice) &&
+    MATCH(dev->subsys_vendor_id, e->subvendor) &&
+    MATCH(dev->subsys_id, e->subdevice) &&
     (class & e->class_mask) == e->class;
 #undef MATCH
 }
diff --git a/lspci.c b/lspci.c
index d14d1b9185d6ce20340c4f3cab49b473f6b684d9..f52e7924199484ea7aa142bf9af7b86f2accc39a 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -143,7 +143,7 @@ scan_device(struct pci_dev *p)
        d->config_cached += 64;
     }
   pci_setup_cache(p, d->config, d->config_cached);
-  pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_CLASS);
+  pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_CLASS_EXT | PCI_FILL_SUBSYS);
   return d;
 }
 
@@ -285,25 +285,6 @@ show_slot_name(struct device *d)
   show_slot_path(d);
 }
 
-void
-get_subid(struct device *d, word *subvp, word *subdp)
-{
-  byte htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
-
-  if (htype == PCI_HEADER_TYPE_NORMAL)
-    {
-      *subvp = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
-      *subdp = get_conf_word(d, PCI_SUBSYSTEM_ID);
-    }
-  else if (htype == PCI_HEADER_TYPE_CARDBUS && d->config_cached >= 128)
-    {
-      *subvp = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
-      *subdp = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
-    }
-  else
-    *subvp = *subdp = 0xffff;
-}
-
 static void
 show_terse(struct device *d)
 {
@@ -319,12 +300,12 @@ show_terse(struct device *d)
         pci_lookup_name(pacc, devbuf, sizeof(devbuf),
                         PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
                         p->vendor_id, p->device_id));
-  if (c = get_conf_byte(d, PCI_REVISION_ID))
-    printf(" (rev %02x)", c);
+  if ((p->known_fields & PCI_FILL_CLASS_EXT) && p->rev_id)
+    printf(" (rev %02x)", p->rev_id);
   if (verbose)
     {
       char *x;
-      c = get_conf_byte(d, PCI_CLASS_PROG);
+      c = (p->known_fields & PCI_FILL_CLASS_EXT) ? p->prog_if : 0;
       x = pci_lookup_name(pacc, devbuf, sizeof(devbuf),
                          PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS,
                          p->device_class, c);
@@ -340,19 +321,18 @@ show_terse(struct device *d)
 
   if (verbose || opt_kernel)
     {
-      word subsys_v, subsys_d;
       char ssnamebuf[256];
 
       pci_fill_info(p, PCI_FILL_LABEL);
 
       if (p->label)
         printf("\tDeviceName: %s", p->label);
-      get_subid(d, &subsys_v, &subsys_d);
-      if (subsys_v && subsys_v != 0xffff)
+      if ((p->known_fields & PCI_FILL_SUBSYS) &&
+         p->subsys_vendor_id && p->subsys_vendor_id != 0xffff)
        printf("\tSubsystem: %s\n",
                pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf),
                        PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
-                       p->vendor_id, p->device_id, subsys_v, subsys_d));
+                       p->vendor_id, p->device_id, p->subsys_vendor_id, p->subsys_id));
     }
 }
 
@@ -766,7 +746,7 @@ show_verbose(struct device *d)
 
   pci_fill_info(p, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES |
     PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE | PCI_FILL_IOMMU_GROUP |
-    PCI_FILL_BRIDGE_BASES);
+    PCI_FILL_BRIDGE_BASES | PCI_FILL_CLASS_EXT | PCI_FILL_SUBSYS);
   irq = p->irq;
 
   switch (htype)
@@ -947,13 +927,9 @@ static void
 show_machine(struct device *d)
 {
   struct pci_dev *p = d->dev;
-  int c;
-  word sv_id, sd_id;
   char classbuf[128], vendbuf[128], devbuf[128], svbuf[128], sdbuf[128];
   char *dt_node, *iommu_group;
 
-  get_subid(d, &sv_id, &sd_id);
-
   if (verbose)
     {
       pci_fill_info(p, PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE | PCI_FILL_IOMMU_GROUP);
@@ -966,19 +942,20 @@ show_machine(struct device *d)
             pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
       printf("Device:\t%s\n",
             pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
-      if (sv_id && sv_id != 0xffff)
+      if ((p->known_fields & PCI_FILL_SUBSYS) &&
+         p->subsys_vendor_id && p->subsys_vendor_id != 0xffff)
        {
          printf("SVendor:\t%s\n",
-                pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
+                pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, p->subsys_vendor_id));
          printf("SDevice:\t%s\n",
-                pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
+                pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, p->subsys_vendor_id, p->subsys_id));
        }
       if (p->phy_slot)
        printf("PhySlot:\t%s\n", p->phy_slot);
-      if (c = get_conf_byte(d, PCI_REVISION_ID))
-       printf("Rev:\t%02x\n", c);
-      if (c = get_conf_byte(d, PCI_CLASS_PROG))
-       printf("ProgIf:\t%02x\n", c);
+      if ((p->known_fields & PCI_FILL_CLASS_EXT) && p->rev_id)
+       printf("Rev:\t%02x\n", p->rev_id);
+      if (p->known_fields & PCI_FILL_CLASS_EXT)
+       printf("ProgIf:\t%02x\n", p->prog_if);
       if (opt_kernel)
        show_kernel_machine(d);
       if (p->numa_node != -1)
@@ -994,14 +971,15 @@ show_machine(struct device *d)
       print_shell_escaped(pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, p->device_class));
       print_shell_escaped(pci_lookup_name(pacc, vendbuf, sizeof(vendbuf), PCI_LOOKUP_VENDOR, p->vendor_id, p->device_id));
       print_shell_escaped(pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id));
-      if (c = get_conf_byte(d, PCI_REVISION_ID))
-       printf(" -r%02x", c);
-      if (c = get_conf_byte(d, PCI_CLASS_PROG))
-       printf(" -p%02x", c);
-      if (sv_id && sv_id != 0xffff)
+      if ((p->known_fields & PCI_FILL_CLASS_EXT) && p->rev_id)
+       printf(" -r%02x", p->rev_id);
+      if (p->known_fields & PCI_FILL_CLASS_EXT)
+       printf(" -p%02x", p->prog_if);
+      if ((p->known_fields & PCI_FILL_SUBSYS) &&
+         p->subsys_vendor_id && p->subsys_vendor_id != 0xffff)
        {
-         print_shell_escaped(pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, sv_id));
-         print_shell_escaped(pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, sv_id, sd_id));
+         print_shell_escaped(pci_lookup_name(pacc, svbuf, sizeof(svbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR, p->subsys_vendor_id));
+         print_shell_escaped(pci_lookup_name(pacc, sdbuf, sizeof(sdbuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id, p->subsys_vendor_id, p->subsys_id));
        }
       else
        printf(" \"\" \"\"");
diff --git a/lspci.h b/lspci.h
index 352177fcce7b327fc9fdb209f46a47f093a8ca6f..6e0bb2492fd532d11b4235a93982229b7c3ef5e1 100644 (file)
--- a/lspci.h
+++ b/lspci.h
@@ -55,8 +55,6 @@ u32 get_conf_long(struct device *d, unsigned int pos);
 word get_conf_word(struct device *d, unsigned int pos);
 byte get_conf_byte(struct device *d, unsigned int pos);
 
-void get_subid(struct device *d, word *subvp, word *subdp);
-
 /* Useful macros for decoding of bits and bit fields */
 
 #define FLAG(x,y) ((x & y) ? '+' : '-')