summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-13 12:17:14 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-13 12:17:14 +0200
commit5367f82a212305c35b35303a8a21ca348f653ca3 (patch)
tree98e88cbd6f40762b11802624022eaccf08051c39 /drivers/thunderbolt/switch.c
parent9bc46a12c53d8268392774172742aa9e5dd6953d (diff)
parent6f3badead6a078cf3c71f381f9d84ac922984a00 (diff)
Merge tag 'thunderbolt-for-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next
Mika writes: thunderbolt: Changes for v5.13 merge window This includes following Thunderbolt/USB4 changes for v5.13 merge window: * Debugfs improvements * Align the inter-domain (peer-to-peer) support with the USB4 inter-domain spec for better interoperability * Add support for USB4 DROM and the new product descriptor * More KUnit tests * Detailed uevent for routers * Few miscellaneous improvements All these have been in linux-next without reported issues. * tag 'thunderbolt-for-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: (24 commits) thunderbolt: Hide authorized attribute if router does not support PCIe tunnels thunderbolt: Add details to router uevent thunderbolt: Unlock on error path in tb_domain_add() thunderbolt: Add support for USB4 DROM thunderbolt: Check quirks in tb_switch_add() thunderbolt: Add KUnit tests for DMA tunnels thunderbolt: Add KUnit tests for XDomain properties net: thunderbolt: Align the driver to the USB4 networking spec thunderbolt: Allow multiple DMA tunnels over a single XDomain connection thunderbolt: Drop unused tb_port_set_initial_credits() thunderbolt: Use dedicated flow control for DMA tunnels thunderbolt: Add support for maxhopid XDomain property thunderbolt: Add tb_property_copy_dir() thunderbolt: Align XDomain protocol timeouts with the spec thunderbolt: Use pseudo-random number as initial property block generation thunderbolt: Do not re-establish XDomain DMA paths automatically thunderbolt: Add more logging to XDomain connections Documentation / thunderbolt: Drop speed/lanes entries for XDomain thunderbolt: Decrease control channel timeout for software connection manager thunderbolt: Do not pass timeout for tb_cfg_reset() ...
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 2a95b4ce06c0..e73cd296db7e 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -627,28 +627,6 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits)
}
/**
- * tb_port_set_initial_credits() - Set initial port link credits allocated
- * @port: Port to set the initial credits
- * @credits: Number of credits to to allocate
- *
- * Set initial credits value to be used for ingress shared buffering.
- */
-int tb_port_set_initial_credits(struct tb_port *port, u32 credits)
-{
- u32 data;
- int ret;
-
- ret = tb_port_read(port, &data, TB_CFG_PORT, ADP_CS_5, 1);
- if (ret)
- return ret;
-
- data &= ~ADP_CS_5_LCA_MASK;
- data |= (credits << ADP_CS_5_LCA_SHIFT) & ADP_CS_5_LCA_MASK;
-
- return tb_port_write(port, &data, TB_CFG_PORT, ADP_CS_5, 1);
-}
-
-/**
* tb_port_clear_counter() - clear a counter in TB_CFG_COUNTER
* @port: Port whose counters to clear
* @counter: Counter index to clear
@@ -1331,7 +1309,7 @@ int tb_switch_reset(struct tb_switch *sw)
TB_CFG_SWITCH, 2, 2);
if (res.err)
return res.err;
- res = tb_cfg_reset(sw->tb->ctl, tb_route(sw), TB_CFG_DEFAULT_TIMEOUT);
+ res = tb_cfg_reset(sw->tb->ctl, tb_route(sw));
if (res.err > 0)
return -EIO;
return res.err;
@@ -1762,6 +1740,18 @@ static struct attribute *switch_attrs[] = {
NULL,
};
+static bool has_port(const struct tb_switch *sw, enum tb_port_type type)
+{
+ const struct tb_port *port;
+
+ tb_switch_for_each_port(sw, port) {
+ if (!port->disabled && port->config.type == type)
+ return true;
+ }
+
+ return false;
+}
+
static umode_t switch_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
@@ -1770,7 +1760,8 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_authorized.attr) {
if (sw->tb->security_level == TB_SECURITY_NOPCIE ||
- sw->tb->security_level == TB_SECURITY_DPONLY)
+ sw->tb->security_level == TB_SECURITY_DPONLY ||
+ !has_port(sw, TB_TYPE_PCIE_UP))
return 0;
} else if (attr == &dev_attr_device.attr) {
if (!sw->device)
@@ -1849,6 +1840,39 @@ static void tb_switch_release(struct device *dev)
kfree(sw);
}
+static int tb_switch_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct tb_switch *sw = tb_to_switch(dev);
+ const char *type;
+
+ if (sw->config.thunderbolt_version == USB4_VERSION_1_0) {
+ if (add_uevent_var(env, "USB4_VERSION=1.0"))
+ return -ENOMEM;
+ }
+
+ if (!tb_route(sw)) {
+ type = "host";
+ } else {
+ const struct tb_port *port;
+ bool hub = false;
+
+ /* Device is hub if it has any downstream ports */
+ tb_switch_for_each_port(sw, port) {
+ if (!port->disabled && !tb_is_upstream_port(port) &&
+ tb_port_is_null(port)) {
+ hub = true;
+ break;
+ }
+ }
+
+ type = hub ? "hub" : "device";
+ }
+
+ if (add_uevent_var(env, "USB4_TYPE=%s", type))
+ return -ENOMEM;
+ return 0;
+}
+
/*
* Currently only need to provide the callbacks. Everything else is handled
* in the connection manager.
@@ -1882,6 +1906,7 @@ static const struct dev_pm_ops tb_switch_pm_ops = {
struct device_type tb_switch_type = {
.name = "thunderbolt_device",
.release = tb_switch_release,
+ .uevent = tb_switch_uevent,
.pm = &tb_switch_pm_ops,
};
@@ -2542,6 +2567,8 @@ int tb_switch_add(struct tb_switch *sw)
}
tb_sw_dbg(sw, "uid: %#llx\n", sw->uid);
+ tb_check_quirks(sw);
+
ret = tb_switch_set_uuid(sw);
if (ret) {
dev_err(&sw->dev, "failed to set UUID\n");