Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Rajmohan Mani and committed by
Mika Westerberg
faa1c615 1cbf680f

+53 -17
+1 -1
Documentation/ABI/testing/sysfs-bus-thunderbolt
··· 221 221 and flush it to the storage area. 222 222 - Writing "3" will authenticate the image that is 223 223 currently written in the storage area. This is only 224 - supported with USB4 devices. 224 + supported with USB4 devices and retimers. 225 225 226 226 When read holds status of the last authentication 227 227 operation if an error occurred during the process. This
+37 -14
drivers/thunderbolt/retimer.c
··· 103 103 unsigned int image_size, hdr_size; 104 104 const u8 *buf = rt->nvm->buf; 105 105 u16 ds_size, device; 106 + int ret; 106 107 107 108 image_size = rt->nvm->buf_data_size; 108 109 if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE) ··· 141 140 buf += hdr_size; 142 141 image_size -= hdr_size; 143 142 144 - return usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf, 145 - image_size); 143 + ret = usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf, 144 + image_size); 145 + if (!ret) 146 + rt->nvm->flushed = true; 147 + 148 + return ret; 149 + } 150 + 151 + static int tb_retimer_nvm_authenticate(struct tb_retimer *rt, bool auth_only) 152 + { 153 + int ret; 154 + 155 + if (auth_only) { 156 + ret = usb4_port_retimer_nvm_set_offset(rt->port, rt->index, 0); 157 + if (ret) 158 + return ret; 159 + } 160 + 161 + return usb4_port_retimer_nvm_authenticate(rt->port, rt->index); 146 162 } 147 163 148 164 static ssize_t device_show(struct device *dev, struct device_attribute *attr, ··· 194 176 struct device_attribute *attr, const char *buf, size_t count) 195 177 { 196 178 struct tb_retimer *rt = tb_to_retimer(dev); 197 - bool val; 198 - int ret; 179 + int val, ret; 199 180 200 181 pm_runtime_get_sync(&rt->dev); 201 182 ··· 208 191 goto exit_unlock; 209 192 } 210 193 211 - ret = kstrtobool(buf, &val); 194 + ret = kstrtoint(buf, 10, &val); 212 195 if (ret) 213 196 goto exit_unlock; 214 197 ··· 216 199 rt->auth_status = 0; 217 200 218 201 if (val) { 219 - if (!rt->nvm->buf) { 220 - ret = -EINVAL; 221 - goto exit_unlock; 202 + if (val == AUTHENTICATE_ONLY) { 203 + ret = tb_retimer_nvm_authenticate(rt, true); 204 + } else { 205 + if (!rt->nvm->flushed) { 206 + if (!rt->nvm->buf) { 207 + ret = -EINVAL; 208 + goto exit_unlock; 209 + } 210 + 211 + ret = tb_retimer_nvm_validate_and_write(rt); 212 + if (ret || val == WRITE_ONLY) 213 + goto exit_unlock; 214 + } 215 + if (val == WRITE_AND_AUTHENTICATE) 216 + ret = tb_retimer_nvm_authenticate(rt, false); 222 217 } 223 - 224 - ret = tb_retimer_nvm_validate_and_write(rt); 225 - if (ret) 226 - goto exit_unlock; 227 - 228 - ret = usb4_port_retimer_nvm_authenticate(rt->port, rt->index); 229 218 } 230 219 231 220 exit_unlock:
+2
drivers/thunderbolt/tb.h
··· 1082 1082 const void *buf, u8 size); 1083 1083 int usb4_port_retimer_is_last(struct tb_port *port, u8 index); 1084 1084 int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index); 1085 + int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, 1086 + unsigned int address); 1085 1087 int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index, 1086 1088 unsigned int address, const void *buf, 1087 1089 size_t size);
+13 -2
drivers/thunderbolt/usb4.c
··· 1513 1513 return ret ? ret : metadata & USB4_NVM_SECTOR_SIZE_MASK; 1514 1514 } 1515 1515 1516 - static int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, 1517 - unsigned int address) 1516 + /** 1517 + * usb4_port_retimer_nvm_set_offset() - Set NVM write offset 1518 + * @port: USB4 port 1519 + * @index: Retimer index 1520 + * @address: Start offset 1521 + * 1522 + * Exlicitly sets NVM write offset. Normally when writing to NVM this is 1523 + * done automatically by usb4_port_retimer_nvm_write(). 1524 + * 1525 + * Returns %0 in success and negative errno if there was a failure. 1526 + */ 1527 + int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, 1528 + unsigned int address) 1518 1529 { 1519 1530 u32 metadata, dwaddress; 1520 1531 int ret;