.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Thunderbolt bus support |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2017, Intel Corporation |
---|
5 | | - * Author: Mika Westerberg <mika.westerberg@linux.intel.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
| 6 | + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #include <linux/device.h> |
---|
| 10 | +#include <linux/dmar.h> |
---|
13 | 11 | #include <linux/idr.h> |
---|
| 12 | +#include <linux/iommu.h> |
---|
14 | 13 | #include <linux/module.h> |
---|
15 | 14 | #include <linux/pm_runtime.h> |
---|
16 | 15 | #include <linux/slab.h> |
---|
.. | .. |
---|
148 | 147 | |
---|
149 | 148 | for (ret = 0, i = 0; i < tb->nboot_acl; i++) { |
---|
150 | 149 | if (!uuid_is_null(&uuids[i])) |
---|
151 | | - ret += snprintf(buf + ret, PAGE_SIZE - ret, "%pUb", |
---|
| 150 | + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%pUb", |
---|
152 | 151 | &uuids[i]); |
---|
153 | 152 | |
---|
154 | | - ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s", |
---|
| 153 | + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s", |
---|
155 | 154 | i < tb->nboot_acl - 1 ? "," : "\n"); |
---|
156 | 155 | } |
---|
157 | 156 | |
---|
.. | .. |
---|
239 | 238 | } |
---|
240 | 239 | static DEVICE_ATTR_RW(boot_acl); |
---|
241 | 240 | |
---|
| 241 | +static ssize_t iommu_dma_protection_show(struct device *dev, |
---|
| 242 | + struct device_attribute *attr, |
---|
| 243 | + char *buf) |
---|
| 244 | +{ |
---|
| 245 | + /* |
---|
| 246 | + * Kernel DMA protection is a feature where Thunderbolt security is |
---|
| 247 | + * handled natively using IOMMU. It is enabled when IOMMU is |
---|
| 248 | + * enabled and ACPI DMAR table has DMAR_PLATFORM_OPT_IN set. |
---|
| 249 | + */ |
---|
| 250 | + return sprintf(buf, "%d\n", |
---|
| 251 | + iommu_present(&pci_bus_type) && dmar_platform_optin()); |
---|
| 252 | +} |
---|
| 253 | +static DEVICE_ATTR_RO(iommu_dma_protection); |
---|
| 254 | + |
---|
242 | 255 | static ssize_t security_show(struct device *dev, struct device_attribute *attr, |
---|
243 | 256 | char *buf) |
---|
244 | 257 | { |
---|
.. | .. |
---|
254 | 267 | |
---|
255 | 268 | static struct attribute *domain_attrs[] = { |
---|
256 | 269 | &dev_attr_boot_acl.attr, |
---|
| 270 | + &dev_attr_iommu_dma_protection.attr, |
---|
257 | 271 | &dev_attr_security.attr, |
---|
258 | 272 | NULL, |
---|
259 | 273 | }; |
---|
.. | .. |
---|
261 | 275 | static umode_t domain_attr_is_visible(struct kobject *kobj, |
---|
262 | 276 | struct attribute *attr, int n) |
---|
263 | 277 | { |
---|
264 | | - struct device *dev = container_of(kobj, struct device, kobj); |
---|
| 278 | + struct device *dev = kobj_to_dev(kobj); |
---|
265 | 279 | struct tb *tb = container_of(dev, struct tb, dev); |
---|
266 | 280 | |
---|
267 | 281 | if (attr == &dev_attr_boot_acl.attr) { |
---|
.. | .. |
---|
441 | 455 | /* This starts event processing */ |
---|
442 | 456 | mutex_unlock(&tb->lock); |
---|
443 | 457 | |
---|
| 458 | + device_init_wakeup(&tb->dev, true); |
---|
| 459 | + |
---|
444 | 460 | pm_runtime_no_callbacks(&tb->dev); |
---|
445 | 461 | pm_runtime_set_active(&tb->dev); |
---|
446 | 462 | pm_runtime_enable(&tb->dev); |
---|
.. | .. |
---|
528 | 544 | int tb_domain_suspend(struct tb *tb) |
---|
529 | 545 | { |
---|
530 | 546 | return tb->cm_ops->suspend ? tb->cm_ops->suspend(tb) : 0; |
---|
| 547 | +} |
---|
| 548 | + |
---|
| 549 | +int tb_domain_freeze_noirq(struct tb *tb) |
---|
| 550 | +{ |
---|
| 551 | + int ret = 0; |
---|
| 552 | + |
---|
| 553 | + mutex_lock(&tb->lock); |
---|
| 554 | + if (tb->cm_ops->freeze_noirq) |
---|
| 555 | + ret = tb->cm_ops->freeze_noirq(tb); |
---|
| 556 | + if (!ret) |
---|
| 557 | + tb_ctl_stop(tb->ctl); |
---|
| 558 | + mutex_unlock(&tb->lock); |
---|
| 559 | + |
---|
| 560 | + return ret; |
---|
| 561 | +} |
---|
| 562 | + |
---|
| 563 | +int tb_domain_thaw_noirq(struct tb *tb) |
---|
| 564 | +{ |
---|
| 565 | + int ret = 0; |
---|
| 566 | + |
---|
| 567 | + mutex_lock(&tb->lock); |
---|
| 568 | + tb_ctl_start(tb->ctl); |
---|
| 569 | + if (tb->cm_ops->thaw_noirq) |
---|
| 570 | + ret = tb->cm_ops->thaw_noirq(tb); |
---|
| 571 | + mutex_unlock(&tb->lock); |
---|
| 572 | + |
---|
| 573 | + return ret; |
---|
531 | 574 | } |
---|
532 | 575 | |
---|
533 | 576 | void tb_domain_complete(struct tb *tb) |
---|
.. | .. |
---|
664 | 707 | } |
---|
665 | 708 | |
---|
666 | 709 | shash->tfm = tfm; |
---|
667 | | - shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
---|
668 | 710 | |
---|
669 | 711 | memset(hmac, 0, sizeof(hmac)); |
---|
670 | 712 | ret = crypto_shash_digest(shash, challenge, sizeof(hmac), hmac); |
---|
.. | .. |
---|
785 | 827 | { |
---|
786 | 828 | int ret; |
---|
787 | 829 | |
---|
| 830 | + tb_test_init(); |
---|
| 831 | + |
---|
| 832 | + tb_debugfs_init(); |
---|
788 | 833 | ret = tb_xdomain_init(); |
---|
789 | 834 | if (ret) |
---|
790 | | - return ret; |
---|
| 835 | + goto err_debugfs; |
---|
791 | 836 | ret = bus_register(&tb_bus_type); |
---|
792 | 837 | if (ret) |
---|
793 | | - tb_xdomain_exit(); |
---|
| 838 | + goto err_xdomain; |
---|
| 839 | + |
---|
| 840 | + return 0; |
---|
| 841 | + |
---|
| 842 | +err_xdomain: |
---|
| 843 | + tb_xdomain_exit(); |
---|
| 844 | +err_debugfs: |
---|
| 845 | + tb_debugfs_exit(); |
---|
| 846 | + tb_test_exit(); |
---|
794 | 847 | |
---|
795 | 848 | return ret; |
---|
796 | 849 | } |
---|
.. | .. |
---|
799 | 852 | { |
---|
800 | 853 | bus_unregister(&tb_bus_type); |
---|
801 | 854 | ida_destroy(&tb_domain_ida); |
---|
802 | | - tb_switch_exit(); |
---|
| 855 | + tb_nvm_exit(); |
---|
803 | 856 | tb_xdomain_exit(); |
---|
| 857 | + tb_debugfs_exit(); |
---|
| 858 | + tb_test_exit(); |
---|
804 | 859 | } |
---|