summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2021-04-12 14:25:08 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2021-06-01 09:53:32 +0200
commit1cbf680f7687f55ae5a1405556519bc70d66a616 (patch)
treeeb5ac85abaffcae38f4924a2f667b84e00e62eaa /drivers/thunderbolt
parentthunderbolt: Move nvm_write_ops to tb.h (diff)
downloadlinux-1cbf680f7687f55ae5a1405556519bc70d66a616.tar.xz
linux-1cbf680f7687f55ae5a1405556519bc70d66a616.zip
thunderbolt: Allow router NVM authenticate separately
It may be useful if the actual NVM authentication can be delayed to be run later, for instance when the user logs out. For this reason add a new NVM operation (AUHENTICATE_ONLY) that just triggers the authentication procedure over whatever was written to the NVM storage. This is not supported with Thunderbolt 1-3 devices, though. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt')
-rw-r--r--drivers/thunderbolt/switch.c50
-rw-r--r--drivers/thunderbolt/tb.h2
-rw-r--r--drivers/thunderbolt/usb4.c13
3 files changed, 45 insertions, 20 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index bf4821d3bbab..83b1ef3d5d03 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -303,13 +303,23 @@ static inline int nvm_read(struct tb_switch *sw, unsigned int address,
return dma_port_flash_read(sw->dma_port, address, buf, size);
}
-static int nvm_authenticate(struct tb_switch *sw)
+static int nvm_authenticate(struct tb_switch *sw, bool auth_only)
{
int ret;
- if (tb_switch_is_usb4(sw))
+ if (tb_switch_is_usb4(sw)) {
+ if (auth_only) {
+ ret = usb4_switch_nvm_set_offset(sw, 0);
+ if (ret)
+ return ret;
+ }
+ sw->nvm->authenticating = true;
return usb4_switch_nvm_authenticate(sw);
+ } else if (auth_only) {
+ return -EOPNOTSUPP;
+ }
+ sw->nvm->authenticating = true;
if (!tb_route(sw)) {
nvm_authenticate_start_dma_port(sw);
ret = nvm_authenticate_host_dma_port(sw);
@@ -1713,8 +1723,7 @@ static ssize_t nvm_authenticate_sysfs(struct device *dev, const char *buf,
bool disconnect)
{
struct tb_switch *sw = tb_to_switch(dev);
- int val;
- int ret;
+ int val, ret;
pm_runtime_get_sync(&sw->dev);
@@ -1737,22 +1746,27 @@ static ssize_t nvm_authenticate_sysfs(struct device *dev, const char *buf,
nvm_clear_auth_status(sw);
if (val > 0) {
- if (!sw->nvm->flushed) {
- if (!sw->nvm->buf) {
+ if (val == AUTHENTICATE_ONLY) {
+ if (disconnect)
ret = -EINVAL;
- goto exit_unlock;
+ else
+ ret = nvm_authenticate(sw, true);
+ } else {
+ if (!sw->nvm->flushed) {
+ if (!sw->nvm->buf) {
+ ret = -EINVAL;
+ goto exit_unlock;
+ }
+
+ ret = nvm_validate_and_write(sw);
+ if (ret || val == WRITE_ONLY)
+ goto exit_unlock;
}
-
- ret = nvm_validate_and_write(sw);
- if (ret || val == WRITE_ONLY)
- goto exit_unlock;
- }
- if (val == WRITE_AND_AUTHENTICATE) {
- if (disconnect) {
- ret = tb_lc_force_power(sw);
- } else {
- sw->nvm->authenticating = true;
- ret = nvm_authenticate(sw);
+ if (val == WRITE_AND_AUTHENTICATE) {
+ if (disconnect)
+ ret = tb_lc_force_power(sw);
+ else
+ ret = nvm_authenticate(sw, false);
}
}
}
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 863d80ad44ab..53f6bb85b178 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -61,6 +61,7 @@ struct tb_nvm {
enum tb_nvm_write_ops {
WRITE_AND_AUTHENTICATE = 1,
WRITE_ONLY = 2,
+ AUTHENTICATE_ONLY = 3,
};
#define TB_SWITCH_KEY_SIZE 32
@@ -1049,6 +1050,7 @@ int usb4_switch_set_sleep(struct tb_switch *sw);
int usb4_switch_nvm_sector_size(struct tb_switch *sw);
int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf,
size_t size);
+int usb4_switch_nvm_set_offset(struct tb_switch *sw, unsigned int address);
int usb4_switch_nvm_write(struct tb_switch *sw, unsigned int address,
const void *buf, size_t size);
int usb4_switch_nvm_authenticate(struct tb_switch *sw);
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 8af96dbaa7a7..76d7335aa440 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -547,8 +547,17 @@ int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf,
usb4_switch_nvm_read_block, sw);
}
-static int usb4_switch_nvm_set_offset(struct tb_switch *sw,
- unsigned int address)
+/**
+ * usb4_switch_nvm_set_offset() - Set NVM write offset
+ * @sw: USB4 router
+ * @address: Start offset
+ *
+ * Explicitly sets NVM write offset. Normally when writing to NVM this
+ * is done automatically by usb4_switch_nvm_write().
+ *
+ * Returns %0 in success and negative errno if there was a failure.
+ */
+int usb4_switch_nvm_set_offset(struct tb_switch *sw, unsigned int address)
{
u32 metadata, dwaddress;
u8 status = 0;