Skip to contentSkip to conversation

Handle multi-GPU EFI systems better

PATCH Superseded Matthew Garrett 1 participant 5 messages Mar 23, 2012

Subsystems (6)
DRM drivers x86 DRM misc PCI +2 more subsystems

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

Right now we assume that the GPU with the legacy VGA routing is the active video device. This holds for BIOS systems, but falls down quite badly on EFI-based systems. This patchset adds support for cleaning that up and has been confirmed to work on an Apple machine with dual GPUs.

Signature · 1 line
Matthew Garrett | [email protected]
#1 lore raw

PATCH 1/4 vgaarb: Add support for setting the default video device

The default VGA device is a somewhat fluid concept on platforms with multiple GPUs. Add support for setting it so switching code can update things appropriately, and make sure that the sysfs code returns the right device if it's changed.

---
 drivers/gpu/vga/vgaarb.c |    7 +++++++
 drivers/pci/pci-sysfs.c  |    5 +++++
 include/linux/vgaarb.h   |    3 +++
 3 files changed, 15 insertions(+), 0 deletions(-)
drivers/gpu/vga/vgaarb.c +7 -0
index 111d956..e223b96 100644
@@ -136,6 +136,11 @@ struct pci_dev *vga_default_device(void)
 {
 	return vga_default;
 }
+
+void vga_set_default_device(struct pci_dev *pdev)
+{
+	vga_default = pdev;
+}
 #endif
 
 static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
@@ -605,10 +610,12 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
 		goto bail;
 	}
 
+#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == pdev) {
 		pci_dev_put(vga_default);
 		vga_default = NULL;
 	}
+#endif
 
 	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
 		vga_decode_count--;
drivers/pci/pci-sysfs.c +5 -0
index a3cd8ca..7dd9f2b 100644
@@ -27,6 +27,7 @@
 #include <linux/security.h>
 #include <linux/pci-aspm.h>
 #include <linux/slab.h>
+#include <linux/vgaarb.h>
 #include "pci.h"
 
 static int sysfs_initialized;	/* = 0 */
@@ -414,6 +415,10 @@ static ssize_t
 boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pci_dev *vga_dev = vga_default_device();
+
+	if (vga_dev)
+		return sprintf(buf, "%u\n", (pdev == vga_dev));
 
 	return sprintf(buf, "%u\n",
 		!!(pdev->resource[PCI_ROM_RESOURCE].flags &
include/linux/vgaarb.h +3 -0
index 9c3120d..7ad7f2a 100644
@@ -31,6 +31,7 @@
 #ifndef LINUX_VGA_H
 #define LINUX_VGA_H
 
+#include <video/vga.h>
 
 /* Legacy VGA regions */
 #define VGA_RSRC_NONE	       0x00
@@ -177,10 +178,12 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
  *     I suppose it's a matter of having the proper arch hook telling
  *     us about it, so we basically never allow anybody to succeed a
  *     vga_get()...
+ *
  */
 
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 extern struct pci_dev *vga_default_device(void);
+extern void vga_set_default_device(struct pci_dev *pdev)
 #endif
 
 /**
Signature · 1 line
1.7.7.6
#2 lore raw

PATCH 2/4 vga-switcheroo: Use vga_default_device()

In reply to Matthew Garrett

vga-switcheroo currently changes the default VGA device by fiddling with the IORESOURCE_ROM_SHADOW flag on the device. This isn't strictly accurate, since there's no guarantee that switching also changes the ROM decoding. Switch over to using the vgaarb functions for this.

---
 drivers/gpu/vga/vga_switcheroo.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)
drivers/gpu/vga/vga_switcheroo.c +5 -4
index 9a2c805..44c664e 100644
@@ -28,6 +28,8 @@
 #include <linux/pci.h>
 #include <linux/vga_switcheroo.h>
 
+#include <linux/vgaarb.h>
+
 struct vga_switcheroo_client {
 	struct pci_dev *pdev;
 	struct fb_info *fb_info;
@@ -140,7 +142,7 @@ int vga_switcheroo_register_client(struct pci_dev *pdev,
 	vgasr_priv.clients[index].reprobe = reprobe;
 	vgasr_priv.clients[index].can_switch = can_switch;
 	vgasr_priv.clients[index].id = -1;
-	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+	if (pdev == vga_default_device())
 		vgasr_priv.clients[index].active = true;
 
 	vgasr_priv.registered_clients |= (1 << index);
@@ -248,9 +250,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 	if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
 		vga_switchon(new_client);
 
-	/* swap shadow resource to denote boot VGA device has changed so X starts on new device */
-	active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
-	new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+	vga_set_default_device(new_client->pdev);
+
 	return 0;
 }
 
Signature · 1 line
1.7.7.6
#3 lore raw

PATCH 3/4 x86: Use vga_default_device() when determining whether an fb is primary

In reply to Matthew Garrett

IORESOURCE_ROM_SHADOW is not necessarily an indication that the hardware is the primary device. Add support for using the vgaarb functions and fall back if nothing's set them.

---
 arch/x86/video/fbdev.c |   20 +++++++++++++++-----
 1 files changed, 15 insertions(+), 5 deletions(-)
arch/x86/video/fbdev.c +15 -5
index c5ffb6a..d5644bb 100644
@@ -9,24 +9,34 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/vgaarb.h>
 
 int fb_is_primary_device(struct fb_info *info)
 {
 	struct device *device = info->device;
 	struct pci_dev *pci_dev = NULL;
+	struct pci_dev *default_device = vga_default_device();
 	struct resource *res = NULL;
-	int retval = 0;
 
 	if (device)
 		pci_dev = to_pci_dev(device);
 
-	if (pci_dev)
-		res = &pci_dev->resource[PCI_ROM_RESOURCE];
+	if (!pci_dev)
+		return 0;
+
+	if (default_device) {
+		if (pci_dev == default_device)
+			return 1;
+		else
+			return 0;
+	}
+
+	res = &pci_dev->resource[PCI_ROM_RESOURCE];
 
 	if (res && res->flags & IORESOURCE_ROM_SHADOW)
-		retval = 1;
+		return 1;
 
-	return retval;
+	return 0;
 }
 EXPORT_SYMBOL(fb_is_primary_device);
 MODULE_LICENSE("GPL");
Signature · 1 line
1.7.7.6
#4 lore raw

PATCH 4/4 efifb: Implement vga_default_device()

In reply to Matthew Garrett

EFI doesn't typically make use of the legacy VGA ROM, but it may still be configured to pass that through to a given video device. This may lead to an inaccurate choice of default video device. Add support to efifb to pick out the correct active video device.

---
 arch/x86/include/asm/vga.h |    6 +++
 drivers/video/efifb.c      |   77 ++++++++++++++++++++++++++++++++-----------
 2 files changed, 63 insertions(+), 20 deletions(-)
arch/x86/include/asm/vga.h +6 -0
index c4b9dc2..2723c07 100644
@@ -17,4 +17,10 @@
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))
 
+#if 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 */
drivers/video/efifb.c +57 -20

98 lines not on this page · raw message

Signature · 1 line
1.7.7.6