x86: Fix pci_match_tbdf()
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 27 Mar 2014 22:37:04 +0000 (15:37 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 29 Mar 2014 01:17:05 +0000 (18:17 -0700)
And made it a PCI helper.  Also, bails out for all PCI devices when
match_tbdf fails.

Right now, the MSI enable mucks with my rtl8169 and attempting to
msi_enable() breaks the IRQ routing.

kern/arch/x86/ioapic.c
kern/arch/x86/pci.c
kern/arch/x86/pci.h

index 4032157..a5e7e9a 100644 (file)
@@ -380,30 +380,12 @@ int nextvec(void)
        return vecno;
 }
 
-static struct pci_device *pcimatchtbdf(int tbdf)
-{
-       /* don't we have macros for this somewhere? */
-       int bus, dev, func;
-       bus = tbdf >> 16;
-       dev = (tbdf>>11)&0x1f;
-       func = (tbdf>>8)&3;
-
-       struct pci_device *search;
-       STAILQ_FOREACH(search, &pci_devices, all_dev) {
-               if ((search->bus == bus) &&
-                   (search->dev == dev) &&
-                   (search->func == func))
-                       return search;
-       }
-       return NULL;
-}
-
 static int msimask(struct vkey *v, int mask)
 {
        int pcimsimask(struct pci_device *p, int mask);
 
        struct pci_device *p;
-       p = pcimatchtbdf(v->tbdf);
+       p = pci_match_tbdf(v->tbdf);
        if (p == NULL)
                return -1;
        return pcimsimask(p, mask);
@@ -537,8 +519,7 @@ int bus_irq_setup(struct irq_handler *irq_h)
        struct Rbus *rbus;
        struct Rdt *rdt;
        int busno, devno, vecno;
-       struct pci_device pcidev;
-       struct pci_device *msidev;
+       struct pci_device *pcidev;
 
        if (!ioapic_exists()) {
                switch (BUSTYPE(irq_h->tbdf)) {
@@ -588,19 +569,17 @@ int bus_irq_setup(struct irq_handler *irq_h)
                        devno = irq_h->dev_irq << 2;
                        break;
                case BusPCI:
-                       /* TODO: we'll assume it's there.  (fix when adding MSI) */
-
-                       /* temp disable MSI til we get ACPI and such sorted */
-                       if ((msidev = pcimatchtbdf(irq_h->tbdf)) == NULL) {
-                               printk("no PCI dev for tbdf %p", irq_h->tbdf);
-                       } else {
-                               if ((vecno = intrenablemsi(irq_h, msidev)) != -1)
-                                       return vecno;
-                               disablemsi(irq_h, msidev);
+                       pcidev = pci_match_tbdf(irq_h->tbdf);
+                       if (!pcidev) {
+                               printk("No PCI dev for tbdf %p!", irq_h->tbdf);
+                               return -1;
                        }
+                       if ((vecno = intrenablemsi(irq_h, pcidev)) != -1)
+                               return vecno;
+                       disablemsi(irq_h, pcidev);
                        busno = BUSBNO(irq_h->tbdf);
-                       explode_tbdf(irq_h->tbdf);
-                       devno = pcidev_read8(&pcidev, PciINTP);
+                       assert(busno == pcidev->bus);
+                       devno = pcidev_read8(pcidev, PciINTP);
 
                        /* this might not be a big deal - some PCI devices have no INTP.  if
                         * so, change our devno - 1 below. */
index 207527a..b5a99f1 100644 (file)
@@ -399,3 +399,20 @@ void pci_clr_bus_master(struct pci_device *pcidev)
        reg &= ~PCI_CMD_BUS_MAS;
        pcidev_write16(pcidev, PCI_CMD_REG, reg);
 }
+
+struct pci_device *pci_match_tbdf(int tbdf)
+{
+       struct pci_device *search;
+       int bus, dev, func;
+       bus = BUSBNO(tbdf);
+       dev = BUSDNO(tbdf);
+       func = BUSFNO(tbdf);
+
+       STAILQ_FOREACH(search, &pci_devices, all_dev) {
+               if ((search->bus == bus) &&
+                   (search->dev == dev) &&
+                   (search->func == func))
+                       return search;
+       }
+       return NULL;
+}
index a994616..c6d1cd3 100644 (file)
@@ -392,6 +392,7 @@ uint32_t pci_getiobar32(uint32_t bar);
 /* Other common PCI functions */
 void pci_set_bus_master(struct pci_device *pcidev);
 void pci_clr_bus_master(struct pci_device *pcidev);
+struct pci_device *pci_match_tbdf(int tbdf);
 
 /* TODO: this is quite the Hacke */
 #define explode_tbdf(tbdf) {pcidev.bus = tbdf >> 16;\