diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2017-06-06 14:25:16 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-06-09 11:42:43 +0200 |
commit | f67cf491175a315ca86c9b349708bfed7b1f40c1 (patch) | |
tree | 7b9b16deadbf5941b14cc16086eababa2dc70523 /drivers/thunderbolt/nhi.c | |
parent | thunderbolt: Do not touch the hardware if the NHI is gone on resume (diff) | |
download | linux-f67cf491175a315ca86c9b349708bfed7b1f40c1.tar.xz linux-f67cf491175a315ca86c9b349708bfed7b1f40c1.zip |
thunderbolt: Add support for Internal Connection Manager (ICM)
Starting from Intel Falcon Ridge the internal connection manager running
on the Thunderbolt host controller has been supporting 4 security
levels. One reason for this is to prevent DMA attacks and only allow
connecting devices the user trusts.
The internal connection manager (ICM) is the preferred way of connecting
Thunderbolt devices over software only implementation typically used on
Macs. The driver communicates with ICM using special Thunderbolt ring 0
(control channel) messages. In order to handle these messages we add
support for the ICM messages to the control channel.
The security levels are as follows:
none - No security, all tunnels are created automatically
user - User needs to approve the device before tunnels are created
secure - User need to approve the device before tunnels are created.
The device is sent a challenge on future connects to be able
to verify it is actually the approved device.
dponly - Only Display Port and USB tunnels can be created and those
are created automatically.
The security levels are typically configurable from the system BIOS and
by default it is set to "user" on many systems.
In this patch each Thunderbolt device will have either one or two new
sysfs attributes: authorized and key. The latter appears for devices
that support secure connect.
In order to identify the device the user can read identication
information, including UUID and name of the device from sysfs and based
on that make a decision to authorize the device. The device is
authorized by simply writing 1 to the "authorized" sysfs attribute. This
is following the USB bus device authorization mechanism. The secure
connect requires an additional challenge step (writing 2 to the
"authorized" attribute) in future connects when the key has already been
stored to the NVM of the device.
Non-ICM systems (before Alpine Ridge) continue to use the existing
functionality and the security level is set to none. For systems with
Alpine Ridge, even on Apple hardware, we will use ICM.
This code is based on the work done by Amir Levy and Michael Jamet.
Signed-off-by: Michael Jamet <michael.jamet@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/nhi.c')
-rw-r--r-- | drivers/thunderbolt/nhi.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 14311535661d..05af126a2435 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -13,7 +13,6 @@ #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/dmi.h> #include <linux/delay.h> #include "nhi.h" @@ -668,6 +667,22 @@ static int nhi_resume_noirq(struct device *dev) return tb_domain_resume_noirq(tb); } +static int nhi_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct tb *tb = pci_get_drvdata(pdev); + + return tb_domain_suspend(tb); +} + +static void nhi_complete(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct tb *tb = pci_get_drvdata(pdev); + + tb_domain_complete(tb); +} + static void nhi_shutdown(struct tb_nhi *nhi) { int i; @@ -784,10 +799,16 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* magic value - clock related? */ iowrite32(3906250 / 10000, nhi->iobase + 0x38c00); - dev_info(&nhi->pdev->dev, "NHI initialized, starting thunderbolt\n"); - tb = tb_probe(nhi); + tb = icm_probe(nhi); if (!tb) + tb = tb_probe(nhi); + if (!tb) { + dev_err(&nhi->pdev->dev, + "failed to determine connection manager, aborting\n"); return -ENODEV; + } + + dev_info(&nhi->pdev->dev, "NHI initialized, starting thunderbolt\n"); res = tb_domain_add(tb); if (res) { @@ -826,6 +847,10 @@ static const struct dev_pm_ops nhi_pm_ops = { * pci-tunnels stay alive. */ .restore_noirq = nhi_resume_noirq, + .suspend = nhi_suspend, + .freeze = nhi_suspend, + .poweroff = nhi_suspend, + .complete = nhi_complete, }; static struct pci_device_id nhi_ids[] = { @@ -886,8 +911,6 @@ static int __init nhi_init(void) { int ret; - if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc.")) - return -ENOSYS; ret = tb_domain_init(); if (ret) return ret; |