From 3c12c28f448fa76d17e9009995c89f56cccb0abb Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Tue, 5 Aug 2014 12:16:31 -0400
Subject: [PATCH] xfree86: Allow mixed fbdev and pci setups

You'd like to be able to do this because (for example) that way you'd be
able to drive both intel and udlfb at once.  There's no fundamental
reason why that can't work, so just delete the check in PostProbe that
forbids it.  Also in the fbdev driver, we're now actually passing the PCI
device in at init time, so we can look up the device node sanely.

That almost works!  Except then you break HyperV, because hyperv_fb
binds to the vmbus device, not the PCI device, because why the hell not.
So then the PCI probe path fails (because we try to find the fbdev node
under the PCI device tree, and fail), but the legacy probe path
succeeds; but then Init fails because we don't preserve that fd (or even
which /dev node we opened!), and since it _is_ a PCI device we try
fbdev_open_pci and that fails like it did during PCI probe.  "I know",
you think, "I'll just record the choice made at probe time", and then
you remember you have nowhere to hang it.

So, whatever.  If we make it to Init we know Probe succeeded one way or
the other, so just fall back from pci-style to handwave-style in Init
once if it seem appropriate.  And in all cases, use the explicit-device
open path even for PCI devices so that Option "fbdev" actually takes
effect.

I think this is the best you can do without breaking the Probe
interface, though admittedly burning this all to the ground is a noble
goal.

Signed-off-by: Adam Jackson <ajax@redhat.com>
---
 hw/xfree86/common/xf86Bus.c  | 15 ---------------
 hw/xfree86/fbdevhw/fbdevhw.c | 18 +++++++++++++++---
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 6bbf489..3186478 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -536,21 +536,6 @@ xf86GetDevFromEntity(int entityIndex, int instance)
 void
 xf86PostProbe(void)
 {
-    if (fbSlotClaimed && (
-#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
-                             sbusSlotClaimed ||
-#endif
-#ifdef XSERVER_PLATFORM_BUS
-                             platformSlotClaimed ||
-#endif
-#ifdef XSERVER_LIBPCIACCESS
-                             pciSlotClaimed
-#else
-                             TRUE
-#endif
-        ))
-        FatalError("Cannot run in framebuffer mode. Please specify busIDs "
-                   "       for all framebuffer devices\n");
 }
 
 int
diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 0bd77df..a2cf78f 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -351,7 +351,7 @@ fbdevHWProbe(struct pci_device *pPci, char *device, char **namep)
 {
     int fd;
 
-    if (pPci)
+    if (pPci && !device)
         fd = fbdev_open_pci(pPci, namep);
     else
         fd = fbdev_open(-1, device, namep);
@@ -365,16 +365,28 @@ fbdevHWProbe(struct pci_device *pPci, char *device, char **namep)
 Bool
 fbdevHWInit(ScrnInfoPtr pScrn, struct pci_device *pPci, char *device)
 {
+    static Bool been_here;
     fbdevHWPtr fPtr;
 
     fbdevHWGetRec(pScrn);
     fPtr = FBDEVHWPTR(pScrn);
 
     /* open device */
-    if (pPci)
+    if (pPci && !device)
         fPtr->fd = fbdev_open_pci(pPci, NULL);
     else
-        fPtr->fd = fbdev_open(pScrn->scrnIndex, device, NULL);
+	fPtr->fd = fbdev_open(pScrn->scrnIndex, device, NULL);
+
+    if (pPci && fPtr->fd == -1) {
+	if (been_here != serverGeneration) {
+	    fPtr->fd = fbdev_open(pScrn->scrnIndex, device, NULL);
+	    been_here = serverGeneration;
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Please specify Option \"fbdev\" to use this device\n");
+	}
+    }
+
     if (-1 == fPtr->fd) {
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "Failed to open framebuffer device, consult warnings"
-- 
2.17.0

