@@ -5,7 +5,7 @@
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
#include <linux/screen_info.h>
#include <asm/machvec.h>
@@ -22,7 +22,7 @@
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device
- * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * with IORESOURCE_ROM_SHADOW check if a pci_default_display is already set
* by either arch code or vga-arbitration; if so only apply the fixup to this
* already-determined primary video card.
*/
@@ -59,7 +59,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
}
bus = bus->parent;
}
- if (!vga_default_device() || pdev == vga_default_device()) {
+ if (!pci_default_display() || pdev == pci_default_display()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
res = &pdev->resource[PCI_ROM_RESOURCE];
@@ -31,7 +31,7 @@
#include <linux/irq.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -1747,8 +1747,8 @@ static void fixup_vga(struct pci_dev *pdev)
u16 cmd;
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- if ((cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) || !vga_default_device())
- vga_set_default_device(pdev);
+ if ((cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) || !pci_default_display())
+ pci_set_default_display(pdev);
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
@@ -5,7 +5,7 @@
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
#include <asm/hpet.h>
#include <asm/pci_x86.h>
@@ -302,7 +302,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device
- * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * with IORESOURCE_ROM_SHADOW check if a pci_default_display is already set
* by either arch code or vga-arbitration; if so only apply the fixup to this
* already-determined primary video card.
*/
@@ -334,7 +334,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
}
bus = bus->parent;
}
- if (!vga_default_device() || pdev == vga_default_device()) {
+ if (!pci_default_display() || pdev == pci_default_display()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
res = &pdev->resource[PCI_ROM_RESOURCE];
@@ -9,12 +9,12 @@
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/module.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
int fb_is_primary_device(struct fb_info *info)
{
struct device *device = info->device;
- struct pci_dev *default_device = vga_default_device();
+ struct pci_dev *default_device = pci_default_display();
struct pci_dev *pci_dev;
struct resource *res;
@@ -1,3 +1,14 @@
+config DEFAULT_DISPLAY
+ bool "Default Display Device Support" if EXPERT
+ default y
+ depends on PCI
+ help
+ Some programs find it helpful to know what PCI display device is the
+ default. On platforms like x86 this means the device used by the BIOS
+ to show early boot messages. On other platforms this may be an arbitrary
+ PCI graphics card. Select this to have a default device recorded within
+ the kernel and exposed to userspace through sysfs.
+
config VGA_ARB
bool "VGA Arbitration" if EXPERT
default y
@@ -22,6 +33,7 @@ config VGA_SWITCHEROO
depends on X86
depends on ACPI
select VGA_ARB
+ select DEFAULT_DISPLAY
help
Many laptops released in 2008/9/10 have two GPUs with a multiplexer
to switch between them. This adds support for dynamic switching when
@@ -1,2 +1,3 @@
obj-$(CONFIG_VGA_ARB) += vgaarb.o
+obj-$(CONFIG_DEFAULT_DISPLAY) += default_display.o
obj-$(CONFIG_VGA_SWITCHEROO) += vga_switcheroo.o
new file mode 100644
@@ -0,0 +1,86 @@
+/*
+ * default_display.c: What is the default/boot PCI VGA device?
+ *
+ * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
+ * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
+ * (C) Copyright 2017 Canonical Ltd. (Author: Daniel Axtens <dja@axtens.net>)
+ *
+ * (License from vgaarb.c)
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/**
+ * DOC: overview
+ *
+ * What device should a graphics system draw to?
+ *
+ * It is helpful to have a concept of a default or boot device (for
+ * example, for autoconfiguration where there is no device speficied
+ * by the user). That should be:
+ *
+ * 1) If the platform has a concept of a boot device for early boot
+ * messages (think BIOS displays on x86), that device.
+ *
+ * 2) Anything specified by an arch hook,
+ * e.g. arch/powerpc/kernel/pci-common.c::fixup_vga()
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <linux/default_display.h>
+
+static struct pci_dev *vga_default;
+
+/**
+ * pci_default_display - return the default display device
+ *
+ * This represents the default or boot device.
+ *
+ * The default implementation is rather dumb and will probably only
+ * work properly on single vga card setups and/or x86 platforms.
+ */
+struct pci_dev *pci_default_display(void)
+{
+ return vga_default;
+}
+EXPORT_SYMBOL_GPL(pci_default_display);
+
+/**
+ * pci_set_default_display - set the default display device
+ * @pdev: pci device to set as default
+ *
+ * Idempotent - safe to call with the same device repeatedly.
+ *
+ * Drops a reference to the old default, if applicable. Takes a
+ * reference to the new device.
+ */
+void pci_set_default_display(struct pci_dev *pdev)
+{
+ if (vga_default == pdev)
+ return;
+
+ pci_dev_put(vga_default);
+ vga_default = pci_dev_get(pdev);
+}
@@ -41,7 +41,7 @@
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
#include <linux/vga_switcheroo.h>
/**
@@ -320,7 +320,7 @@ int vga_switcheroo_register_client(struct pci_dev *pdev,
bool driver_power_control)
{
return register_client(pdev, ops, VGA_SWITCHEROO_UNKNOWN_ID,
- pdev == vga_default_device(),
+ pdev == pci_default_display(),
driver_power_control);
}
EXPORT_SYMBOL(vga_switcheroo_register_client);
@@ -397,7 +397,7 @@ bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)
* apple-gmux is needed on pre-retina MacBook Pro
* to probe the panel if pdev is the inactive GPU.
*/
- if (apple_gmux_present() && pdev != vga_default_device() &&
+ if (apple_gmux_present() && pdev != pci_default_display() &&
!vgasr_priv.handler_flags)
return true;
}
@@ -659,7 +659,7 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
vga_switchon(new_client);
- vga_set_default_device(new_client->pdev);
+ pci_set_default_display(new_client->pdev);
return 0;
}
@@ -51,6 +51,7 @@
#include <linux/uaccess.h>
+#include <linux/default_display.h>
#include <linux/vgaarb.h>
static void vga_arbiter_notify_clients(void);
@@ -119,9 +120,6 @@ static int vga_str_to_iostate(char *buf, int str_size, int *io_state)
return 1;
}
-/* this is only used a cookie - it should not be dereferenced */
-static struct pci_dev *vga_default;
-
static void vga_arb_device_card_gone(struct pci_dev *pdev);
/* Find somebody in our list */
@@ -135,39 +133,6 @@ static struct vga_device *vgadev_find(struct pci_dev *pdev)
return NULL;
}
-/**
- * vga_default_device - return the default VGA device, for vgacon
- *
- * This can be defined by the platform. The default implementation
- * is rather dumb and will probably only work properly on single
- * vga card setups and/or x86 platforms.
- *
- * If your VGA default device is not PCI, you'll have to return
- * NULL here. In this case, I assume it will not conflict with
- * any PCI card. If this is not true, I'll have to define two archs
- * hooks for enabling/disabling the VGA default device if that is
- * possible. This may be a problem with real _ISA_ VGA cards, in
- * addition to a PCI one. I don't know at this point how to deal
- * with that card. Can theirs IOs be disabled at all ? If not, then
- * 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()...
- */
-struct pci_dev *vga_default_device(void)
-{
- return vga_default;
-}
-EXPORT_SYMBOL_GPL(vga_default_device);
-
-void vga_set_default_device(struct pci_dev *pdev)
-{
- if (vga_default == pdev)
- return;
-
- pci_dev_put(vga_default);
- vga_default = pci_dev_get(pdev);
-}
-
static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
{
if (vgadev->irq_set_state)
@@ -423,7 +388,7 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
vga_check_first_use();
/* The one who calls us should check for this, but lets be sure... */
if (pdev == NULL)
- pdev = vga_default_device();
+ pdev = pci_default_display();
if (pdev == NULL)
return 0;
@@ -490,7 +455,7 @@ int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
/* The one who calls us should check for this, but lets be sure... */
if (pdev == NULL)
- pdev = vga_default_device();
+ pdev = pci_default_display();
if (pdev == NULL)
return 0;
spin_lock_irqsave(&vga_lock, flags);
@@ -524,7 +489,7 @@ void vga_put(struct pci_dev *pdev, unsigned int rsrc)
/* The one who calls us should check for this, but lets be sure... */
if (pdev == NULL)
- pdev = vga_default_device();
+ pdev = pci_default_display();
if (pdev == NULL)
return;
spin_lock_irqsave(&vga_lock, flags);
@@ -667,10 +632,10 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
/* Deal with VGA default device. Use first enabled one
* by default if arch doesn't have it's own hook
*/
- if (vga_default == NULL &&
+ if (pci_default_display() == NULL &&
((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
- vga_set_default_device(pdev);
+ pci_set_default_display(pdev);
}
vga_arbiter_check_bridge_sharing(vgadev);
@@ -704,8 +669,8 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
goto bail;
}
- if (vga_default == pdev)
- vga_set_default_device(NULL);
+ if (pci_default_display() == pdev)
+ pci_set_default_display(NULL);
if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
vga_decode_count--;
@@ -1182,7 +1147,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
pr_debug("client 0x%p called 'target'\n", priv);
/* if target is default */
if (!strncmp(curr_pos, "default", 7))
- pdev = pci_dev_get(vga_default_device());
+ pdev = pci_dev_get(pci_default_display());
else {
if (!vga_pci_str_to_vars(curr_pos, remaining,
&domain, &bus, &devfn)) {
@@ -1292,7 +1257,7 @@ static int vga_arb_open(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&vga_user_lock, flags);
/* Set the client' lists of locks */
- priv->target = vga_default_device(); /* Maybe this is still null! */
+ priv->target = pci_default_display(); /* Maybe this is still null! */
priv->cards[0].pdev = priv->target;
priv->cards[0].io_cnt = 0;
priv->cards[0].mem_cnt = 0;
@@ -1455,11 +1420,11 @@ static int __init vga_arb_device_init(void)
if (screen_info.lfb_base < start || limit >= end)
continue;
- if (!vga_default_device())
+ if (!pci_default_display())
vgaarb_info(dev, "setting as boot device\n");
- else if (vgadev->pdev != vga_default_device())
+ else if (vgadev->pdev != pci_default_display())
vgaarb_info(dev, "overriding boot device\n");
- vga_set_default_device(vgadev->pdev);
+ pci_set_default_display(vgadev->pdev);
}
#endif
if (vgadev->bridge_has_one_vga)
@@ -27,7 +27,7 @@
#include <linux/security.h>
#include <linux/pci-aspm.h>
#include <linux/slab.h>
-#include <linux/vgaarb.h>
+#include <linux/default_display.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include "pci.h"
@@ -785,7 +785,7 @@ 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();
+ struct pci_dev *vga_dev = pci_default_display();
if (vga_dev)
return sprintf(buf, "%u\n", (pdev == vga_dev));
new file mode 100644
@@ -0,0 +1,44 @@
+/*
+ * default_display.h: What is the default/boot PCI VGA device?
+ *
+ * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
+ * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
+ * (C) Copyright 2017 Canonical Ltd. (Author: Daniel Axtens <dja@axtens.net>)
+ *
+ * (License from vgaarb.h)
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef LINUX_DEFAULT_DISPLAY_H
+#define LINUX_DEFAULT_DISPLAY_H
+
+struct pci_dev;
+
+#ifdef CONFIG_DEFAULT_DISPLAY
+extern struct pci_dev *pci_default_display(void);
+extern void pci_set_default_display(struct pci_dev *pdev);
+#else
+static inline struct pci_dev *pci_default_display(void) { return NULL; };
+static inline void pci_set_default_display(struct pci_dev *pdev) { };
+#endif
+
+#endif
@@ -42,12 +42,6 @@
#define VGA_RSRC_NORMAL_IO 0x04
#define VGA_RSRC_NORMAL_MEM 0x08
-/* Passing that instead of a pci_dev to use the system "default"
- * device, that is the one used by vgacon. Archs will probably
- * have to provide their own vga_default_device();
- */
-#define VGA_DEFAULT_DEVICE (NULL)
-
struct pci_dev;
/* For use by clients */
@@ -121,15 +115,6 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
#define vga_put(pdev, rsrc)
#endif
-
-#ifdef CONFIG_VGA_ARB
-extern struct pci_dev *vga_default_device(void);
-extern void vga_set_default_device(struct pci_dev *pdev);
-#else
-static inline struct pci_dev *vga_default_device(void) { return NULL; };
-static inline void vga_set_default_device(struct pci_dev *pdev) { };
-#endif
-
/*
* Architectures should define this if they have several
* independent PCI domains that can afford concurrent VGA
Split the small bit of code that does default VGA handling out from the arbiter. Add a Kconfig option to allow the kernel to be built with just the default handling, or the arbiter and default handling. While doing this, rename the functions from vga_(set_)default_device to pci_(set_)default_display. This makes it clear that these functions do not rely on legacy VGA access: they're about the default PCI display. (The device still needs to be a member of PCI_CLASS_DISPLAY_VGA.) This should not introduce any functional change. Signed-off-by: Daniel Axtens <dja@axtens.net> --- I know this adds another config option and that's a bit sad, but we can't include it unconditionally as it depends on PCI. Suggestions welcome. v3: split from the part where we add functionality rename functions --- arch/ia64/pci/fixup.c | 6 +-- arch/powerpc/kernel/pci-common.c | 6 +-- arch/x86/pci/fixup.c | 6 +-- arch/x86/video/fbdev.c | 4 +- drivers/gpu/vga/Kconfig | 12 ++++++ drivers/gpu/vga/Makefile | 1 + drivers/gpu/vga/default_display.c | 86 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/vga/vga_switcheroo.c | 8 ++-- drivers/gpu/vga/vgaarb.c | 61 ++++++--------------------- drivers/pci/pci-sysfs.c | 4 +- include/linux/default_display.h | 44 ++++++++++++++++++++ include/linux/vgaarb.h | 15 ------- 12 files changed, 173 insertions(+), 80 deletions(-) create mode 100644 drivers/gpu/vga/default_display.c create mode 100644 include/linux/default_display.h