--- /dev/null
+From 86fd887b7fe350819dae5b55e7fef05b511c8656 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+Date: Sun, 24 Aug 2014 23:09:53 +0200
+Subject: vgaarb: Don't default exclusively to first video device with mem+io
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+
+commit 86fd887b7fe350819dae5b55e7fef05b511c8656 upstream.
+
+Commit 20cde694027e ("x86, ia64: Move EFI_FB vga_default_device()
+initialization to pci_vga_fixup()") moved boot video device detection from
+efifb to x86 and ia64 pci/fixup.c.
+
+For dual-GPU Apple computers above change represents a regression as code
+in efifb did forcefully override vga_default_device while the merge did not
+(vgaarb happens prior to PCI fixup).
+
+To improve on initial device selection by vgaarb (it cannot know if PCI
+device not behind bridges see/decode legacy VGA I/O or not), move the
+screen_info based check from pci_video_fixup() to vgaarb's init function and
+use it to refine/override decision taken while adding the individual PCI
+VGA devices. This way PCI fixup has no reason to adjust vga_default_device
+anymore but can depend on its value for flagging shadowed VBIOS.
+
+This has the nice benefit of removing duplicated code but does introduce a
+#if defined() block in vgaarb. Not all architectures have screen_info and
+would cause compile to fail without it.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=84461
+Reported-and-Tested-By: Andreas Noever <andreas.noever@gmail.com>
+Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+CC: Matthew Garrett <matthew.garrett@nebula.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/ia64/pci/fixup.c | 24 +-----------------------
+ arch/x86/pci/fixup.c | 24 +-----------------------
+ drivers/gpu/vga/vgaarb.c | 38 +++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 39 insertions(+), 47 deletions(-)
+
+--- a/arch/ia64/pci/fixup.c
++++ b/arch/ia64/pci/fixup.c
+@@ -38,27 +38,6 @@ static void pci_fixup_video(struct pci_d
+ return;
+ /* Maybe, this machine supports legacy memory map. */
+
+- if (!vga_default_device()) {
+- resource_size_t start, end;
+- int i;
+-
+- /* Does firmware framebuffer belong to us? */
+- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+- if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+- continue;
+-
+- start = pci_resource_start(pdev, i);
+- end = pci_resource_end(pdev, i);
+-
+- if (!start || !end)
+- continue;
+-
+- if (screen_info.lfb_base >= start &&
+- (screen_info.lfb_base + screen_info.lfb_size) < end)
+- vga_set_default_device(pdev);
+- }
+- }
+-
+ /* Is VGA routed to us? */
+ bus = pdev->bus;
+ while (bus) {
+@@ -83,8 +62,7 @@ static void pci_fixup_video(struct pci_d
+ pci_read_config_word(pdev, PCI_COMMAND, &config);
+ if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+- dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+- vga_set_default_device(pdev);
++ dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
+ }
+ }
+ }
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -326,27 +326,6 @@ static void pci_fixup_video(struct pci_d
+ struct pci_bus *bus;
+ u16 config;
+
+- if (!vga_default_device()) {
+- resource_size_t start, end;
+- int i;
+-
+- /* Does firmware framebuffer belong to us? */
+- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+- if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+- continue;
+-
+- start = pci_resource_start(pdev, i);
+- end = pci_resource_end(pdev, i);
+-
+- if (!start || !end)
+- continue;
+-
+- if (screen_info.lfb_base >= start &&
+- (screen_info.lfb_base + screen_info.lfb_size) < end)
+- vga_set_default_device(pdev);
+- }
+- }
+-
+ /* Is VGA routed to us? */
+ bus = pdev->bus;
+ while (bus) {
+@@ -371,8 +350,7 @@ static void pci_fixup_video(struct pci_d
+ pci_read_config_word(pdev, PCI_COMMAND, &config);
+ if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+- dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+- vga_set_default_device(pdev);
++ dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
+ }
+ }
+ }
+--- a/drivers/gpu/vga/vgaarb.c
++++ b/drivers/gpu/vga/vgaarb.c
+@@ -41,6 +41,7 @@
+ #include <linux/poll.h>
+ #include <linux/miscdevice.h>
+ #include <linux/slab.h>
++#include <linux/screen_info.h>
+
+ #include <linux/uaccess.h>
+
+@@ -580,8 +581,11 @@ static bool vga_arbiter_add_pci_device(s
+ */
+ #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
+ if (vga_default == NULL &&
+- ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
++ ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
++ pr_info("vgaarb: setting as boot device: PCI:%s\n",
++ pci_name(pdev));
+ vga_set_default_device(pdev);
++ }
+ #endif
+
+ vga_arbiter_check_bridge_sharing(vgadev);
+@@ -1316,6 +1320,38 @@ static int __init vga_arb_device_init(vo
+ pr_info("vgaarb: loaded\n");
+
+ list_for_each_entry(vgadev, &vga_list, list) {
++#if defined(CONFIG_X86) || defined(CONFIG_IA64)
++ /* Override I/O based detection done by vga_arbiter_add_pci_device()
++ * as it may take the wrong device (e.g. on Apple system under EFI).
++ *
++ * Select the device owning the boot framebuffer if there is one.
++ */
++ resource_size_t start, end;
++ int i;
++
++ /* Does firmware framebuffer belong to us? */
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ if (!(pci_resource_flags(vgadev->pdev, i) & IORESOURCE_MEM))
++ continue;
++
++ start = pci_resource_start(vgadev->pdev, i);
++ end = pci_resource_end(vgadev->pdev, i);
++
++ if (!start || !end)
++ continue;
++
++ if (screen_info.lfb_base < start ||
++ (screen_info.lfb_base + screen_info.lfb_size) >= end)
++ continue;
++ if (!vga_default_device())
++ pr_info("vgaarb: setting as boot device: PCI:%s\n",
++ pci_name(vgadev->pdev));
++ else if (vgadev->pdev != vga_default_device())
++ pr_info("vgaarb: overriding boot device: PCI:%s\n",
++ pci_name(vgadev->pdev));
++ vga_set_default_device(vgadev->pdev);
++ }
++#endif
+ if (vgadev->bridge_has_one_vga)
+ pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev));
+ else
--- /dev/null
+From 20cde694027e7477cc532833e38ab9fcaa83fb64 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+Date: Wed, 25 Jun 2014 00:55:01 +0200
+Subject: x86, ia64: Move EFI_FB vga_default_device() initialization to pci_vga_fixup()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org>
+
+commit 20cde694027e7477cc532833e38ab9fcaa83fb64 upstream.
+
+Commit b4aa0163056b ("efifb: Implement vga_default_device() (v2)") added
+efifb vga_default_device() so EFI systems that do not load shadow VBIOS or
+setup VGA get proper value for boot_vga PCI sysfs attribute on the
+corresponding PCI device.
+
+Xorg doesn't detect devices when boot_vga=0, e.g., on some EFI systems such
+as MacBookAir2,1. Xorg detects the GPU and finds the DRI device but then
+bails out with "no devices detected".
+
+Note: When vga_default_device() is set boot_vga PCI sysfs attribute
+reflects its state. When unset this attribute is 1 whenever
+IORESOURCE_ROM_SHADOW flag is set.
+
+With introduction of sysfb/simplefb/simpledrm efifb is getting obsolete
+while having native drivers for the GPU also makes selecting sysfb/efifb
+optional.
+
+Remove the efifb implementation of vga_default_device() and initialize
+vgaarb's vga_default_device() with the PCI GPU that matches boot
+screen_info in pci_fixup_video().
+
+[bhelgaas: remove unused "dev" in efifb_setup()]
+Fixes: b4aa0163056b ("efifb: Implement vga_default_device() (v2)")
+Tested-by: Anibal Francisco Martinez Cortina <linuxkid.zeuz@gmail.com>
+Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Matthew Garrett <matthew.garrett@nebula.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/ia64/pci/fixup.c | 22 ++++++++++++++++++++++
+ arch/x86/include/asm/vga.h | 6 ------
+ arch/x86/pci/fixup.c | 21 +++++++++++++++++++++
+ drivers/video/fbdev/efifb.c | 39 ---------------------------------------
+ 4 files changed, 43 insertions(+), 45 deletions(-)
+
+--- a/arch/ia64/pci/fixup.c
++++ b/arch/ia64/pci/fixup.c
+@@ -6,6 +6,7 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/vgaarb.h>
++#include <linux/screen_info.h>
+
+ #include <asm/machvec.h>
+
+@@ -37,6 +38,27 @@ static void pci_fixup_video(struct pci_d
+ return;
+ /* Maybe, this machine supports legacy memory map. */
+
++ if (!vga_default_device()) {
++ resource_size_t start, end;
++ int i;
++
++ /* Does firmware framebuffer belong to us? */
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
++ continue;
++
++ start = pci_resource_start(pdev, i);
++ end = pci_resource_end(pdev, i);
++
++ if (!start || !end)
++ continue;
++
++ if (screen_info.lfb_base >= start &&
++ (screen_info.lfb_base + screen_info.lfb_size) < end)
++ vga_set_default_device(pdev);
++ }
++ }
++
+ /* Is VGA routed to us? */
+ bus = pdev->bus;
+ while (bus) {
+--- a/arch/x86/include/asm/vga.h
++++ b/arch/x86/include/asm/vga.h
+@@ -17,10 +17,4 @@
+ #define vga_readb(x) (*(x))
+ #define vga_writeb(x, y) (*(y) = (x))
+
+-#ifdef CONFIG_FB_EFI
+-#define __ARCH_HAS_VGA_DEFAULT_DEVICE
+-extern struct pci_dev *vga_default_device(void);
+-extern void vga_set_default_device(struct pci_dev *pdev);
+-#endif
+-
+ #endif /* _ASM_X86_VGA_H */
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -326,6 +326,27 @@ static void pci_fixup_video(struct pci_d
+ struct pci_bus *bus;
+ u16 config;
+
++ if (!vga_default_device()) {
++ resource_size_t start, end;
++ int i;
++
++ /* Does firmware framebuffer belong to us? */
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
++ continue;
++
++ start = pci_resource_start(pdev, i);
++ end = pci_resource_end(pdev, i);
++
++ if (!start || !end)
++ continue;
++
++ if (screen_info.lfb_base >= start &&
++ (screen_info.lfb_base + screen_info.lfb_size) < end)
++ vga_set_default_device(pdev);
++ }
++ }
++
+ /* Is VGA routed to us? */
+ bus = pdev->bus;
+ while (bus) {
+--- a/drivers/video/fbdev/efifb.c
++++ b/drivers/video/fbdev/efifb.c
+@@ -19,8 +19,6 @@
+
+ static bool request_mem_succeeded = false;
+
+-static struct pci_dev *default_vga;
+-
+ static struct fb_var_screeninfo efifb_defined = {
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+@@ -84,23 +82,10 @@ static struct fb_ops efifb_ops = {
+ .fb_imageblit = cfb_imageblit,
+ };
+
+-struct pci_dev *vga_default_device(void)
+-{
+- return default_vga;
+-}
+-
+-EXPORT_SYMBOL_GPL(vga_default_device);
+-
+-void vga_set_default_device(struct pci_dev *pdev)
+-{
+- default_vga = pdev;
+-}
+-
+ static int efifb_setup(char *options)
+ {
+ char *this_opt;
+ int i;
+- struct pci_dev *dev = NULL;
+
+ if (options && *options) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+@@ -126,30 +111,6 @@ static int efifb_setup(char *options)
+ }
+ }
+
+- for_each_pci_dev(dev) {
+- int i;
+-
+- if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+- continue;
+-
+- for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
+- resource_size_t start, end;
+-
+- if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
+- continue;
+-
+- start = pci_resource_start(dev, i);
+- end = pci_resource_end(dev, i);
+-
+- if (!start || !end)
+- continue;
+-
+- if (screen_info.lfb_base >= start &&
+- (screen_info.lfb_base + screen_info.lfb_size) < end)
+- default_vga = dev;
+- }
+- }
+-
+ return 0;
+ }
+