summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/retimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thunderbolt/retimer.c')
-rw-r--r--drivers/thunderbolt/retimer.c81
1 files changed, 23 insertions, 58 deletions
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
index bec02ad4cb3b..dd8f033b1690 100644
--- a/drivers/thunderbolt/retimer.c
+++ b/drivers/thunderbolt/retimer.c
@@ -73,34 +73,23 @@ static int nvm_write(void *priv, unsigned int offset, void *val, size_t bytes)
static int tb_retimer_nvm_add(struct tb_retimer *rt)
{
struct tb_nvm *nvm;
- u32 val, nvm_size;
int ret;
nvm = tb_nvm_alloc(&rt->dev);
- if (IS_ERR(nvm))
- return PTR_ERR(nvm);
-
- ret = usb4_port_retimer_nvm_read(rt->port, rt->index, NVM_VERSION, &val,
- sizeof(val));
- if (ret)
+ if (IS_ERR(nvm)) {
+ ret = PTR_ERR(nvm) == -EOPNOTSUPP ? 0 : PTR_ERR(nvm);
goto err_nvm;
+ }
- nvm->major = (val >> 16) & 0xff;
- nvm->minor = (val >> 8) & 0xff;
-
- ret = usb4_port_retimer_nvm_read(rt->port, rt->index, NVM_FLASH_SIZE,
- &val, sizeof(val));
+ ret = tb_nvm_read_version(nvm);
if (ret)
goto err_nvm;
- nvm_size = (SZ_1M << (val & 7)) / 8;
- nvm_size = (nvm_size - SZ_16K) / 2;
-
- ret = tb_nvm_add_active(nvm, nvm_size, nvm_read);
+ ret = tb_nvm_add_active(nvm, nvm_read);
if (ret)
goto err_nvm;
- ret = tb_nvm_add_non_active(nvm, NVM_MAX_SIZE, nvm_write);
+ ret = tb_nvm_add_non_active(nvm, nvm_write);
if (ret)
goto err_nvm;
@@ -108,59 +97,33 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt)
return 0;
err_nvm:
- tb_nvm_free(nvm);
+ dev_dbg(&rt->dev, "NVM upgrade disabled\n");
+ if (!IS_ERR(nvm))
+ tb_nvm_free(nvm);
+
return ret;
}
static int tb_retimer_nvm_validate_and_write(struct tb_retimer *rt)
{
- unsigned int image_size, hdr_size;
- const u8 *buf = rt->nvm->buf;
- u16 ds_size, device;
+ unsigned int image_size;
+ const u8 *buf;
int ret;
- image_size = rt->nvm->buf_data_size;
- if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE)
- return -EINVAL;
-
- /*
- * FARB pointer must point inside the image and must at least
- * contain parts of the digital section we will be reading here.
- */
- hdr_size = (*(u32 *)buf) & 0xffffff;
- if (hdr_size + NVM_DEVID + 2 >= image_size)
- return -EINVAL;
-
- /* Digital section start should be aligned to 4k page */
- if (!IS_ALIGNED(hdr_size, SZ_4K))
- return -EINVAL;
-
- /*
- * Read digital section size and check that it also fits inside
- * the image.
- */
- ds_size = *(u16 *)(buf + hdr_size);
- if (ds_size >= image_size)
- return -EINVAL;
-
- /*
- * Make sure the device ID in the image matches the retimer
- * hardware.
- */
- device = *(u16 *)(buf + hdr_size + NVM_DEVID);
- if (device != rt->device)
- return -EINVAL;
+ ret = tb_nvm_validate(rt->nvm);
+ if (ret)
+ return ret;
- /* Skip headers in the image */
- buf += hdr_size;
- image_size -= hdr_size;
+ buf = rt->nvm->buf_data_start;
+ image_size = rt->nvm->buf_data_size;
ret = usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf,
image_size);
- if (!ret)
- rt->nvm->flushed = true;
+ if (ret)
+ return ret;
- return ret;
+ rt->nvm->flushed = true;
+ return 0;
}
static int tb_retimer_nvm_authenticate(struct tb_retimer *rt, bool auth_only)
@@ -214,6 +177,8 @@ static ssize_t nvm_authenticate_show(struct device *dev,
if (!rt->nvm)
ret = -EAGAIN;
+ else if (rt->no_nvm_upgrade)
+ ret = -EOPNOTSUPP;
else
ret = sprintf(buf, "%#x\n", rt->auth_status);