Commit 0a25669b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

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

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

Mika writes:

thunderbolt: Changes for v5.12 merge window

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

  * Start lane initialization after sleep for Thunderbolt 3 compatible
    devices

  * Add support for de-authorizing PCIe tunnels (software based
    connection manager only)

  * Add support for new ACPI 6.4 USB4 _OSC

  * Allow disabling XDomain protocol

  * Add support for new SL5 security level

  * Clean up kernel-docs to pass W=1 builds

  * A couple of cleanups and minor fixes

All these have been in linux-next without reported issues.

* tag 'thunderbolt-for-v5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: (27 commits)
  thunderbolt: Add support for native USB4 _OSC
  ACPI: Add support for native USB4 control _OSC
  ACPI: Execute platform _OSC also with query bit clear
  thunderbolt: Allow disabling XDomain protocol
  thunderbolt: Add support for PCIe tunneling disabled (SL5)
  thunderbolt: dma_test: Drop unnecessary include
  thunderbolt: Add clarifying comments about USB4 terms router and adapter
  thunderbolt: switch: Fix kernel-doc descriptions of non-static functions
  thunderbolt: nhi: Fix kernel-doc descriptions of non-static functions
  thunderbolt: path: Fix kernel-doc descriptions of non-static functions
  thunderbolt: eeprom: Fix kernel-doc descriptions of non-static functions
  thunderbolt: ctl: Fix kernel-doc descriptions of non-static functions
  thunderbolt: switch: Fix function name in the header
  thunderbolt: tunnel: Fix misspelling of 'receive_path'
  thunderbolt: icm: Fix a couple of formatting issues
  thunderbolt: switch: Demote a bunch of non-conformant kernel-doc headers
  thunderbolt: tb: Kernel-doc function headers should document their parameters
  thunderbolt: nhi: Demote some non-conformant kernel-doc headers
  thunderbolt: xdomain: Fix 'tb_unregister_service_driver()'s 'drv' param
  thunderbolt: eeprom: Demote non-conformant kernel-doc headers to standard comment blocks
  ...
parents fe6ad68e c6da62a2
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -49,6 +49,15 @@ Description: Holds a comma separated list of device unique_ids that
		If a device is authorized automatically during boot its
		boot attribute is set to 1.

What: /sys/bus/thunderbolt/devices/.../domainX/deauthorization
Date:		May 2021
KernelVersion:	5.12
Contact:	Mika Westerberg <mika.westerberg@linux.intel.com>
Description:	This attribute tells whether the system supports
		de-authorization of devices. Value of 1 means user can
		de-authorize PCIe tunnel by writing 0 to authorized
		attribute under each device.

What: /sys/bus/thunderbolt/devices/.../domainX/iommu_dma_protection
Date:		Mar 2019
KernelVersion:	4.21
@@ -76,6 +85,8 @@ Description: This attribute holds current Thunderbolt security level
		usbonly  Automatically tunnel USB controller of the
			 connected Thunderbolt dock (and Display Port). All
			 PCIe links downstream of the dock are removed.
		nopcie   USB4 system where PCIe tunneling is disabled from
			 the BIOS.
		=======  ==================================================

What: /sys/bus/thunderbolt/devices/.../authorized
@@ -84,22 +95,25 @@ KernelVersion: 4.13
Contact:	thunderbolt-software@lists.01.org
Description:	This attribute is used to authorize Thunderbolt devices
		after they have been connected. If the device is not
		authorized, no devices such as PCIe and Display port are
		available to the system.
		authorized, no PCIe devices are available to the system.

		Contents of this attribute will be 0 when the device is not
		yet authorized.

		Possible values are supported:

		==  ===========================================
		==  ===================================================
		0   The device will be de-authorized (only supported if
		    deauthorization attribute under domain contains 1)
		1   The device will be authorized and connected
		==  ===========================================
		==  ===================================================

		When key attribute contains 32 byte hex string the possible
		values are:

		==  ========================================================
		0   The device will be de-authorized (only supported if
		    deauthorization attribute under domain contains 1)
		1   The 32 byte hex string is added to the device NVM and
		    the device is authorized.
		2   Send a challenge based on the 32 byte hex string. If the
+23 −0
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ be DMA masters and thus read contents of the host memory without CPU and OS
knowing about it. There are ways to prevent this by setting up an IOMMU but
it is not always available for various reasons.

Some USB4 systems have a BIOS setting to disable PCIe tunneling. This is
treated as another security level (nopcie).

The security levels are as follows:

  none
@@ -77,6 +80,10 @@ The security levels are as follows:
    Display Port in a dock. All PCIe links downstream of the dock are
    removed.

  nopcie
    PCIe tunneling is disabled/forbidden from the BIOS. Available in some
    USB4 systems.

The current security level can be read from
``/sys/bus/thunderbolt/devices/domainX/security`` where ``domainX`` is
the Thunderbolt domain the host controller manages. There is typically
@@ -153,6 +160,22 @@ If the user still wants to connect the device they can either approve
the device without a key or write a new key and write 1 to the
``authorized`` file to get the new key stored on the device NVM.

De-authorizing devices
----------------------
It is possible to de-authorize devices by writing ``0`` to their
``authorized`` attribute. This requires support from the connection
manager implementation and can be checked by reading domain
``deauthorization`` attribute. If it reads ``1`` then the feature is
supported.

When a device is de-authorized the PCIe tunnel from the parent device
PCIe downstream (or root) port to the device PCIe upstream port is torn
down. This is essentially the same thing as PCIe hot-remove and the PCIe
toplogy in question will not be accessible anymore until the device is
authorized again. If there is storage such as NVMe or similar involved,
there is a risk for data loss if the filesystem on that storage is not
properly shut down. You have been warned!

DMA protection utilizing IOMMU
------------------------------
Recent systems from 2018 and forward with Thunderbolt ports may natively
+107 −12
Original line number Diff line number Diff line
@@ -281,10 +281,16 @@ bool osc_sb_apei_support_acked;
bool osc_pc_lpi_support_confirmed;
EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed);

/*
 * ACPI 6.4 Operating System Capabilities for USB.
 */
bool osc_sb_native_usb4_support_confirmed;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed);

static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
static void acpi_bus_osc_support(void)
static void acpi_bus_osc_negotiate_platform_control(void)
{
	u32 capbuf[2];
	u32 capbuf[2], *capbuf_ret;
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
@@ -317,21 +323,109 @@ static void acpi_bus_osc_support(void)
	if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;

	if (IS_ENABLED(CONFIG_USB4))
		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT;

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;

	if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
		return;

	capbuf_ret = context.ret.pointer;
	if (context.ret.length <= OSC_SUPPORT_DWORD) {
		kfree(context.ret.pointer);
		return;
	}

	/*
	 * Now run _OSC again with query flag clear and with the caps
	 * supported by both the OS and the platform.
	 */
	capbuf[OSC_QUERY_DWORD] = 0;
	capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD];
	kfree(context.ret.pointer);

	if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
		return;

	capbuf_ret = context.ret.pointer;
	if (context.ret.length > OSC_SUPPORT_DWORD) {
		osc_sb_apei_support_acked =
			capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
		osc_pc_lpi_support_confirmed =
			capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
		osc_sb_native_usb4_support_confirmed =
			capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT;
	}

	kfree(context.ret.pointer);
}
	/* do we need to check other returned cap? Sounds no */

/*
 * Native control of USB4 capabilities. If any of the tunneling bits is
 * set it means OS is in control and we use software based connection
 * manager.
 */
u32 osc_sb_native_usb4_control;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control);

static void acpi_bus_decode_usb_osc(const char *msg, u32 bits)
{
	printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg,
	       (bits & OSC_USB_USB3_TUNNELING) ? '+' : '-',
	       (bits & OSC_USB_DP_TUNNELING) ? '+' : '-',
	       (bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-',
	       (bits & OSC_USB_XDOMAIN) ? '+' : '-');
}

static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A";
static void acpi_bus_osc_negotiate_usb_control(void)
{
	u32 capbuf[3];
	struct acpi_osc_context context = {
		.uuid_str = sb_usb_uuid_str,
		.rev = 1,
		.cap.length = sizeof(capbuf),
		.cap.pointer = capbuf,
	};
	acpi_handle handle;
	acpi_status status;
	u32 control;

	if (!osc_sb_native_usb4_support_confirmed)
		return;

	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;

	control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING |
		  OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN;

	capbuf[OSC_QUERY_DWORD] = 0;
	capbuf[OSC_SUPPORT_DWORD] = 0;
	capbuf[OSC_CONTROL_DWORD] = control;

	status = acpi_run_osc(handle, &context);
	if (ACPI_FAILURE(status))
		return;

	if (context.ret.length != sizeof(capbuf)) {
		printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n");
		goto out_free;
	}

	osc_sb_native_usb4_control =
		control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD];

	acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control);
	acpi_bus_decode_usb_osc("USB4 _OSC: OS controls",
				osc_sb_native_usb4_control);

out_free:
	kfree(context.ret.pointer);
}

/* --------------------------------------------------------------------------
@@ -1168,7 +1262,8 @@ static int __init acpi_bus_init(void)
	 * _OSC method may exist in module level code,
	 * so it must be run after ACPI_FULL_INITIALIZATION
	 */
	acpi_bus_osc_support();
	acpi_bus_osc_negotiate_platform_control();
	acpi_bus_osc_negotiate_usb_control();

	/*
	 * _PDC control method may load dynamic SSDT tables,
+65 −0
Original line number Diff line number Diff line
@@ -115,3 +115,68 @@ void tb_acpi_add_links(struct tb_nhi *nhi)
	if (ACPI_FAILURE(status))
		dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
}

/**
 * tb_acpi_is_native() - Did the platform grant native TBT/USB4 control
 *
 * Returns %true if the platform granted OS native control over
 * TBT/USB4. In this case software based connection manager can be used,
 * otherwise there is firmware based connection manager running.
 */
bool tb_acpi_is_native(void)
{
	return osc_sb_native_usb4_support_confirmed &&
	       osc_sb_native_usb4_control;
}

/**
 * tb_acpi_may_tunnel_usb3() - Is USB3 tunneling allowed by the platform
 *
 * When software based connection manager is used, this function
 * returns %true if platform allows native USB3 tunneling.
 */
bool tb_acpi_may_tunnel_usb3(void)
{
	if (tb_acpi_is_native())
		return osc_sb_native_usb4_control & OSC_USB_USB3_TUNNELING;
	return true;
}

/**
 * tb_acpi_may_tunnel_dp() - Is DisplayPort tunneling allowed by the platform
 *
 * When software based connection manager is used, this function
 * returns %true if platform allows native DP tunneling.
 */
bool tb_acpi_may_tunnel_dp(void)
{
	if (tb_acpi_is_native())
		return osc_sb_native_usb4_control & OSC_USB_DP_TUNNELING;
	return true;
}

/**
 * tb_acpi_may_tunnel_pcie() - Is PCIe tunneling allowed by the platform
 *
 * When software based connection manager is used, this function
 * returns %true if platform allows native PCIe tunneling.
 */
bool tb_acpi_may_tunnel_pcie(void)
{
	if (tb_acpi_is_native())
		return osc_sb_native_usb4_control & OSC_USB_PCIE_TUNNELING;
	return true;
}

/**
 * tb_acpi_is_xdomain_allowed() - Are XDomain connections allowed
 *
 * When software based connection manager is used, this function
 * returns %true if platform allows XDomain connections.
 */
bool tb_acpi_is_xdomain_allowed(void)
{
	if (tb_acpi_is_native())
		return osc_sb_native_usb4_control & OSC_USB_XDOMAIN;
	return true;
}
+1 −1
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset)

/**
 * tb_switch_find_cap() - Find switch capability
 * @sw Switch to find the capability for
 * @sw: Switch to find the capability for
 * @cap: Capability to look
 *
 * Returns offset to start of capability or %-ENOENT if no such
Loading