From: Greg Kroah-Hartman Date: Mon, 6 Jan 2014 22:18:38 +0000 (-0800) Subject: 3.12-stable patches X-Git-Tag: v3.4.76~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ae886cbcb77e8bd783beaef947dfa75fa6d98f16;p=thirdparty%2Fkernel%2Fstable-queue.git 3.12-stable patches added patches: acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch --- 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 index 00000000000..ea3736743a8 --- /dev/null +++ b/queue-3.12/acpiphp-radeon-nouveau-fix-vga-switcheroo-problem-related-to-hotplug.patch @@ -0,0 +1,215 @@ +From f244d8b623dae7a7bc695b0336f67729b95a9736 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 31 Dec 2013 13:39:42 +0100 +Subject: ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug + +From: "Rafael J. Wysocki" + +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 +Reported-and-tested-by: +Reported-and-tested-by: Joaquín Aramendía +Cc: Alex Deucher +Cc: Dave Airlie +Cc: Takashi Iwai +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4c206b4cee5 --- /dev/null +++ b/queue-3.12/nouveau_acpi-convert-acpi_get_handle-to-acpi_has_method.patch @@ -0,0 +1,53 @@ +From 187b5b5d520c2318a1f88fb8d8913a9d7fbf7d92 Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Tue, 3 Sep 2013 08:32:00 +0800 +Subject: nouveau_acpi: convert acpi_get_handle() to acpi_has_method() + +From: Zhang Rui + +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 +CC: Ben Skeggs +CC: Dave Airlie +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-3.12/series b/queue-3.12/series index 19123220b65..34719e9e0ad 100644 --- a/queue-3.12/series +++ b/queue-3.12/series @@ -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