diff options
author | Bruno Prémont <bonbons@linux-vserver.org> | 2014-08-24 17:09:53 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-16 15:06:18 -0400 |
commit | 86fd887b7fe350819dae5b55e7fef05b511c8656 (patch) | |
tree | 73888d1d65e169f1eb18316faf98df372f5557b3 | |
parent | 52addcf9d6669fa439387610bc65c92fa0980cef (diff) |
vgaarb: Don't default exclusively to first video device with mem+io
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>
CC: stable@vger.kernel.org # v3.5+
-rw-r--r-- | arch/ia64/pci/fixup.c | 24 | ||||
-rw-r--r-- | arch/x86/pci/fixup.c | 24 | ||||
-rw-r--r-- | drivers/gpu/vga/vgaarb.c | 38 |
3 files changed, 39 insertions, 47 deletions
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c index ec73b2cf912a..fc505d58f078 100644 --- a/arch/ia64/pci/fixup.c +++ b/arch/ia64/pci/fixup.c | |||
@@ -38,27 +38,6 @@ static void pci_fixup_video(struct pci_dev *pdev) | |||
38 | return; | 38 | return; |
39 | /* Maybe, this machine supports legacy memory map. */ | 39 | /* Maybe, this machine supports legacy memory map. */ |
40 | 40 | ||
41 | if (!vga_default_device()) { | ||
42 | resource_size_t start, end; | ||
43 | int i; | ||
44 | |||
45 | /* Does firmware framebuffer belong to us? */ | ||
46 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
47 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) | ||
48 | continue; | ||
49 | |||
50 | start = pci_resource_start(pdev, i); | ||
51 | end = pci_resource_end(pdev, i); | ||
52 | |||
53 | if (!start || !end) | ||
54 | continue; | ||
55 | |||
56 | if (screen_info.lfb_base >= start && | ||
57 | (screen_info.lfb_base + screen_info.lfb_size) < end) | ||
58 | vga_set_default_device(pdev); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* Is VGA routed to us? */ | 41 | /* Is VGA routed to us? */ |
63 | bus = pdev->bus; | 42 | bus = pdev->bus; |
64 | while (bus) { | 43 | while (bus) { |
@@ -83,8 +62,7 @@ static void pci_fixup_video(struct pci_dev *pdev) | |||
83 | pci_read_config_word(pdev, PCI_COMMAND, &config); | 62 | pci_read_config_word(pdev, PCI_COMMAND, &config); |
84 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | 63 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { |
85 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | 64 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; |
86 | dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); | 65 | dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); |
87 | vga_set_default_device(pdev); | ||
88 | } | 66 | } |
89 | } | 67 | } |
90 | } | 68 | } |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index c61ea57d1ba1..9a2b7101ae8a 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -326,27 +326,6 @@ static void pci_fixup_video(struct pci_dev *pdev) | |||
326 | struct pci_bus *bus; | 326 | struct pci_bus *bus; |
327 | u16 config; | 327 | u16 config; |
328 | 328 | ||
329 | if (!vga_default_device()) { | ||
330 | resource_size_t start, end; | ||
331 | int i; | ||
332 | |||
333 | /* Does firmware framebuffer belong to us? */ | ||
334 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
335 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) | ||
336 | continue; | ||
337 | |||
338 | start = pci_resource_start(pdev, i); | ||
339 | end = pci_resource_end(pdev, i); | ||
340 | |||
341 | if (!start || !end) | ||
342 | continue; | ||
343 | |||
344 | if (screen_info.lfb_base >= start && | ||
345 | (screen_info.lfb_base + screen_info.lfb_size) < end) | ||
346 | vga_set_default_device(pdev); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /* Is VGA routed to us? */ | 329 | /* Is VGA routed to us? */ |
351 | bus = pdev->bus; | 330 | bus = pdev->bus; |
352 | while (bus) { | 331 | while (bus) { |
@@ -371,8 +350,7 @@ static void pci_fixup_video(struct pci_dev *pdev) | |||
371 | pci_read_config_word(pdev, PCI_COMMAND, &config); | 350 | pci_read_config_word(pdev, PCI_COMMAND, &config); |
372 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | 351 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { |
373 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | 352 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; |
374 | dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); | 353 | dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); |
375 | vga_set_default_device(pdev); | ||
376 | } | 354 | } |
377 | } | 355 | } |
378 | } | 356 | } |
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index d2077f040f3e..24ac52e6cd41 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/poll.h> | 41 | #include <linux/poll.h> |
42 | #include <linux/miscdevice.h> | 42 | #include <linux/miscdevice.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/screen_info.h> | ||
44 | 45 | ||
45 | #include <linux/uaccess.h> | 46 | #include <linux/uaccess.h> |
46 | 47 | ||
@@ -585,8 +586,11 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev) | |||
585 | */ | 586 | */ |
586 | #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE | 587 | #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE |
587 | if (vga_default == NULL && | 588 | if (vga_default == NULL && |
588 | ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) | 589 | ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) { |
590 | pr_info("vgaarb: setting as boot device: PCI:%s\n", | ||
591 | pci_name(pdev)); | ||
589 | vga_set_default_device(pdev); | 592 | vga_set_default_device(pdev); |
593 | } | ||
590 | #endif | 594 | #endif |
591 | 595 | ||
592 | vga_arbiter_check_bridge_sharing(vgadev); | 596 | vga_arbiter_check_bridge_sharing(vgadev); |
@@ -1320,6 +1324,38 @@ static int __init vga_arb_device_init(void) | |||
1320 | pr_info("vgaarb: loaded\n"); | 1324 | pr_info("vgaarb: loaded\n"); |
1321 | 1325 | ||
1322 | list_for_each_entry(vgadev, &vga_list, list) { | 1326 | list_for_each_entry(vgadev, &vga_list, list) { |
1327 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) | ||
1328 | /* Override I/O based detection done by vga_arbiter_add_pci_device() | ||
1329 | * as it may take the wrong device (e.g. on Apple system under EFI). | ||
1330 | * | ||
1331 | * Select the device owning the boot framebuffer if there is one. | ||
1332 | */ | ||
1333 | resource_size_t start, end; | ||
1334 | int i; | ||
1335 | |||
1336 | /* Does firmware framebuffer belong to us? */ | ||
1337 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
1338 | if (!(pci_resource_flags(vgadev->pdev, i) & IORESOURCE_MEM)) | ||
1339 | continue; | ||
1340 | |||
1341 | start = pci_resource_start(vgadev->pdev, i); | ||
1342 | end = pci_resource_end(vgadev->pdev, i); | ||
1343 | |||
1344 | if (!start || !end) | ||
1345 | continue; | ||
1346 | |||
1347 | if (screen_info.lfb_base < start || | ||
1348 | (screen_info.lfb_base + screen_info.lfb_size) >= end) | ||
1349 | continue; | ||
1350 | if (!vga_default_device()) | ||
1351 | pr_info("vgaarb: setting as boot device: PCI:%s\n", | ||
1352 | pci_name(vgadev->pdev)); | ||
1353 | else if (vgadev->pdev != vga_default_device()) | ||
1354 | pr_info("vgaarb: overriding boot device: PCI:%s\n", | ||
1355 | pci_name(vgadev->pdev)); | ||
1356 | vga_set_default_device(vgadev->pdev); | ||
1357 | } | ||
1358 | #endif | ||
1323 | if (vgadev->bridge_has_one_vga) | 1359 | if (vgadev->bridge_has_one_vga) |
1324 | pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev)); | 1360 | pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev)); |
1325 | else | 1361 | else |