summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-02-09 13:00:07 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-02-09 13:00:07 +0100
commit0a25669ba8a276f34dfa41f0eeae96ee9ecb2a17 (patch)
treecbccc015d6b755d8f35f37e9ee999891c58c21c8
parentfe6ad68e4a6235aef254233c2630096f1cc8e505 (diff)
parentc6da62a219d028de10f2e22e93a34c7ee2b88d03 (diff)
downloadlinux-0a25669ba8a276f34dfa41f0eeae96ee9ecb2a17.tar.gz
linux-0a25669ba8a276f34dfa41f0eeae96ee9ecb2a17.tar.bz2
linux-0a25669ba8a276f34dfa41f0eeae96ee9ecb2a17.zip
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 ...
-rw-r--r--Documentation/ABI/testing/sysfs-bus-thunderbolt22
-rw-r--r--Documentation/admin-guide/thunderbolt.rst23
-rw-r--r--drivers/acpi/bus.c119
-rw-r--r--drivers/thunderbolt/acpi.c65
-rw-r--r--drivers/thunderbolt/cap.c2
-rw-r--r--drivers/thunderbolt/ctl.c51
-rw-r--r--drivers/thunderbolt/dma_port.c2
-rw-r--r--drivers/thunderbolt/dma_test.c5
-rw-r--r--drivers/thunderbolt/domain.c48
-rw-r--r--drivers/thunderbolt/eeprom.c33
-rw-r--r--drivers/thunderbolt/icm.c10
-rw-r--r--drivers/thunderbolt/lc.c35
-rw-r--r--drivers/thunderbolt/nhi.c39
-rw-r--r--drivers/thunderbolt/path.c2
-rw-r--r--drivers/thunderbolt/switch.c82
-rw-r--r--drivers/thunderbolt/tb.c54
-rw-r--r--drivers/thunderbolt/tb.h22
-rw-r--r--drivers/thunderbolt/tb_regs.h1
-rw-r--r--drivers/thunderbolt/tunnel.c12
-rw-r--r--drivers/thunderbolt/usb4.c11
-rw-r--r--drivers/thunderbolt/xdomain.c15
-rw-r--r--include/linux/acpi.h10
-rw-r--r--include/linux/thunderbolt.h3
23 files changed, 585 insertions, 81 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt b/Documentation/ABI/testing/sysfs-bus-thunderbolt
index a91b4b24496e..d7f09d011b6d 100644
--- a/Documentation/ABI/testing/sysfs-bus-thunderbolt
+++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt
@@ -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
diff --git a/Documentation/admin-guide/thunderbolt.rst b/Documentation/admin-guide/thunderbolt.rst
index 613cb24c76c7..f18e881373c4 100644
--- a/Documentation/admin-guide/thunderbolt.rst
+++ b/Documentation/admin-guide/thunderbolt.rst
@@ -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
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 1682f8b454a2..9c3fe08e8f18 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -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 (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;
- }
+
+ 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;
}
- /* do we need to check other returned cap? Sounds no */
+
+ kfree(context.ret.pointer);
+}
+
+/*
+ * 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,
diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c
index b5442f979b4d..35fa17f7e599 100644
--- a/drivers/thunderbolt/acpi.c
+++ b/drivers/thunderbolt/acpi.c
@@ -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;
+}
diff --git a/drivers/thunderbolt/cap.c b/drivers/thunderbolt/cap.c
index 6f571e912cf2..8ecd610c62d5 100644
--- a/drivers/thunderbolt/cap.c
+++ b/drivers/thunderbolt/cap.c
@@ -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
diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index bac08b820015..f1aeaff9f368 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -20,7 +20,17 @@
#define TB_CTL_RETRIES 4
/**
- * struct tb_cfg - thunderbolt control channel
+ * struct tb_ctl - Thunderbolt control channel
+ * @nhi: Pointer to the NHI structure
+ * @tx: Transmit ring
+ * @rx: Receive ring
+ * @frame_pool: DMA pool for control messages
+ * @rx_packets: Received control messages
+ * @request_queue_lock: Lock protecting @request_queue
+ * @request_queue: List of outstanding requests
+ * @running: Is the control channel running at the moment
+ * @callback: Callback called when hotplug message is received
+ * @callback_data: Data passed to @callback
*/
struct tb_ctl {
struct tb_nhi *nhi;
@@ -338,7 +348,7 @@ static void tb_ctl_tx_callback(struct tb_ring *ring, struct ring_frame *frame,
tb_ctl_pkg_free(pkg);
}
-/**
+/*
* tb_cfg_tx() - transmit a packet on the control channel
*
* len must be a multiple of four.
@@ -375,7 +385,7 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len,
return res;
}
-/**
+/*
* tb_ctl_handle_event() - acknowledge a plug event, invoke ctl->callback
*/
static bool tb_ctl_handle_event(struct tb_ctl *ctl, enum tb_cfg_pkg_type type,
@@ -602,6 +612,9 @@ struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl,
/**
* tb_ctl_alloc() - allocate a control channel
+ * @nhi: Pointer to NHI
+ * @cb: Callback called for plug events
+ * @cb_data: Data passed to @cb
*
* cb will be invoked once for every hot plug event.
*
@@ -649,6 +662,7 @@ err:
/**
* tb_ctl_free() - free a control channel
+ * @ctl: Control channel to free
*
* Must be called after tb_ctl_stop.
*
@@ -677,6 +691,7 @@ void tb_ctl_free(struct tb_ctl *ctl)
/**
* tb_cfg_start() - start/resume the control channel
+ * @ctl: Control channel to start
*/
void tb_ctl_start(struct tb_ctl *ctl)
{
@@ -691,7 +706,8 @@ void tb_ctl_start(struct tb_ctl *ctl)
}
/**
- * control() - pause the control channel
+ * tb_ctrl_stop() - pause the control channel
+ * @ctl: Control channel to stop
*
* All invocations of ctl->callback will have finished after this method
* returns.
@@ -784,6 +800,9 @@ static bool tb_cfg_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg)
/**
* tb_cfg_reset() - send a reset packet and wait for a response
+ * @ctl: Control channel pointer
+ * @route: Router string for the router to send reset
+ * @timeout_msec: Timeout in ms how long to wait for the response
*
* If the switch at route is incorrectly configured then we will not receive a
* reply (even though the switch will reset). The caller should check for
@@ -820,9 +839,17 @@ struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route,
}
/**
- * tb_cfg_read() - read from config space into buffer
+ * tb_cfg_read_raw() - read from config space into buffer
+ * @ctl: Pointer to the control channel
+ * @buffer: Buffer where the data is read
+ * @route: Route string of the router
+ * @port: Port number when reading from %TB_CFG_PORT, %0 otherwise
+ * @space: Config space selector
+ * @offset: Dword word offset of the register to start reading
+ * @length: Number of dwords to read
+ * @timeout_msec: Timeout in ms how long to wait for the response
*
- * Offset and length are in dwords.
+ * Reads from router config space without translating the possible error.
*/
struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
u64 route, u32 port, enum tb_cfg_space space,
@@ -884,8 +911,16 @@ struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
/**
* tb_cfg_write() - write from buffer into config space
+ * @ctl: Pointer to the control channel
+ * @buffer: Data to write
+ * @route: Route string of the router
+ * @port: Port number when writing to %TB_CFG_PORT, %0 otherwise
+ * @space: Config space selector
+ * @offset: Dword word offset of the register to start writing
+ * @length: Number of dwords to write
+ * @timeout_msec: Timeout in ms how long to wait for the response
*
- * Offset and length are in dwords.
+ * Writes to router config space without translating the possible error.
*/
struct tb_cfg_result tb_cfg_write_raw(struct tb_ctl *ctl, const void *buffer,
u64 route, u32 port, enum tb_cfg_space space,
@@ -1022,6 +1057,8 @@ int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port,
/**
* tb_cfg_get_upstream_port() - get upstream port number of switch at route
+ * @ctl: Pointer to the control channel
+ * @route: Route string of the router
*
* Reads the first dword from the switches TB_CFG_SWITCH config area and
* returns the port number from which the reply originated.
diff --git a/drivers/thunderbolt/dma_port.c b/drivers/thunderbolt/dma_port.c
index 847dd07a7b17..7288aaf01ae6 100644
--- a/drivers/thunderbolt/dma_port.c
+++ b/drivers/thunderbolt/dma_port.c
@@ -335,6 +335,8 @@ static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address,
/* Write the block to MAIL_DATA registers */
ret = dma_port_write(sw->tb->ctl, buf, tb_route(sw), dma->port,
dma->base + MAIL_DATA, dwords, DMA_PORT_TIMEOUT);
+ if (ret)
+ return ret;
in = MAIL_IN_CMD_FLASH_WRITE << MAIL_IN_CMD_SHIFT;
diff --git a/drivers/thunderbolt/dma_test.c b/drivers/thunderbolt/dma_test.c
index f924423fa180..6debaf5a6604 100644
--- a/drivers/thunderbolt/dma_test.c
+++ b/drivers/thunderbolt/dma_test.c
@@ -7,7 +7,6 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
-#include <linux/acpi.h>
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/module.h>
@@ -299,14 +298,12 @@ static int dma_test_submit_tx(struct dma_test *dt, size_t npackets)
tf->frame.size = 0; /* means 4096 */
tf->dma_test = dt;
- tf->data = kzalloc(DMA_TEST_FRAME_SIZE, GFP_KERNEL);
+ tf->data = kmemdup(dma_test_pattern, DMA_TEST_FRAME_SIZE, GFP_KERNEL);
if (!tf->data) {
kfree(tf);
return -ENOMEM;
}
- memcpy(tf->data, dma_test_pattern, DMA_TEST_FRAME_SIZE);
-
dma_addr = dma_map_single(dma_dev, tf->data, DMA_TEST_FRAME_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(dma_dev, dma_addr)) {
diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index f0de94f7acbf..89ae614eaba2 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -118,6 +118,7 @@ static const char * const tb_security_names[] = {
[TB_SECURITY_SECURE] = "secure",
[TB_SECURITY_DPONLY] = "dponly",
[TB_SECURITY_USBONLY] = "usbonly",
+ [TB_SECURITY_NOPCIE] = "nopcie",
};
static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr,
@@ -238,6 +239,22 @@ err_free_str:
}
static DEVICE_ATTR_RW(boot_acl);
+static ssize_t deauthorization_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ const struct tb *tb = container_of(dev, struct tb, dev);
+ bool deauthorization = false;
+
+ /* Only meaningful if authorization is supported */
+ if (tb->security_level == TB_SECURITY_USER ||
+ tb->security_level == TB_SECURITY_SECURE)
+ deauthorization = !!tb->cm_ops->disapprove_switch;
+
+ return sprintf(buf, "%d\n", deauthorization);
+}
+static DEVICE_ATTR_RO(deauthorization);
+
static ssize_t iommu_dma_protection_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -267,6 +284,7 @@ static DEVICE_ATTR_RO(security);
static struct attribute *domain_attrs[] = {
&dev_attr_boot_acl.attr,
+ &dev_attr_deauthorization.attr,
&dev_attr_iommu_dma_protection.attr,
&dev_attr_security.attr,
NULL,
@@ -289,7 +307,7 @@ static umode_t domain_attr_is_visible(struct kobject *kobj,
return attr->mode;
}
-static struct attribute_group domain_attr_group = {
+static const struct attribute_group domain_attr_group = {
.is_visible = domain_attr_is_visible,
.attrs = domain_attrs,
};
@@ -394,7 +412,9 @@ static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
switch (type) {
case TB_CFG_PKG_XDOMAIN_REQ:
case TB_CFG_PKG_XDOMAIN_RESP:
- return tb_xdomain_handle_request(tb, type, buf, size);
+ if (tb_is_xdomain_enabled())
+ return tb_xdomain_handle_request(tb, type, buf, size);
+ break;
default:
tb->cm_ops->handle_event(tb, type, buf, size);
@@ -441,6 +461,9 @@ int tb_domain_add(struct tb *tb)
goto err_ctl_stop;
}
+ tb_dbg(tb, "security level set to %s\n",
+ tb_security_names[tb->security_level]);
+
ret = device_add(&tb->dev);
if (ret)
goto err_ctl_stop;
@@ -602,13 +625,30 @@ int tb_domain_runtime_resume(struct tb *tb)
}
/**
+ * tb_domain_disapprove_switch() - Disapprove switch
+ * @tb: Domain the switch belongs to
+ * @sw: Switch to disapprove
+ *
+ * This will disconnect PCIe tunnel from parent to this @sw.
+ *
+ * Return: %0 on success and negative errno in case of failure.
+ */
+int tb_domain_disapprove_switch(struct tb *tb, struct tb_switch *sw)
+{
+ if (!tb->cm_ops->disapprove_switch)
+ return -EPERM;
+
+ return tb->cm_ops->disapprove_switch(tb, sw);
+}
+
+/**
* tb_domain_approve_switch() - Approve switch
* @tb: Domain the switch belongs to
* @sw: Switch to approve
*
* This will approve switch by connection manager specific means. In
- * case of success the connection manager will create tunnels for all
- * supported protocols.
+ * case of success the connection manager will create PCIe tunnel from
+ * parent to @sw.
*/
int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw)
{
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 0c8471be3e32..dd03d3096653 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include "tb.h"
-/**
+/*
* tb_eeprom_ctl_write() - write control word
*/
static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
@@ -20,7 +20,7 @@ static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1);
}
-/**
+/*
* tb_eeprom_ctl_write() - read control word
*/
static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
@@ -33,7 +33,7 @@ enum tb_eeprom_transfer {
TB_EEPROM_OUT,
};
-/**
+/*
* tb_eeprom_active - enable rom access
*
* WARNING: Always disable access after usage. Otherwise the controller will
@@ -62,7 +62,7 @@ static int tb_eeprom_active(struct tb_switch *sw, bool enable)
}
}
-/**
+/*
* tb_eeprom_transfer - transfer one bit
*
* If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->data_in.
@@ -90,7 +90,7 @@ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl,
return tb_eeprom_ctl_write(sw, ctl);
}
-/**
+/*
* tb_eeprom_out - write one byte to the bus
*/
static int tb_eeprom_out(struct tb_switch *sw, u8 val)
@@ -110,7 +110,7 @@ static int tb_eeprom_out(struct tb_switch *sw, u8 val)
return 0;
}
-/**
+/*
* tb_eeprom_in - read one byte from the bus
*/
static int tb_eeprom_in(struct tb_switch *sw, u8 *val)
@@ -131,7 +131,7 @@ static int tb_eeprom_in(struct tb_switch *sw, u8 *val)
return 0;
}
-/**
+/*
* tb_eeprom_get_drom_offset - get drom offset within eeprom
*/
static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
@@ -162,7 +162,7 @@ static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
return 0;
}
-/**
+/*
* tb_eeprom_read_n - read count bytes from offset into val
*/
static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
@@ -279,7 +279,9 @@ struct tb_drom_entry_port {
/**
- * tb_drom_read_uid_only - read uid directly from drom
+ * tb_drom_read_uid_only() - Read UID directly from DROM
+ * @sw: Router whose UID to read
+ * @uid: UID is placed here
*
* Does not use the cached copy in sw->drom. Used during resume to check switch
* identity.
@@ -374,7 +376,7 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw,
return 0;
}
-/**
+/*
* tb_drom_parse_entries - parse the linked list of drom entries
*
* Drom must have been copied to sw->drom.
@@ -410,7 +412,7 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
return 0;
}
-/**
+/*
* tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
*/
static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
@@ -520,7 +522,14 @@ static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
}
/**
- * tb_drom_read - copy drom to sw->drom and parse it
+ * tb_drom_read() - Copy DROM to sw->drom and parse it
+ * @sw: Router whose DROM to read and parse
+ *
+ * This function reads router DROM and if successful parses the entries and
+ * populates the fields in @sw accordingly. Can be called for any router
+ * generation.
+ *
+ * Returns %0 in case of success and negative errno otherwise.
*/
int tb_drom_read(struct tb_switch *sw)
{
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
index b8c4159bc32d..f6f605d48371 100644
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -85,8 +85,8 @@ struct usb4_switch_nvm_auth {
* @set_uuid: Set UUID for the root switch (optional)
* @device_connected: Handle device connected ICM message
* @device_disconnected: Handle device disconnected ICM message
- * @xdomain_connected - Handle XDomain connected ICM message
- * @xdomain_disconnected - Handle XDomain disconnected ICM message
+ * @xdomain_connected: Handle XDomain connected ICM message
+ * @xdomain_disconnected: Handle XDomain disconnected ICM message
* @rtd3_veto: Handle RTD3 veto notification ICM message
*/
struct icm {
@@ -1701,10 +1701,12 @@ static void icm_handle_notification(struct work_struct *work)
icm->device_disconnected(tb, n->pkg);
break;
case ICM_EVENT_XDOMAIN_CONNECTED:
- icm->xdomain_connected(tb, n->pkg);
+ if (tb_is_xdomain_enabled())
+ icm->xdomain_connected(tb, n->pkg);
break;
case ICM_EVENT_XDOMAIN_DISCONNECTED:
- icm->xdomain_disconnected(tb, n->pkg);
+ if (tb_is_xdomain_enabled())
+ icm->xdomain_disconnected(tb, n->pkg);
break;
case ICM_EVENT_RTD3_VETO:
icm->rtd3_veto(tb, n->pkg);
diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c
index 41e6c738f6c8..bc671730a11f 100644
--- a/drivers/thunderbolt/lc.c
+++ b/drivers/thunderbolt/lc.c
@@ -158,6 +158,41 @@ void tb_lc_unconfigure_xdomain(struct tb_port *port)
tb_lc_set_xdomain_configured(port, false);
}
+/**
+ * tb_lc_start_lane_initialization() - Start lane initialization