[kernel] r22059 - in dists/sid/linux/debian: . patches patches/features/x86/apple-tb

Ben Hutchings benh at moszumanska.debian.org
Sun Nov 9 10:25:36 UTC 2014


Author: benh
Date: Sun Nov  9 10:25:36 2014
New Revision: 22059

Log:
Add PCI quirks for Apple Thunderbolt

Added:
   dists/sid/linux/debian/patches/features/x86/apple-tb/pci-add-pci_fixup_suspend_late-quirk-pass.patch
   dists/sid/linux/debian/patches/features/x86/apple-tb/pci-suspend-resume-quirks-for-apple-thunderbolt.patch
Modified:
   dists/sid/linux/debian/changelog
   dists/sid/linux/debian/patches/series

Modified: dists/sid/linux/debian/changelog
==============================================================================
--- dists/sid/linux/debian/changelog	Sun Nov  9 10:15:54 2014	(r22058)
+++ dists/sid/linux/debian/changelog	Sun Nov  9 10:25:36 2014	(r22059)
@@ -1,6 +1,9 @@
 linux (3.16.7-3) UNRELEASED; urgency=medium
 
-  * [x86] Enable THUNDERBOLT as module (Closes: #768653)
+  * [x86] Complete Thunderbolt support on Apple computers (Closes: #768653)
+    - PCI: Add pci_fixup_suspend_late quirk pass
+    - PCI: Suspend/resume quirks for Apple thunderbolt
+    - Enable THUNDERBOLT as module
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sun, 09 Nov 2014 10:13:09 +0000
 

Added: dists/sid/linux/debian/patches/features/x86/apple-tb/pci-add-pci_fixup_suspend_late-quirk-pass.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/x86/apple-tb/pci-add-pci_fixup_suspend_late-quirk-pass.patch	Sun Nov  9 10:25:36 2014	(r22059)
@@ -0,0 +1,164 @@
+From: Andreas Noever <andreas.noever at gmail.com>
+Date: Tue, 3 Jun 2014 22:04:09 +0200
+Subject: [1/2] PCI: Add pci_fixup_suspend_late quirk pass
+Origin: https://git.kernel.org/linus/7d2a01b87f1682fde87461864e6682031bfaa0a9
+
+Add pci_fixup_suspend_late as a new pci_fixup_pass. The pass is called
+from suspend_noirq and poweroff_noirq. Using the same pass for suspend
+and hibernate is consistent with resume_early which is called by
+resume_noirq and restore_noirq.
+
+The new quirk pass is required for Thunderbolt support on Apple
+hardware.
+
+Signed-off-by: Andreas Noever <andreas.noever at gmail.com>
+Acked-by: Bjorn Helgaas <bhelgaas at google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/pci/pci-driver.c          | 18 ++++++++++++++----
+ drivers/pci/quirks.c              |  7 +++++++
+ include/asm-generic/vmlinux.lds.h |  3 +++
+ include/linux/pci.h               | 12 +++++++++++-
+ 4 files changed, 35 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -582,7 +582,7 @@ static int pci_legacy_suspend_late(struc
+ 			WARN_ONCE(pci_dev->current_state != prev,
+ 				"PCI PM: Device state not saved by %pF\n",
+ 				drv->suspend_late);
+-			return 0;
++			goto Fixup;
+ 		}
+ 	}
+ 
+@@ -591,6 +591,9 @@ static int pci_legacy_suspend_late(struc
+ 
+ 	pci_pm_set_unknown_state(pci_dev);
+ 
++Fixup:
++	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
++
+ 	return 0;
+ }
+ 
+@@ -734,7 +737,7 @@ static int pci_pm_suspend_noirq(struct d
+ 
+ 	if (!pm) {
+ 		pci_save_state(pci_dev);
+-		return 0;
++		goto Fixup;
+ 	}
+ 
+ 	if (pm->suspend_noirq) {
+@@ -751,7 +754,7 @@ static int pci_pm_suspend_noirq(struct d
+ 			WARN_ONCE(pci_dev->current_state != prev,
+ 				"PCI PM: State of device not saved by %pF\n",
+ 				pm->suspend_noirq);
+-			return 0;
++			goto Fixup;
+ 		}
+ 	}
+ 
+@@ -775,6 +778,9 @@ static int pci_pm_suspend_noirq(struct d
+ 	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ 		pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+ 
++Fixup:
++	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
++
+ 	return 0;
+ }
+ 
+@@ -999,8 +1005,10 @@ static int pci_pm_poweroff_noirq(struct
+ 	if (pci_has_legacy_pm_support(to_pci_dev(dev)))
+ 		return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
+ 
+-	if (!drv || !drv->pm)
++	if (!drv || !drv->pm) {
++		pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+ 		return 0;
++	}
+ 
+ 	if (drv->pm->poweroff_noirq) {
+ 		int error;
+@@ -1021,6 +1029,8 @@ static int pci_pm_poweroff_noirq(struct
+ 	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ 		pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+ 
++	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
++
+ 	if (pcibios_pm_ops.poweroff_noirq)
+ 		return pcibios_pm_ops.poweroff_noirq(dev);
+ 
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -3038,6 +3038,8 @@ extern struct pci_fixup __start_pci_fixu
+ extern struct pci_fixup __end_pci_fixups_resume_early[];
+ extern struct pci_fixup __start_pci_fixups_suspend[];
+ extern struct pci_fixup __end_pci_fixups_suspend[];
++extern struct pci_fixup __start_pci_fixups_suspend_late[];
++extern struct pci_fixup __end_pci_fixups_suspend_late[];
+ 
+ static bool pci_apply_fixup_final_quirks;
+ 
+@@ -3083,6 +3085,11 @@ void pci_fixup_device(enum pci_fixup_pas
+ 		end = __end_pci_fixups_suspend;
+ 		break;
+ 
++	case pci_fixup_suspend_late:
++		start = __start_pci_fixups_suspend_late;
++		end = __end_pci_fixups_suspend_late;
++		break;
++
+ 	default:
+ 		/* stupid compiler warning, you would think with an enum... */
+ 		return;
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -268,6 +268,9 @@
+ 		VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .;		\
+ 		*(.pci_fixup_suspend)					\
+ 		VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .;		\
++		VMLINUX_SYMBOL(__start_pci_fixups_suspend_late) = .;	\
++		*(.pci_fixup_suspend_late)				\
++		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
+ 	}								\
+ 									\
+ 	/* Built-in firmware blobs */					\
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1483,8 +1483,9 @@ enum pci_fixup_pass {
+ 	pci_fixup_final,	/* Final phase of device fixups */
+ 	pci_fixup_enable,	/* pci_enable_device() time */
+ 	pci_fixup_resume,	/* pci_device_resume() */
+-	pci_fixup_suspend,	/* pci_device_suspend */
++	pci_fixup_suspend,	/* pci_device_suspend() */
+ 	pci_fixup_resume_early, /* pci_device_resume_early() */
++	pci_fixup_suspend_late,	/* pci_device_suspend_late() */
+ };
+ 
+ /* Anonymous variables would be nice... */
+@@ -1525,6 +1526,11 @@ enum pci_fixup_pass {
+ 	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,			\
+ 		suspend##hook, vendor, device, class,	\
+ 		class_shift, hook)
++#define DECLARE_PCI_FIXUP_CLASS_SUSPEND_LATE(vendor, device, class,	\
++					 class_shift, hook)		\
++	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend_late,		\
++		suspend_late##hook, vendor, device,	\
++		class, class_shift, hook)
+ 
+ #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\
+ 	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
+@@ -1550,6 +1556,10 @@ enum pci_fixup_pass {
+ 	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,			\
+ 		suspend##hook, vendor, device,		\
+ 		PCI_ANY_ID, 0, hook)
++#define DECLARE_PCI_FIXUP_SUSPEND_LATE(vendor, device, hook)		\
++	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend_late,		\
++		suspend_late##hook, vendor, device,	\
++		PCI_ANY_ID, 0, hook)
+ 
+ #ifdef CONFIG_PCI_QUIRKS
+ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);

Added: dists/sid/linux/debian/patches/features/x86/apple-tb/pci-suspend-resume-quirks-for-apple-thunderbolt.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/x86/apple-tb/pci-suspend-resume-quirks-for-apple-thunderbolt.patch	Sun Nov  9 10:25:36 2014	(r22059)
@@ -0,0 +1,135 @@
+From: Andreas Noever <andreas.noever at gmail.com>
+Date: Tue, 3 Jun 2014 22:04:10 +0200
+Subject: [2/2] PCI: Suspend/resume quirks for Apple thunderbolt
+Origin: https://git.kernel.org/linus/1df5172c5c251ec24a1bd0f44fe38c841f384330
+
+Add two quirks to support thunderbolt suspend/resume on Apple systems.
+We need to perform two different actions during suspend and resume:
+
+The whole controller has to be powered down before suspend. If this is
+not done then the native host interface device will be gone after resume
+if a thunderbolt device was plugged in before suspending. The controller
+represents itself as multiple PCI devices/bridges. To power it down we
+hook into the upstream bridge of the controller and call the magic ACPI
+methods.  Power will be restored automatically during resume (by the
+firmware presumably).
+
+During resume we have to wait for the native host interface to
+reestablish all pci tunnels. Since there is no parent-child relationship
+between the NHI and the bridges we have to explicitly wait for them
+using device_pm_wait_for_dev. We do this in the resume_noirq phase of
+the downstream bridges of the controller (which lead into the
+thunderbolt tunnels).
+
+Signed-off-by: Andreas Noever <andreas.noever at gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/pci/quirks.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -3006,6 +3006,103 @@ DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601,
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169,
+ 			 quirk_broken_intx_masking);
+ 
++#ifdef CONFIG_ACPI
++/*
++ * Apple: Shutdown Cactus Ridge Thunderbolt controller.
++ *
++ * On Apple hardware the Cactus Ridge Thunderbolt controller needs to be
++ * shutdown before suspend. Otherwise the native host interface (NHI) will not
++ * be present after resume if a device was plugged in before suspend.
++ *
++ * The thunderbolt controller consists of a pcie switch with downstream
++ * bridges leading to the NHI and to the tunnel pci bridges.
++ *
++ * This quirk cuts power to the whole chip. Therefore we have to apply it
++ * during suspend_noirq of the upstream bridge.
++ *
++ * Power is automagically restored before resume. No action is needed.
++ */
++static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
++{
++	acpi_handle bridge, SXIO, SXFP, SXLV;
++
++	if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
++		return;
++	if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM)
++		return;
++	bridge = ACPI_HANDLE(&dev->dev);
++	if (!bridge)
++		return;
++	/*
++	 * SXIO and SXLV are present only on machines requiring this quirk.
++	 * TB bridges in external devices might have the same device id as those
++	 * on the host, but they will not have the associated ACPI methods. This
++	 * implicitly checks that we are at the right bridge.
++	 */
++	if (ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXIO", &SXIO))
++	    || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXFP", &SXFP))
++	    || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXLV", &SXLV)))
++		return;
++	dev_info(&dev->dev, "quirk: cutting power to thunderbolt controller...\n");
++
++	/* magic sequence */
++	acpi_execute_simple_method(SXIO, NULL, 1);
++	acpi_execute_simple_method(SXFP, NULL, 0);
++	msleep(300);
++	acpi_execute_simple_method(SXLV, NULL, 0);
++	acpi_execute_simple_method(SXIO, NULL, 0);
++	acpi_execute_simple_method(SXLV, NULL, 0);
++}
++DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547,
++			       quirk_apple_poweroff_thunderbolt);
++
++/*
++ * Apple: Wait for the thunderbolt controller to reestablish pci tunnels.
++ *
++ * During suspend the thunderbolt controller is reset and all pci
++ * tunnels are lost. The NHI driver will try to reestablish all tunnels
++ * during resume. We have to manually wait for the NHI since there is
++ * no parent child relationship between the NHI and the tunneled
++ * bridges.
++ */
++static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
++{
++	struct pci_dev *sibling = NULL;
++	struct pci_dev *nhi = NULL;
++
++	if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
++		return;
++	if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
++		return;
++	/*
++	 * Find the NHI and confirm that we are a bridge on the tb host
++	 * controller and not on a tb endpoint.
++	 */
++	sibling = pci_get_slot(dev->bus, 0x0);
++	if (sibling == dev)
++		goto out; /* we are the downstream bridge to the NHI */
++	if (!sibling || !sibling->subordinate)
++		goto out;
++	nhi = pci_get_slot(sibling->subordinate, 0x0);
++	if (!nhi)
++		goto out;
++	if (nhi->vendor != PCI_VENDOR_ID_INTEL
++			|| (nhi->device != 0x1547 && nhi->device != 0x156c)
++			|| nhi->subsystem_vendor != 0x2222
++			|| nhi->subsystem_device != 0x1111)
++		goto out;
++	dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n");
++	device_pm_wait_for_dev(&dev->dev, &nhi->dev);
++out:
++	pci_dev_put(nhi);
++	pci_dev_put(sibling);
++}
++DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547,
++			       quirk_apple_wait_for_thunderbolt);
++DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d,
++			       quirk_apple_wait_for_thunderbolt);
++#endif
++
+ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ 			  struct pci_fixup *end)
+ {

Modified: dists/sid/linux/debian/patches/series
==============================================================================
--- dists/sid/linux/debian/patches/series	Sun Nov  9 10:15:54 2014	(r22058)
+++ dists/sid/linux/debian/patches/series	Sun Nov  9 10:25:36 2014	(r22059)
@@ -453,6 +453,8 @@
 features/x86/apple-tb/0029-thunderbolt-Correct-the-size-argument-to-devm_kzallo.patch
 features/x86/apple-tb/0030-thunderbolt-Use-kcalloc.patch
 features/x86/apple-tb/0031-thunderbolt-Clear-hops-before-overwriting.patch
+features/x86/apple-tb/pci-add-pci_fixup_suspend_late-quirk-pass.patch
+features/x86/apple-tb/pci-suspend-resume-quirks-for-apple-thunderbolt.patch
 
 # Add iwlwifi firmware monitor from 3.17
 features/all/iwlwifi-debug/iwlwifi-add-device-firmware-to-fw-error-dump-file.patch



More information about the Kernel-svn-changes mailing list