Blob Blame History Raw
From 39f73e813f7d404498629f6104a9003d092af28d Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Tue, 8 May 2012 13:01:12 +0100
Subject: [PATCH] xf86/pci: fix slot claiming counting.

Currently if we claim a slot for a PCI driver, we never let it go properly,
this prevents the fallback probe from reusing the slot, even though it
isn't claimed for that pci slot.

So if you set the modesetting driver to point at a specific kms device,
that isn't a PCI device (i.e. USB dongle), then the modesetting driver
loads, the pci probe tries to bind the config slot to the primary PCI
device, however we then check the kms device bus id to discover it
isn't valid. However we don't remove the claim on the slot. Next the
old probe function is called and there is no slots to claim.

This patch fixes that and converts the pciSlotClaimed boolean into
a counter, and changes the unclaim api to take a device pointer
to remove from the entity.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 hw/xfree86/common/xf86.h       |    4 ++--
 hw/xfree86/common/xf86Bus.c    |   20 ++++++++++++++++++++
 hw/xfree86/common/xf86Priv.h   |    1 +
 hw/xfree86/common/xf86pciBus.c |   10 ++++++----
 4 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index fc4c34e..e6d41d6 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -97,12 +97,12 @@ extern _X_EXPORT Bool VTSwitchEnabled;  /* kbd driver */
 /* PCI related */
 #ifdef XSERVER_LIBPCIACCESS
 #include <pciaccess.h>
-extern _X_EXPORT Bool pciSlotClaimed;
+extern _X_EXPORT int pciSlotClaimed;
 
 extern _X_EXPORT Bool xf86CheckPciSlot(const struct pci_device *);
 extern _X_EXPORT int xf86ClaimPciSlot(struct pci_device *, DriverPtr drvp,
                                       int chipset, GDevPtr dev, Bool active);
-extern _X_EXPORT void xf86UnclaimPciSlot(struct pci_device *);
+extern _X_EXPORT void xf86UnclaimPciSlot(struct pci_device *, GDevPtr dev);
 extern _X_EXPORT Bool xf86ParsePciBusString(const char *busID, int *bus,
                                             int *device, int *func);
 extern _X_EXPORT Bool xf86ComparePciBusString(const char *busID, int bus,
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index b176e8c..b876434 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -420,6 +420,26 @@ xf86AddDevToEntity(int entityIndex, GDevPtr dev)
     dev->claimed = TRUE;
 }
 
+
+void
+xf86RemoveDevFromEntity(int entityIndex, GDevPtr dev)
+{
+    EntityPtr pEnt;
+    int i, j;
+    if (entityIndex >= xf86NumEntities)
+        return;
+
+    pEnt = xf86Entities[entityIndex];
+    for (i = 0; i < pEnt->numInstances; i++) {
+        if (pEnt->devices[i] == dev) {
+            for (j = i; j < pEnt->numInstances - 1; j++)
+                pEnt->devices[j] = pEnt->devices[j + 1];
+            break;
+        }
+    }
+    pEnt->numInstances--;
+    dev->claimed = FALSE;
+}
 /*
  * xf86GetEntityInfo() -- This function hands information from the
  * EntityRec struct to the drivers. The EntityRec structure itself
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 8d9cb55..6c5efea 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -116,6 +116,7 @@ extern _X_EXPORT void xf86AccessLeave(void);
 extern _X_EXPORT void xf86PostProbe(void);
 extern _X_EXPORT void xf86ClearEntityListForScreen(int scrnIndex);
 extern _X_EXPORT void xf86AddDevToEntity(int entityIndex, GDevPtr dev);
+extern _X_EXPORT void xf86RemoveDevFromEntity(int entityIndex, GDevPtr dev);
 
 /* xf86Config.c */
 
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
index e52f1da..d758260 100644
--- a/hw/xfree86/common/xf86pciBus.c
+++ b/hw/xfree86/common/xf86pciBus.c
@@ -52,7 +52,7 @@
 #define PCI_VENDOR_GENERIC		0x00FF
 
 /* Bus-specific globals */
-Bool pciSlotClaimed = FALSE;
+int pciSlotClaimed = 0;
 
 #define PCIINFOCLASSES(c) \
     ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \
@@ -223,7 +223,7 @@ xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
         p->inUse = FALSE;
         if (dev)
             xf86AddDevToEntity(num, dev);
-        pciSlotClaimed = TRUE;
+        pciSlotClaimed++;
 
         return num;
     }
@@ -235,7 +235,7 @@ xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
  * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim.
  */
 void
-xf86UnclaimPciSlot(struct pci_device *d)
+xf86UnclaimPciSlot(struct pci_device *d, GDevPtr dev)
 {
     int i;
 
@@ -244,6 +244,8 @@ xf86UnclaimPciSlot(struct pci_device *d)
 
         if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
             /* Probably the slot should be deallocated? */
+            xf86RemoveDevFromEntity(i, dev);
+            pciSlotClaimed--;
             p->bus.type = BUS_NONE;
             return;
         }
@@ -537,7 +539,7 @@ xf86PciProbeDev(DriverPtr drvp)
                         foundScreen = TRUE;
                     }
                     else
-                        xf86UnclaimPciSlot(pPci);
+                        xf86UnclaimPciSlot(pPci, devList[i]);
                 }
 
                 break;
-- 
1.7.7.6