Commit 59ee364b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'thunderbolt-for-v5.10-rc1' of...

Merge tag 'thunderbolt-for-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next

Mika writes:

thunderbolt: Changes for v5.10 merge window

This includes following Thunderbolt/USB4 changes for v5.10 merge window:

  * A couple of optimizations around Tiger Lake force power logic and
    NHI (Native Host Interface) LC (Link Controller) mailbox command
    processing

  * Power management improvements for Software Connection Manager

  * Debugfs support

  * Allow KUnit tests to be enabled also when Thunderbolt driver is
    configured as module.

  * Few minor cleanups and fixes

All these have been in linux-next with no reported issues.

* tag 'thunderbolt-for-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: (37 commits)
  thunderbolt: Capitalize comment on top of QUIRK_FORCE_POWER_LINK_CONTROLLER
  thunderbolt: Correct tb_check_quirks() kernel-doc
  thunderbolt: Log correct zeroX entries in decode_error()
  thunderbolt: Handle ERR_LOCK notification
  thunderbolt: Use "if USB4" instead of "depends on" in Kconfig
  thunderbolt: Allow KUnit tests to be built also when CONFIG_USB4=m
  thunderbolt: Only stop control channel when entering freeze
  thunderbolt: debugfs: Fix uninitialized return in counters_write()
  thunderbolt: Add debugfs interface
  thunderbolt: No need to warn in TB_CFG_ERROR_INVALID_CONFIG_SPACE
  thunderbolt: Introduce tb_switch_is_tiger_lake()
  thunderbolt: Introduce tb_switch_is_ice_lake()
  thunderbolt: Check for Intel vendor ID when identifying controller
  thunderbolt: Introduce tb_port_is_nhi()
  thunderbolt: Introduce tb_switch_next_cap()
  thunderbolt: Introduce tb_port_next_cap()
  thunderbolt: Move struct tb_cap_any to tb_regs.h
  thunderbolt: Add runtime PM for Software CM
  thunderbolt: Create device links from ACPI description
  ACPI: Export acpi_get_first_physical_node() to modules
  ...
parents bf1c6744 810278da
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -551,6 +551,7 @@ struct device *acpi_get_first_physical_node(struct acpi_device *adev)
	mutex_unlock(physical_node_lock);
	return phys_dev;
}
EXPORT_SYMBOL_GPL(acpi_get_first_physical_node);

static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
						      const struct device *dev)
+0 −57
Original line number Diff line number Diff line
@@ -3673,63 +3673,6 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL,
			       PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
			       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 (!x86_apple_machine)
		return;
	if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
		return;

	/*
	 * Find the NHI and confirm that we are a bridge on the Thunderbolt
	 * host controller and not on a Thunderbolt 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 != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
			nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
			nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI &&
			nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI)
		    || nhi->class != PCI_CLASS_SYSTEM_OTHER << 8)
		goto out;
	pci_info(dev, "quirk: waiting 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,
			       PCI_DEVICE_ID_INTEL_LIGHT_RIDGE,
			       quirk_apple_wait_for_thunderbolt);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
			       PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C,
			       quirk_apple_wait_for_thunderbolt);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
			       PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE,
			       quirk_apple_wait_for_thunderbolt);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,
			       PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE,
			       quirk_apple_wait_for_thunderbolt);
#endif

/*
+13 −1
Original line number Diff line number Diff line
@@ -16,7 +16,19 @@ menuconfig USB4
	  To compile this driver a module, choose M here. The module will be
	  called thunderbolt.

if USB4

config USB4_DEBUGFS_WRITE
	bool "Enable write by debugfs to configuration spaces (DANGEROUS)"
	help
	  Enables writing to device configuration registers through
	  debugfs interface.

	  Only enable this if you know what you are doing! Never enable
	  this for production systems or distro kernels.

config USB4_KUNIT_TEST
	bool "KUnit tests"
	depends on KUNIT=y
	depends on USB4=y

endif # USB4
+3 −1
Original line number Diff line number Diff line
@@ -4,4 +4,6 @@ thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o ee
thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o
thunderbolt-objs += nvm.o retimer.o quirks.o

obj-${CONFIG_USB4_KUNIT_TEST} += test.o
thunderbolt-${CONFIG_ACPI} += acpi.o
thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o
thunderbolt-${CONFIG_USB4_KUNIT_TEST} += test.o
+117 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * ACPI support
 *
 * Copyright (C) 2020, Intel Corporation
 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
 */

#include <linux/acpi.h>

#include "tb.h"

static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
				    void **return_value)
{
	struct fwnode_reference_args args;
	struct fwnode_handle *fwnode;
	struct tb_nhi *nhi = data;
	struct acpi_device *adev;
	struct pci_dev *pdev;
	struct device *dev;
	int ret;

	if (acpi_bus_get_device(handle, &adev))
		return AE_OK;

	fwnode = acpi_fwnode_handle(adev);
	ret = fwnode_property_get_reference_args(fwnode, "usb4-host-interface",
						 NULL, 0, 0, &args);
	if (ret)
		return AE_OK;

	/* It needs to reference this NHI */
	if (nhi->pdev->dev.fwnode != args.fwnode)
		goto out_put;

	/*
	 * Try to find physical device walking upwards to the hierarcy.
	 * We need to do this because the xHCI driver might not yet be
	 * bound so the USB3 SuperSpeed ports are not yet created.
	 */
	dev = acpi_get_first_physical_node(adev);
	while (!dev) {
		adev = adev->parent;
		if (!adev)
			break;
		dev = acpi_get_first_physical_node(adev);
	}

	if (!dev)
		goto out_put;

	/*
	 * Check that the device is PCIe. This is because USB3
	 * SuperSpeed ports have this property and they are not power
	 * managed with the xHCI and the SuperSpeed hub so we create the
	 * link from xHCI instead.
	 */
	while (!dev_is_pci(dev))
		dev = dev->parent;

	if (!dev)
		goto out_put;

	/*
	 * Check that this actually matches the type of device we
	 * expect. It should either be xHCI or PCIe root/downstream
	 * port.
	 */
	pdev = to_pci_dev(dev);
	if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI ||
	    (pci_is_pcie(pdev) &&
		(pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
		 pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) {
		const struct device_link *link;

		link = device_link_add(&pdev->dev, &nhi->pdev->dev,
				       DL_FLAG_AUTOREMOVE_SUPPLIER |
				       DL_FLAG_PM_RUNTIME);
		if (link) {
			dev_dbg(&nhi->pdev->dev, "created link from %s\n",
				dev_name(&pdev->dev));
		} else {
			dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n",
				 dev_name(&pdev->dev));
		}
	}

out_put:
	fwnode_handle_put(args.fwnode);
	return AE_OK;
}

/**
 * tb_acpi_add_links() - Add device links based on ACPI description
 * @nhi: Pointer to NHI
 *
 * Goes over ACPI namespace finding tunneled ports that reference to
 * @nhi ACPI node. For each reference a device link is added. The link
 * is automatically removed by the driver core.
 */
void tb_acpi_add_links(struct tb_nhi *nhi)
{
	acpi_status status;

	if (!has_acpi_companion(&nhi->pdev->dev))
		return;

	/*
	 * Find all devices that have usb4-host-controller interface
	 * property that references to this NHI.
	 */
	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32,
				     tb_acpi_add_link, NULL, nhi, NULL);
	if (ACPI_FAILURE(status))
		dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
}
Loading