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:
Родитель
1cbf680f76
Коммит
faa1c615f0
|
@ -221,7 +221,7 @@ Description: When new NVM image is written to the non-active NVM
|
|||
and flush it to the storage area.
|
||||
- Writing "3" will authenticate the image that is
|
||||
currently written in the storage area. This is only
|
||||
supported with USB4 devices.
|
||||
supported with USB4 devices and retimers.
|
||||
|
||||
When read holds status of the last authentication
|
||||
operation if an error occurred during the process. This
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче