diff options
| author | Yehezkel Bernat <yehezkel.bernat@intel.com> | 2018-01-22 05:50:09 -0500 |
|---|---|---|
| committer | Mika Westerberg <mika.westerberg@linux.intel.com> | 2018-03-09 04:54:11 -0500 |
| commit | 14862ee308bbcaae0ac9927b6cbccccb51386b6c (patch) | |
| tree | 5052d4e77b83a46557e61c5e2e6c7af66e72e804 | |
| parent | 3080e197e936ab7cdcf66cacec22abe5c6c1007a (diff) | |
thunderbolt: Add 'boot' attribute for devices
In various cases, Thunderbolt device can be connected by ICM on boot
without waiting for approval from user. Most cases are related to
OEM-specific BIOS configurations. This information is interesting for
user-space as if the device isn't in SW ACL, it may create a friction in
the user experience where the device is automatically authorized if it's
connected on boot but requires an explicit user action if connected
after OS is up. User-space can use this information to suggest adding
the device to SW ACL for auto-authorization on later connections.
Signed-off-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
| -rw-r--r-- | Documentation/ABI/testing/sysfs-bus-thunderbolt | 7 | ||||
| -rw-r--r-- | drivers/thunderbolt/icm.c | 12 | ||||
| -rw-r--r-- | drivers/thunderbolt/switch.c | 14 | ||||
| -rw-r--r-- | drivers/thunderbolt/tb.h | 2 | ||||
| -rw-r--r-- | drivers/thunderbolt/tb_msgs.h | 1 |
5 files changed, 32 insertions, 4 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt b/Documentation/ABI/testing/sysfs-bus-thunderbolt index 93798c02e28b..1f145b727d76 100644 --- a/Documentation/ABI/testing/sysfs-bus-thunderbolt +++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt | |||
| @@ -38,6 +38,13 @@ Description: This attribute is used to authorize Thunderbolt devices | |||
| 38 | the device did not contain a key at all, and | 38 | the device did not contain a key at all, and |
| 39 | EKEYREJECTED if the challenge response did not match. | 39 | EKEYREJECTED if the challenge response did not match. |
| 40 | 40 | ||
| 41 | What: /sys/bus/thunderbolt/devices/.../boot | ||
| 42 | Date: Jun 2018 | ||
| 43 | KernelVersion: 4.17 | ||
| 44 | Contact: thunderbolt-software@lists.01.org | ||
| 45 | Description: This attribute contains 1 if Thunderbolt device was already | ||
| 46 | authorized on boot and 0 otherwise. | ||
| 47 | |||
| 41 | What: /sys/bus/thunderbolt/devices/.../key | 48 | What: /sys/bus/thunderbolt/devices/.../key |
| 42 | Date: Sep 2017 | 49 | Date: Sep 2017 |
| 43 | KernelVersion: 4.13 | 50 | KernelVersion: 4.13 |
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index 5d3cd740b71f..bece5540b06b 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c | |||
| @@ -402,7 +402,7 @@ static int icm_fr_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) | |||
| 402 | static void add_switch(struct tb_switch *parent_sw, u64 route, | 402 | static void add_switch(struct tb_switch *parent_sw, u64 route, |
| 403 | const uuid_t *uuid, u8 connection_id, u8 connection_key, | 403 | const uuid_t *uuid, u8 connection_id, u8 connection_key, |
| 404 | u8 link, u8 depth, enum tb_security_level security_level, | 404 | u8 link, u8 depth, enum tb_security_level security_level, |
| 405 | bool authorized) | 405 | bool authorized, bool boot) |
| 406 | { | 406 | { |
| 407 | struct tb_switch *sw; | 407 | struct tb_switch *sw; |
| 408 | 408 | ||
| @@ -417,6 +417,7 @@ static void add_switch(struct tb_switch *parent_sw, u64 route, | |||
| 417 | sw->depth = depth; | 417 | sw->depth = depth; |
| 418 | sw->authorized = authorized; | 418 | sw->authorized = authorized; |
| 419 | sw->security_level = security_level; | 419 | sw->security_level = security_level; |
| 420 | sw->boot = boot; | ||
| 420 | 421 | ||
| 421 | /* Link the two switches now */ | 422 | /* Link the two switches now */ |
| 422 | tb_port_at(route, parent_sw)->remote = tb_upstream_port(sw); | 423 | tb_port_at(route, parent_sw)->remote = tb_upstream_port(sw); |
| @@ -431,7 +432,7 @@ static void add_switch(struct tb_switch *parent_sw, u64 route, | |||
| 431 | 432 | ||
| 432 | static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, | 433 | static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, |
| 433 | u64 route, u8 connection_id, u8 connection_key, | 434 | u64 route, u8 connection_id, u8 connection_key, |
| 434 | u8 link, u8 depth) | 435 | u8 link, u8 depth, bool boot) |
| 435 | { | 436 | { |
| 436 | /* Disconnect from parent */ | 437 | /* Disconnect from parent */ |
| 437 | tb_port_at(tb_route(sw), parent_sw)->remote = NULL; | 438 | tb_port_at(tb_route(sw), parent_sw)->remote = NULL; |
| @@ -445,6 +446,7 @@ static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, | |||
| 445 | sw->connection_key = connection_key; | 446 | sw->connection_key = connection_key; |
| 446 | sw->link = link; | 447 | sw->link = link; |
| 447 | sw->depth = depth; | 448 | sw->depth = depth; |
| 449 | sw->boot = boot; | ||
| 448 | 450 | ||
| 449 | /* This switch still exists */ | 451 | /* This switch still exists */ |
| 450 | sw->is_unplugged = false; | 452 | sw->is_unplugged = false; |
| @@ -504,6 +506,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) | |||
| 504 | bool authorized = false; | 506 | bool authorized = false; |
| 505 | struct tb_xdomain *xd; | 507 | struct tb_xdomain *xd; |
| 506 | u8 link, depth; | 508 | u8 link, depth; |
| 509 | bool boot; | ||
| 507 | u64 route; | 510 | u64 route; |
| 508 | int ret; | 511 | int ret; |
| 509 | 512 | ||
| @@ -513,6 +516,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) | |||
| 513 | authorized = pkg->link_info & ICM_LINK_INFO_APPROVED; | 516 | authorized = pkg->link_info & ICM_LINK_INFO_APPROVED; |
| 514 | security_level = (pkg->hdr.flags & ICM_FLAGS_SLEVEL_MASK) >> | 517 | security_level = (pkg->hdr.flags & ICM_FLAGS_SLEVEL_MASK) >> |
| 515 | ICM_FLAGS_SLEVEL_SHIFT; | 518 | ICM_FLAGS_SLEVEL_SHIFT; |
| 519 | boot = pkg->link_info & ICM_LINK_INFO_BOOT; | ||
| 516 | 520 | ||
| 517 | if (pkg->link_info & ICM_LINK_INFO_REJECTED) { | 521 | if (pkg->link_info & ICM_LINK_INFO_REJECTED) { |
| 518 | tb_info(tb, "switch at %u.%u was rejected by ICM firmware because topology limit exceeded\n", | 522 | tb_info(tb, "switch at %u.%u was rejected by ICM firmware because topology limit exceeded\n", |
| @@ -546,7 +550,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) | |||
| 546 | if (sw->depth == depth && sw_phy_port == phy_port && | 550 | if (sw->depth == depth && sw_phy_port == phy_port && |
| 547 | !!sw->authorized == authorized) { | 551 | !!sw->authorized == authorized) { |
| 548 | update_switch(parent_sw, sw, route, pkg->connection_id, | 552 | update_switch(parent_sw, sw, route, pkg->connection_id, |
| 549 | pkg->connection_key, link, depth); | 553 | pkg->connection_key, link, depth, boot); |
| 550 | tb_switch_put(sw); | 554 | tb_switch_put(sw); |
| 551 | return; | 555 | return; |
| 552 | } | 556 | } |
| @@ -595,7 +599,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) | |||
| 595 | 599 | ||
| 596 | add_switch(parent_sw, route, &pkg->ep_uuid, pkg->connection_id, | 600 | add_switch(parent_sw, route, &pkg->ep_uuid, pkg->connection_id, |
| 597 | pkg->connection_key, link, depth, security_level, | 601 | pkg->connection_key, link, depth, security_level, |
| 598 | authorized); | 602 | authorized, boot); |
| 599 | 603 | ||
| 600 | tb_switch_put(parent_sw); | 604 | tb_switch_put(parent_sw); |
| 601 | } | 605 | } |
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 4e2b2097bbfc..e9e30aaab2a3 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c | |||
| @@ -775,6 +775,15 @@ static ssize_t authorized_store(struct device *dev, | |||
| 775 | } | 775 | } |
| 776 | static DEVICE_ATTR_RW(authorized); | 776 | static DEVICE_ATTR_RW(authorized); |
| 777 | 777 | ||
| 778 | static ssize_t boot_show(struct device *dev, struct device_attribute *attr, | ||
| 779 | char *buf) | ||
| 780 | { | ||
| 781 | struct tb_switch *sw = tb_to_switch(dev); | ||
| 782 | |||
| 783 | return sprintf(buf, "%u\n", sw->boot); | ||
| 784 | } | ||
| 785 | static DEVICE_ATTR_RO(boot); | ||
| 786 | |||
| 778 | static ssize_t device_show(struct device *dev, struct device_attribute *attr, | 787 | static ssize_t device_show(struct device *dev, struct device_attribute *attr, |
| 779 | char *buf) | 788 | char *buf) |
| 780 | { | 789 | { |
| @@ -951,6 +960,7 @@ static DEVICE_ATTR_RO(unique_id); | |||
| 951 | 960 | ||
| 952 | static struct attribute *switch_attrs[] = { | 961 | static struct attribute *switch_attrs[] = { |
| 953 | &dev_attr_authorized.attr, | 962 | &dev_attr_authorized.attr, |
| 963 | &dev_attr_boot.attr, | ||
| 954 | &dev_attr_device.attr, | 964 | &dev_attr_device.attr, |
| 955 | &dev_attr_device_name.attr, | 965 | &dev_attr_device_name.attr, |
| 956 | &dev_attr_key.attr, | 966 | &dev_attr_key.attr, |
| @@ -979,6 +989,10 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, | |||
| 979 | if (sw->dma_port) | 989 | if (sw->dma_port) |
| 980 | return attr->mode; | 990 | return attr->mode; |
| 981 | return 0; | 991 | return 0; |
| 992 | } else if (attr == &dev_attr_boot.attr) { | ||
| 993 | if (tb_route(sw)) | ||
| 994 | return attr->mode; | ||
| 995 | return 0; | ||
| 982 | } | 996 | } |
| 983 | 997 | ||
| 984 | return sw->safe_mode ? 0 : attr->mode; | 998 | return sw->safe_mode ? 0 : attr->mode; |
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 2cd6085a6e10..9c9cef875ca8 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h | |||
| @@ -66,6 +66,7 @@ struct tb_switch_nvm { | |||
| 66 | * @nvm: Pointer to the NVM if the switch has one (%NULL otherwise) | 66 | * @nvm: Pointer to the NVM if the switch has one (%NULL otherwise) |
| 67 | * @no_nvm_upgrade: Prevent NVM upgrade of this switch | 67 | * @no_nvm_upgrade: Prevent NVM upgrade of this switch |
| 68 | * @safe_mode: The switch is in safe-mode | 68 | * @safe_mode: The switch is in safe-mode |
| 69 | * @boot: Whether the switch was already authorized on boot or not | ||
| 69 | * @authorized: Whether the switch is authorized by user or policy | 70 | * @authorized: Whether the switch is authorized by user or policy |
| 70 | * @work: Work used to automatically authorize a switch | 71 | * @work: Work used to automatically authorize a switch |
| 71 | * @security_level: Switch supported security level | 72 | * @security_level: Switch supported security level |
| @@ -99,6 +100,7 @@ struct tb_switch { | |||
| 99 | struct tb_switch_nvm *nvm; | 100 | struct tb_switch_nvm *nvm; |
| 100 | bool no_nvm_upgrade; | 101 | bool no_nvm_upgrade; |
| 101 | bool safe_mode; | 102 | bool safe_mode; |
| 103 | bool boot; | ||
| 102 | unsigned int authorized; | 104 | unsigned int authorized; |
| 103 | struct work_struct work; | 105 | struct work_struct work; |
| 104 | enum tb_security_level security_level; | 106 | enum tb_security_level security_level; |
diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h index 931db2a7c7b3..9f52f842257a 100644 --- a/drivers/thunderbolt/tb_msgs.h +++ b/drivers/thunderbolt/tb_msgs.h | |||
| @@ -179,6 +179,7 @@ struct icm_fr_event_device_connected { | |||
| 179 | #define ICM_LINK_INFO_DEPTH_MASK GENMASK(7, 4) | 179 | #define ICM_LINK_INFO_DEPTH_MASK GENMASK(7, 4) |
| 180 | #define ICM_LINK_INFO_APPROVED BIT(8) | 180 | #define ICM_LINK_INFO_APPROVED BIT(8) |
| 181 | #define ICM_LINK_INFO_REJECTED BIT(9) | 181 | #define ICM_LINK_INFO_REJECTED BIT(9) |
| 182 | #define ICM_LINK_INFO_BOOT BIT(10) | ||
| 182 | 183 | ||
| 183 | struct icm_fr_pkg_approve_device { | 184 | struct icm_fr_pkg_approve_device { |
| 184 | struct icm_pkg_header hdr; | 185 | struct icm_pkg_header hdr; |
