| .. | .. |
|---|
| 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 | } |
|---|