thunderbolt: Add WRITE_ONLY and AUTHENTICATE_ONLY NVM operations for retimers

The same way we support these two operations for USB4 routers we can
extend the retimer NVM operations to support retimers also.

Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>
Co-developed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Rajmohan Mani
2021-04-12 15:29:16 +03:00
committed by Mika Westerberg
parent 1cbf680f76
commit faa1c615f0
4 changed files with 53 additions and 17 deletions

View File

@@ -103,6 +103,7 @@ 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;
int ret;
image_size = rt->nvm->buf_data_size;
if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE)
@@ -140,8 +141,25 @@ static int tb_retimer_nvm_validate_and_write(struct tb_retimer *rt)
buf += hdr_size;
image_size -= hdr_size;
return usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf,
image_size);
ret = usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf,
image_size);
if (!ret)
rt->nvm->flushed = true;
return ret;
}
static int tb_retimer_nvm_authenticate(struct tb_retimer *rt, bool auth_only)
{
int ret;
if (auth_only) {
ret = usb4_port_retimer_nvm_set_offset(rt->port, rt->index, 0);
if (ret)
return ret;
}
return usb4_port_retimer_nvm_authenticate(rt->port, rt->index);
}
static ssize_t device_show(struct device *dev, struct device_attribute *attr,
@@ -176,8 +194,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tb_retimer *rt = tb_to_retimer(dev);
bool val;
int ret;
int val, ret;
pm_runtime_get_sync(&rt->dev);
@@ -191,7 +208,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
goto exit_unlock;
}
ret = kstrtobool(buf, &val);
ret = kstrtoint(buf, 10, &val);
if (ret)
goto exit_unlock;
@@ -199,16 +216,22 @@ static ssize_t nvm_authenticate_store(struct device *dev,
rt->auth_status = 0;
if (val) {
if (!rt->nvm->buf) {
ret = -EINVAL;
goto exit_unlock;
if (val == AUTHENTICATE_ONLY) {
ret = tb_retimer_nvm_authenticate(rt, true);
} else {
if (!rt->nvm->flushed) {
if (!rt->nvm->buf) {
ret = -EINVAL;
goto exit_unlock;
}
ret = tb_retimer_nvm_validate_and_write(rt);
if (ret || val == WRITE_ONLY)
goto exit_unlock;
}
if (val == WRITE_AND_AUTHENTICATE)
ret = tb_retimer_nvm_authenticate(rt, false);
}
ret = tb_retimer_nvm_validate_and_write(rt);
if (ret)
goto exit_unlock;
ret = usb4_port_retimer_nvm_authenticate(rt->port, rt->index);
}
exit_unlock:

View File

@@ -1082,6 +1082,8 @@ int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg,
const void *buf, u8 size);
int usb4_port_retimer_is_last(struct tb_port *port, u8 index);
int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index);
int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index,
unsigned int address);
int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index,
unsigned int address, const void *buf,
size_t size);

View File

@@ -1513,8 +1513,19 @@ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index)
return ret ? ret : metadata & USB4_NVM_SECTOR_SIZE_MASK;
}
static int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index,
unsigned int address)
/**
* usb4_port_retimer_nvm_set_offset() - Set NVM write offset
* @port: USB4 port
* @index: Retimer index
* @address: Start offset
*
* Exlicitly sets NVM write offset. Normally when writing to NVM this is
* done automatically by usb4_port_retimer_nvm_write().
*
* Returns %0 in success and negative errno if there was a failure.
*/
int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index,
unsigned int address)
{
u32 metadata, dwaddress;
int ret;