aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorBruno Prémont <bonbons@linux-vserver.org>2015-03-11 17:34:45 -0400
committerDarren Hart <dvhart@linux.intel.com>2015-03-18 23:44:44 -0400
commit4eebd5a4e72697aac25a8a57d3f888a9d5f80370 (patch)
treea2c2b9a03f8a38596b3362022e1a804de96c71e9 /drivers/platform
parent0a63ca11b42b4fc9ece395f611679d0d3985cd4d (diff)
apple-gmux: lock iGP IO to protect from vgaarb changes
As GMUX depends on IO for iGP to be enabled and active, lock the IO at vgaarb level. This should prevent GPU driver for dGPU to disable IO for iGP while it tries to own legacy VGA IO. This fixes usage of backlight control combined with closed nvidia driver on some Apple dual-GPU (intel/nvidia) systems. On those systems loading nvidia driver disables intel IO decoding, disabling the gmux backlight controls as a side effect. Prior to commits moving boot_vga from (optional) efifb to less optional vgaarb this mis-behavior could be avoided by using right kernel config (efifb enabled but vgaarb disabled). This patch explicitly does not try to trigger vgaarb changes in order to avoid confusing already running graphics drivers. If IO has been mis-configured by vgaarb gmux will thus fail to probe. It is expected to load/probe gmux prior to graphics drivers. Fixes: ce027dac592c0ada241ce0f95ae65856828ac450 # nvidia interaction Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=86121 Reported-by: Petri Hodju <petrihodju@yahoo.com> Tested-by: Petri Hodju <petrihodju@yahoo.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Matthew Garrett <matthew.garrett@nebula.com> Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/apple-gmux.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index b9429fbf1cd8..e743b03f50da 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -22,6 +22,7 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/vga_switcheroo.h> 24#include <linux/vga_switcheroo.h>
25#include <linux/vgaarb.h>
25#include <acpi/video.h> 26#include <acpi/video.h>
26#include <asm/io.h> 27#include <asm/io.h>
27 28
@@ -31,6 +32,7 @@ struct apple_gmux_data {
31 bool indexed; 32 bool indexed;
32 struct mutex index_lock; 33 struct mutex index_lock;
33 34
35 struct pci_dev *pdev;
34 struct backlight_device *bdev; 36 struct backlight_device *bdev;
35 37
36 /* switcheroo data */ 38 /* switcheroo data */
@@ -415,6 +417,23 @@ static int gmux_resume(struct device *dev)
415 return 0; 417 return 0;
416} 418}
417 419
420static struct pci_dev *gmux_get_io_pdev(void)
421{
422 struct pci_dev *pdev = NULL;
423
424 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) {
425 u16 cmd;
426
427 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
428 if (!(cmd & PCI_COMMAND_IO))
429 continue;
430
431 return pdev;
432 }
433
434 return NULL;
435}
436
418static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) 437static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
419{ 438{
420 struct apple_gmux_data *gmux_data; 439 struct apple_gmux_data *gmux_data;
@@ -425,6 +444,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
425 int ret = -ENXIO; 444 int ret = -ENXIO;
426 acpi_status status; 445 acpi_status status;
427 unsigned long long gpe; 446 unsigned long long gpe;
447 struct pci_dev *pdev = NULL;
428 448
429 if (apple_gmux_data) 449 if (apple_gmux_data)
430 return -EBUSY; 450 return -EBUSY;
@@ -475,7 +495,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
475 ver_minor = (version >> 16) & 0xff; 495 ver_minor = (version >> 16) & 0xff;
476 ver_release = (version >> 8) & 0xff; 496 ver_release = (version >> 8) & 0xff;
477 } else { 497 } else {
478 pr_info("gmux device not present\n"); 498 pr_info("gmux device not present or IO disabled\n");
479 ret = -ENODEV; 499 ret = -ENODEV;
480 goto err_release; 500 goto err_release;
481 } 501 }
@@ -483,6 +503,23 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
483 pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, 503 pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
484 ver_release, (gmux_data->indexed ? "indexed" : "classic")); 504 ver_release, (gmux_data->indexed ? "indexed" : "classic"));
485 505
506 /*
507 * Apple systems with gmux are EFI based and normally don't use
508 * VGA. In addition changing IO+MEM ownership between IGP and dGPU
509 * disables IO/MEM used for backlight control on some systems.
510 * Lock IO+MEM to GPU with active IO to prevent switch.
511 */
512 pdev = gmux_get_io_pdev();
513 if (pdev && vga_tryget(pdev,
514 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM)) {
515 pr_err("IO+MEM vgaarb-locking for PCI:%s failed\n",
516 pci_name(pdev));
517 ret = -EBUSY;
518 goto err_release;
519 } else if (pdev)
520 pr_info("locked IO for PCI:%s\n", pci_name(pdev));
521 gmux_data->pdev = pdev;
522
486 memset(&props, 0, sizeof(props)); 523 memset(&props, 0, sizeof(props));
487 props.type = BACKLIGHT_PLATFORM; 524 props.type = BACKLIGHT_PLATFORM;
488 props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); 525 props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
@@ -574,6 +611,10 @@ err_enable_gpe:
574err_notify: 611err_notify:
575 backlight_device_unregister(bdev); 612 backlight_device_unregister(bdev);
576err_release: 613err_release:
614 if (gmux_data->pdev)
615 vga_put(gmux_data->pdev,
616 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
617 pci_dev_put(pdev);
577 release_region(gmux_data->iostart, gmux_data->iolen); 618 release_region(gmux_data->iostart, gmux_data->iolen);
578err_free: 619err_free:
579 kfree(gmux_data); 620 kfree(gmux_data);
@@ -593,6 +634,11 @@ static void gmux_remove(struct pnp_dev *pnp)
593 &gmux_notify_handler); 634 &gmux_notify_handler);
594 } 635 }
595 636
637 if (gmux_data->pdev) {
638 vga_put(gmux_data->pdev,
639 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
640 pci_dev_put(gmux_data->pdev);
641 }
596 backlight_device_unregister(gmux_data->bdev); 642 backlight_device_unregister(gmux_data->bdev);
597 643
598 release_region(gmux_data->iostart, gmux_data->iolen); 644 release_region(gmux_data->iostart, gmux_data->iolen);