]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 22:18:38 +0000 (14:18 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 22:18:38 +0000 (14:18 -0800)
added patches:
acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch
nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch

queue-3.12/acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch [new file with mode: 0644]
queue-3.12/nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch [new file with mode: 0644]
queue-3.12/series

diff --git a/queue-3.12/acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch b/queue-3.12/acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch
new file mode 100644 (file)
index 0000000..ea37367
--- /dev/null
@@ -0,0 +1,215 @@
+From f244d8b623dae7a7bc695b0336f67729b95a9736 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Tue, 31 Dec 2013 13:39:42 +0100
+Subject: ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug
+
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+
+commit f244d8b623dae7a7bc695b0336f67729b95a9736 upstream.
+
+The changes in the ACPI-based PCI hotplug (ACPIPHP) subsystem made
+during the 3.12 development cycle uncovered a problem with VGA
+switcheroo that on some systems, when the device-specific method
+(ATPX in the radeon case, _DSM in the nouveau case) is used to turn
+off the discrete graphics, the BIOS generates ACPI hotplug events for
+that device and those events cause ACPIPHP to attempt to remove the
+device from the system (they are events for a device that was present
+previously and is not present any more, so that's what should be done
+according to the spec).  Then, the system stops functioning correctly.
+
+Since the hotplug events in question were simply silently ignored
+previously, the least intrusive way to address that problem is to
+make ACPIPHP ignore them again.  For this purpose, introduce a new
+ACPI device flag, no_hotplug, and modify ACPIPHP to ignore hotplug
+events for PCI devices whose ACPI companions have that flag set.
+Next, make the radeon and nouveau switcheroo detection code set the
+no_hotplug flag for the discrete graphics' ACPI companion.
+
+Fixes: bbd34fcdd1b2 (ACPI / hotplug / PCI: Register all devices under the given bridge)
+References: https://bugzilla.kernel.org/show_bug.cgi?id=61891
+References: https://bugzilla.kernel.org/show_bug.cgi?id=64891
+Reported-and-tested-by: Mike Lothian <mike@fireburn.co.uk>
+Reported-and-tested-by: <madcatx@atlas.cz>
+Reported-and-tested-by: Joaquín Aramendía <samsagax@gmail.com>
+Cc: Alex Deucher <alexdeucher@gmail.com>
+Cc: Dave Airlie <airlied@linux.ie>
+Cc: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/bus.c                           |   10 ++++++++++
+ drivers/gpu/drm/nouveau/nouveau_acpi.c       |   16 ++++++++++++++--
+ drivers/gpu/drm/radeon/radeon_atpx_handler.c |   16 ++++++++++++++--
+ drivers/pci/hotplug/acpiphp_glue.c           |   26 +++++++++++++++++++++++---
+ include/acpi/acpi_bus.h                      |    4 +++-
+ 5 files changed, 64 insertions(+), 8 deletions(-)
+
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handl
+ }
+ EXPORT_SYMBOL(acpi_bus_get_private_data);
++void acpi_bus_no_hotplug(acpi_handle handle)
++{
++      struct acpi_device *adev = NULL;
++
++      acpi_bus_get_device(handle, &adev);
++      if (adev)
++              adev->flags.no_hotplug = true;
++}
++EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
++
+ static void acpi_print_osc_error(acpi_handle handle,
+       struct acpi_osc_context *context, char *error)
+ {
+--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
+       bool dsm_detected;
+       bool optimus_detected;
+       acpi_handle dhandle;
++      acpi_handle other_handle;
+       acpi_handle rom_handle;
+ } nouveau_dsm_priv;
+@@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct
+       if (!dhandle)
+               return false;
+-      if (!acpi_has_method(dhandle, "_DSM"))
++      if (!acpi_has_method(dhandle, "_DSM")) {
++              nouveau_dsm_priv.other_handle = dhandle;
+               return false;
+-
++      }
+       if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
+               retval |= NOUVEAU_DSM_HAS_MUX;
+@@ -328,6 +330,16 @@ static bool nouveau_dsm_detect(void)
+               printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
+                       acpi_method_name);
+               nouveau_dsm_priv.dsm_detected = true;
++              /*
++               * On some systems hotplug events are generated for the device
++               * being switched off when _DSM is executed.  They cause ACPI
++               * hotplug to trigger and attempt to remove the device from
++               * the system, which causes it to break down.  Prevent that from
++               * happening by setting the no_hotplug flag for the involved
++               * ACPI device objects.
++               */
++              acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
++              acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
+               ret = true;
+       }
+--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
++++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+@@ -34,6 +34,7 @@ static struct radeon_atpx_priv {
+       bool atpx_detected;
+       /* handle for device - and atpx */
+       acpi_handle dhandle;
++      acpi_handle other_handle;
+       struct radeon_atpx atpx;
+ } radeon_atpx_priv;
+@@ -448,9 +449,10 @@ static bool radeon_atpx_pci_probe_handle
+               return false;
+       status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+-      if (ACPI_FAILURE(status))
++      if (ACPI_FAILURE(status)) {
++              radeon_atpx_priv.other_handle = dhandle;
+               return false;
+-
++      }
+       radeon_atpx_priv.dhandle = dhandle;
+       radeon_atpx_priv.atpx.handle = atpx_handle;
+       return true;
+@@ -527,6 +529,16 @@ static bool radeon_atpx_detect(void)
+               printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
+                      acpi_method_name);
+               radeon_atpx_priv.atpx_detected = true;
++              /*
++               * On some systems hotplug events are generated for the device
++               * being switched off when ATPX is executed.  They cause ACPI
++               * hotplug to trigger and attempt to remove the device from
++               * the system, which causes it to break down.  Prevent that from
++               * happening by setting the no_hotplug flag for the involved
++               * ACPI device objects.
++               */
++              acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
++              acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
+               return true;
+       }
+       return false;
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -645,6 +645,24 @@ static void disable_slot(struct acpiphp_
+       slot->flags &= (~SLOT_ENABLED);
+ }
++static bool acpiphp_no_hotplug(acpi_handle handle)
++{
++      struct acpi_device *adev = NULL;
++
++      acpi_bus_get_device(handle, &adev);
++      return adev && adev->flags.no_hotplug;
++}
++
++static bool slot_no_hotplug(struct acpiphp_slot *slot)
++{
++      struct acpiphp_func *func;
++
++      list_for_each_entry(func, &slot->funcs, sibling)
++              if (acpiphp_no_hotplug(func_to_handle(func)))
++                      return true;
++
++      return false;
++}
+ /**
+  * get_slot_status - get ACPI slot status
+@@ -703,7 +721,8 @@ static void trim_stale_devices(struct pc
+               unsigned long long sta;
+               status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+-              alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
++              alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
++                      || acpiphp_no_hotplug(handle);
+       }
+       if (!alive) {
+               u32 v;
+@@ -743,8 +762,9 @@ static void acpiphp_check_bridge(struct
+               struct pci_dev *dev, *tmp;
+               mutex_lock(&slot->crit_sect);
+-              /* wake up all functions */
+-              if (get_slot_status(slot) == ACPI_STA_ALL) {
++              if (slot_no_hotplug(slot)) {
++                      ; /* do nothing */
++              } else if (get_slot_status(slot) == ACPI_STA_ALL) {
+                       /* remove stale devices if any */
+                       list_for_each_entry_safe(dev, tmp, &bus->devices,
+                                                bus_list)
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -169,7 +169,8 @@ struct acpi_device_flags {
+       u32 ejectable:1;
+       u32 power_manageable:1;
+       u32 match_driver:1;
+-      u32 reserved:27;
++      u32 no_hotplug:1;
++      u32 reserved:26;
+ };
+ /* File System */
+@@ -357,6 +358,7 @@ extern struct kobject *acpi_kobj;
+ extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
+ void acpi_bus_private_data_handler(acpi_handle, void *);
+ int acpi_bus_get_private_data(acpi_handle, void **);
++void acpi_bus_no_hotplug(acpi_handle handle);
+ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
+ extern int register_acpi_notifier(struct notifier_block *);
+ extern int unregister_acpi_notifier(struct notifier_block *);
diff --git a/queue-3.12/nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch b/queue-3.12/nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch
new file mode 100644 (file)
index 0000000..4c206b4
--- /dev/null
@@ -0,0 +1,53 @@
+From 187b5b5d520c2318a1f88fb8d8913a9d7fbf7d92 Mon Sep 17 00:00:00 2001
+From: Zhang Rui <rui.zhang@intel.com>
+Date: Tue, 3 Sep 2013 08:32:00 +0800
+Subject: nouveau_acpi: convert acpi_get_handle() to acpi_has_method()
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+commit 187b5b5d520c2318a1f88fb8d8913a9d7fbf7d92 upstream.
+
+acpi_has_method() is a new ACPI API introduced to check
+the existence of an ACPI control method.
+
+It can be used to replace acpi_get_handle() in the case that
+1. the calling function doesn't need the ACPI handle of the control method.
+and
+2. the calling function doesn't care the reason why the method is unavailable.
+
+Convert acpi_get_handle() to acpi_has_method()
+in drivers/gpu/drm/nouveau/nouveau_acpi.c in this patch.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+CC: Ben Skeggs <bskeggs@redhat.com>
+CC: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nouveau_acpi.c |    7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+@@ -253,18 +253,15 @@ static struct vga_switcheroo_handler nou
+ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
+ {
+-      acpi_handle dhandle, nvidia_handle;
+-      acpi_status status;
++      acpi_handle dhandle;
+       int retval = 0;
+       dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+       if (!dhandle)
+               return false;
+-      status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
+-      if (ACPI_FAILURE(status)) {
++      if (!acpi_has_method(dhandle, "_DSM"))
+               return false;
+-      }
+       if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
+               retval |= NOUVEAU_DSM_HAS_MUX;
index 19123220b65906fcb5ff366146f941ddc827a7a4..34719e9e0ad698da7d21dc4e1e2cef728d5d0290 100644 (file)
@@ -140,3 +140,5 @@ clocksource-dw_apb_timer_of-fix-read_sched_clock.patch
 clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch
 aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch
 aio-migratepages-make-aio-migrate-pages-sane.patch
+nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch
+acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch