diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2020-11-10 11:47:14 +0300 |
---|---|---|
committer | Mika Westerberg <mika.westerberg@linux.intel.com> | 2021-01-15 10:53:06 +0300 |
commit | 3da88be249973f7b74e7b24ed559e6abc2fc5af4 (patch) | |
tree | b6c607a9375ca1303f7502e329d4ea478ca017df /drivers/thunderbolt/switch.c | |
parent | fdb0887c5a87c3a98958d3c5c90f871aa6d1a562 (diff) | |
download | linux-3da88be249973f7b74e7b24ed559e6abc2fc5af4.tar.xz |
thunderbolt: Add support for de-authorizing devices
In some cases it is useful to be able de-authorize devices. For example
if user logs out the userspace can have a policy that disconnects PCIe
devices until logged in again. This is only possible for software based
connection manager as it directly controls the tunnels.
For this reason make the authorized attribute accept writing 0 which
makes the software connection manager to tear down the corresponding
PCIe tunnel. Userspace can check if this is supported by reading a new
domain attribute deauthorization, that holds 1 in that case.
While there correct tb_domain_approve_switch() kernel-doc and
description of authorized attribute to mention that it is only about
PCIe tunnels.
Cc: Christian Kellner <christian@kellner.me>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Yehezkel Bernat <YehezkelShB@gmail.com>
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r-- | drivers/thunderbolt/switch.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index ad992e6204d9..cdba05e72486 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1387,6 +1387,30 @@ static ssize_t authorized_show(struct device *dev, return sprintf(buf, "%u\n", sw->authorized); } +static int disapprove_switch(struct device *dev, void *not_used) +{ + struct tb_switch *sw; + + sw = tb_to_switch(dev); + if (sw && sw->authorized) { + int ret; + + /* First children */ + ret = device_for_each_child_reverse(&sw->dev, NULL, disapprove_switch); + if (ret) + return ret; + + ret = tb_domain_disapprove_switch(sw->tb, sw); + if (ret) + return ret; + + sw->authorized = 0; + kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE); + } + + return 0; +} + static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val) { int ret = -EINVAL; @@ -1394,10 +1418,18 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val) if (!mutex_trylock(&sw->tb->lock)) return restart_syscall(); - if (sw->authorized) + if (!!sw->authorized == !!val) goto unlock; switch (val) { + /* Disapprove switch */ + case 0: + if (tb_route(sw)) { + ret = disapprove_switch(&sw->dev, NULL); + goto unlock; + } + break; + /* Approve switch */ case 1: if (sw->key) |