diff options
Diffstat (limited to 'drivers/thunderbolt/usb4.c')
| -rw-r--r-- | drivers/thunderbolt/usb4.c | 826 |
1 files changed, 555 insertions, 271 deletions
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 05ddb224c464..9e810b2ae0b5 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -9,6 +9,7 @@ #include <linux/delay.h> #include <linux/ktime.h> +#include <linux/string_choices.h> #include <linux/units.h> #include "sb_regs.h" @@ -17,12 +18,6 @@ #define USB4_DATA_RETRIES 3 #define USB4_DATA_DWORDS 16 -enum usb4_sb_target { - USB4_SB_TARGET_ROUTER, - USB4_SB_TARGET_PARTNER, - USB4_SB_TARGET_RETIMER, -}; - #define USB4_NVM_READ_OFFSET_MASK GENMASK(23, 2) #define USB4_NVM_READ_OFFSET_SHIFT 2 #define USB4_NVM_READ_LENGTH_MASK GENMASK(27, 24) @@ -52,6 +47,10 @@ enum usb4_ba_index { #define USB4_BA_VALUE_MASK GENMASK(31, 16) #define USB4_BA_VALUE_SHIFT 16 +/* Delays in us used with usb4_port_wait_for_bit() */ +#define USB4_PORT_DELAY 50 +#define USB4_PORT_SB_DELAY 1000 + static int usb4_native_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata, u8 *status, const void *tx_data, size_t tx_dwords, @@ -155,7 +154,13 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode, tx_dwords, rx_data, rx_dwords); } -static void usb4_switch_check_wakes(struct tb_switch *sw) +/** + * usb4_switch_check_wakes() - Check for wakes and notify PM core about them + * @sw: Router whose wakes to check + * + * Checks wakes occurred during suspend and notify the PM core about them. + */ +void usb4_switch_check_wakes(struct tb_switch *sw) { bool wakeup_usb4 = false; struct usb4_port *usb4; @@ -163,16 +168,13 @@ static void usb4_switch_check_wakes(struct tb_switch *sw) bool wakeup = false; u32 val; - if (!device_may_wakeup(&sw->dev)) - return; - if (tb_route(sw)) { if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1)) return; tb_sw_dbg(sw, "PCIe wake: %s, USB3 wake: %s\n", - (val & ROUTER_CS_6_WOPS) ? "yes" : "no", - (val & ROUTER_CS_6_WOUS) ? "yes" : "no"); + str_yes_no(val & ROUTER_CS_6_WOPS), + str_yes_no(val & ROUTER_CS_6_WOUS)); wakeup = val & (ROUTER_CS_6_WOPS | ROUTER_CS_6_WOUS); } @@ -190,9 +192,9 @@ static void usb4_switch_check_wakes(struct tb_switch *sw) break; tb_port_dbg(port, "USB4 wake: %s, connection wake: %s, disconnection wake: %s\n", - (val & PORT_CS_18_WOU4S) ? "yes" : "no", - (val & PORT_CS_18_WOCS) ? "yes" : "no", - (val & PORT_CS_18_WODS) ? "yes" : "no"); + str_yes_no(val & PORT_CS_18_WOU4S), + str_yes_no(val & PORT_CS_18_WOCS), + str_yes_no(val & PORT_CS_18_WODS)); wakeup_usb4 = val & (PORT_CS_18_WOU4S | PORT_CS_18_WOCS | PORT_CS_18_WODS); @@ -235,6 +237,8 @@ static bool link_is_usb4(struct tb_port *port) * * This does not set the configuration valid bit of the router. To do * that call usb4_switch_configuration_valid(). + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_setup(struct tb_switch *sw) { @@ -244,8 +248,6 @@ int usb4_switch_setup(struct tb_switch *sw) u32 val = 0; int ret; - usb4_switch_check_wakes(sw); - if (!tb_route(sw)) return 0; @@ -261,7 +263,7 @@ int usb4_switch_setup(struct tb_switch *sw) tbt3 = !(val & ROUTER_CS_6_TNS); tb_sw_dbg(sw, "TBT3 support: %s, xHCI: %s\n", - tbt3 ? "yes" : "no", xhci ? "yes" : "no"); + str_yes_no(tbt3), str_yes_no(xhci)); ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); if (ret) @@ -282,7 +284,7 @@ int usb4_switch_setup(struct tb_switch *sw) val |= ROUTER_CS_5_PTO; /* * xHCI can be enabled if PCIe tunneling is supported - * and the parent does not have any USB3 dowstream + * and the parent does not have any USB3 downstream * adapters (so we cannot do USB 3.x tunneling). */ if (xhci) @@ -290,7 +292,7 @@ int usb4_switch_setup(struct tb_switch *sw) } /* TBT3 supported by the CM */ - val |= ROUTER_CS_5_C3S; + val &= ~ROUTER_CS_5_CNS; return tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); } @@ -304,7 +306,7 @@ int usb4_switch_setup(struct tb_switch *sw) * usb4_switch_setup() has been called. Can be called to host and device * routers (does nothing for the latter). * - * Returns %0 in success and negative errno otherwise. + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_configuration_valid(struct tb_switch *sw) { @@ -334,6 +336,8 @@ int usb4_switch_configuration_valid(struct tb_switch *sw) * @uid: UID is stored here * * Reads 64-bit UID from USB4 router config space. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid) { @@ -371,6 +375,8 @@ static int usb4_switch_drom_read_block(void *data, * Uses USB4 router operations to read router DROM. For devices this * should always work but for hosts it may return %-EOPNOTSUPP in which * case the host router does not have DROM. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size) @@ -385,6 +391,8 @@ int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, * * Checks whether conditions are met so that lane bonding can be * established with the upstream router. Call only for device routers. + * + * Return: %true if lane bonding is possible, %false otherwise. */ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) { @@ -404,12 +412,14 @@ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) * usb4_switch_set_wake() - Enabled/disable wake * @sw: USB4 router * @flags: Wakeup flags (%0 to disable) + * @runtime: Wake is being programmed during system runtime * * Enables/disables router to wake up from sleep. + * + * Return: %0 on success, negative errno otherwise. */ -int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) +int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) { - struct usb4_port *usb4; struct tb_port *port; u64 route = tb_route(sw); u32 val; @@ -439,13 +449,11 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) val |= PORT_CS_19_WOU4; } else { bool configured = val & PORT_CS_19_PC; - usb4 = port->usb4; + bool wakeup = runtime || device_may_wakeup(&port->usb4->dev); - if (((flags & TB_WAKE_ON_CONNECT) | - device_may_wakeup(&usb4->dev)) && !configured) + if ((flags & TB_WAKE_ON_CONNECT) && wakeup && !configured) val |= PORT_CS_19_WOC; - if (((flags & TB_WAKE_ON_DISCONNECT) | - device_may_wakeup(&usb4->dev)) && configured) + if ((flags & TB_WAKE_ON_DISCONNECT) && wakeup && configured) val |= PORT_CS_19_WOD; if ((flags & TB_WAKE_ON_USB4) && configured) val |= PORT_CS_19_WOU4; @@ -486,8 +494,10 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) * usb4_switch_set_sleep() - Prepare the router to enter sleep * @sw: USB4 router * - * Sets sleep bit for the router. Returns when the router sleep ready + * Sets sleep bit for the router and waits until router sleep ready * bit has been asserted. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_set_sleep(struct tb_switch *sw) { @@ -513,9 +523,10 @@ int usb4_switch_set_sleep(struct tb_switch *sw) * usb4_switch_nvm_sector_size() - Return router NVM sector size * @sw: USB4 router * - * If the router supports NVM operations this function returns the NVM - * sector size in bytes. If NVM operations are not supported returns - * %-EOPNOTSUPP. + * Return: + * * NVM sector size in bytes if router supports NVM operations. + * * %-EOPNOTSUPP - If router does not support NVM operations. + * * Negative errno - Another error occurred. */ int usb4_switch_nvm_sector_size(struct tb_switch *sw) { @@ -562,8 +573,12 @@ static int usb4_switch_nvm_read_block(void *data, * @buf: Read data is placed here * @size: How many bytes to read * - * Reads NVM contents of the router. If NVM is not supported returns - * %-EOPNOTSUPP. + * Reads NVM contents of the router. + * + * Return: + * * %0 - Read completed successfully. + * * %-EOPNOTSUPP - NVM not supported. + * * Negative errno - Another error occurred. */ int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size) @@ -580,7 +595,7 @@ int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, * 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. + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_nvm_set_offset(struct tb_switch *sw, unsigned int address) { @@ -622,8 +637,12 @@ static int usb4_switch_nvm_write_next_block(void *data, unsigned int dwaddress, * @buf: Pointer to the data to write * @size: Size of @buf in bytes * - * Writes @buf to the router NVM using USB4 router operations. If NVM - * write is not supported returns %-EOPNOTSUPP. + * Writes @buf to the router NVM using USB4 router operations. + * + * Return: + * * %0 - Write completed successfully. + * * %-EOPNOTSUPP - NVM write not supported. + * * Negative errno - Another error occurred. */ int usb4_switch_nvm_write(struct tb_switch *sw, unsigned int address, const void *buf, size_t size) @@ -645,11 +664,13 @@ int usb4_switch_nvm_write(struct tb_switch *sw, unsigned int address, * After the new NVM has been written via usb4_switch_nvm_write(), this * function triggers NVM authentication process. The router gets power * cycled and if the authentication is successful the new NVM starts - * running. In case of failure returns negative errno. + * running. * * The caller should call usb4_switch_nvm_authenticate_status() to read * the status of the authentication after power cycle. It should be the * first router operation to avoid the status being lost. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_nvm_authenticate(struct tb_switch *sw) { @@ -677,11 +698,13 @@ int usb4_switch_nvm_authenticate(struct tb_switch *sw) * @status: Status code of the operation * * The function checks if there is status available from the last NVM - * authenticate router operation. If there is status then %0 is returned - * and the status code is placed in @status. Returns negative errno in case - * of failure. + * authenticate router operation. * * Must be called before any other router operation. + * + * Return: + * * %0 - If there is status. Status code is placed in @status. + * * Negative errno - Failure occurred. */ int usb4_switch_nvm_authenticate_status(struct tb_switch *sw, u32 *status) { @@ -725,7 +748,7 @@ int usb4_switch_nvm_authenticate_status(struct tb_switch *sw, u32 *status) * allocation fields accordingly. Specifically @sw->credits_allocation * is set to %true if these parameters can be used in tunneling. * - * Returns %0 on success and negative errno otherwise. + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_credits_init(struct tb_switch *sw) { @@ -864,8 +887,10 @@ err_invalid: * @in: DP IN adapter * * For DP tunneling this function can be used to query availability of - * DP IN resource. Returns true if the resource is available for DP - * tunneling, false otherwise. + * DP IN resource. + * + * Return: %true if the resource is available for DP tunneling, %false + * otherwise. */ bool usb4_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in) { @@ -893,9 +918,12 @@ bool usb4_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in) * @in: DP IN adapter * * Allocates DP IN resource for DP tunneling using USB4 router - * operations. If the resource was allocated returns %0. Otherwise - * returns negative errno, in particular %-EBUSY if the resource is - * already allocated. + * operations. + * + * Return: + * * %0 - Resource allocated successfully. + * * %-EBUSY - Resource is already allocated. + * * Negative errno - Other failure occurred. */ int usb4_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in) { @@ -919,6 +947,8 @@ int usb4_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in) * @in: DP IN adapter * * Releases the previously allocated DP IN resource. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_dealloc_dp_resource(struct tb_switch *sw, struct tb_port *in) { @@ -936,7 +966,15 @@ int usb4_switch_dealloc_dp_resource(struct tb_switch *sw, struct tb_port *in) return status ? -EIO : 0; } -static int usb4_port_idx(const struct tb_switch *sw, const struct tb_port *port) +/** + * usb4_port_index() - Finds matching USB4 port index + * @sw: USB4 router + * @port: USB4 protocol or lane adapter + * + * Finds matching USB4 port index (starting from %0) that given @port goes + * through. + */ +int usb4_port_index(const struct tb_switch *sw, const struct tb_port *port) { struct tb_port *p; int usb4_idx = 0; @@ -966,11 +1004,13 @@ static int usb4_port_idx(const struct tb_switch *sw, const struct tb_port *port) * downstream adapters where the PCIe topology is extended. This * function returns the corresponding downstream PCIe adapter or %NULL * if no such mapping was possible. + * + * Return: Pointer to &struct tb_port or %NULL if not found. */ struct tb_port *usb4_switch_map_pcie_down(struct tb_switch *sw, const struct tb_port *port) { - int usb4_idx = usb4_port_idx(sw, port); + int usb4_idx = usb4_port_index(sw, port); struct tb_port *p; int pcie_idx = 0; @@ -997,11 +1037,13 @@ struct tb_port *usb4_switch_map_pcie_down(struct tb_switch *sw, * downstream adapters where the USB 3.x topology is extended. This * function returns the corresponding downstream USB 3.x adapter or * %NULL if no such mapping was possible. + * + * Return: Pointer to &struct tb_port or %NULL if not found. */ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, const struct tb_port *port) { - int usb4_idx = usb4_port_idx(sw, port); + int usb4_idx = usb4_port_index(sw, port); struct tb_port *p; int usb_idx = 0; @@ -1026,7 +1068,7 @@ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, * For USB4 router finds all USB4 ports and registers devices for each. * Can be called to any router. * - * Return %0 in case of success and negative errno in case of failure. + * Return: %0 on success, negative errno otherwise. */ int usb4_switch_add_ports(struct tb_switch *sw) { @@ -1079,6 +1121,8 @@ void usb4_switch_remove_ports(struct tb_switch *sw) * * Unlocks USB4 downstream port so that the connection manager can * access the router below this port. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_unlock(struct tb_port *port) { @@ -1099,6 +1143,8 @@ int usb4_port_unlock(struct tb_port *port) * * Enables hot plug events on a given port. This is only intended * to be used on lane, DP-IN, and DP-OUT adapters. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_hotplug_enable(struct tb_port *port) { @@ -1113,6 +1159,47 @@ int usb4_port_hotplug_enable(struct tb_port *port) return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1); } +/** + * usb4_port_reset() - Issue downstream port reset + * @port: USB4 port to reset + * + * Issues downstream port reset to @port. + * + * Return: %0 on success, negative errno otherwise. + */ +int usb4_port_reset(struct tb_port *port) +{ + int ret; + u32 val; + + if (!port->cap_usb4) + return -EINVAL; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val |= PORT_CS_19_DPR; + + ret = tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + fsleep(10000); + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val &= ~PORT_CS_19_DPR; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); +} + static int usb4_port_set_configured(struct tb_port *port, bool configured) { int ret; @@ -1140,6 +1227,8 @@ static int usb4_port_set_configured(struct tb_port *port, bool configured) * @port: USB4 router * * Sets the USB4 link to be configured for power management purposes. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_configure(struct tb_port *port) { @@ -1151,6 +1240,8 @@ int usb4_port_configure(struct tb_port *port) * @port: USB4 router * * Sets the USB4 link to be unconfigured for power management purposes. + * + * Return: %0 on success, negative errno otherwise. */ void usb4_port_unconfigure(struct tb_port *port) { @@ -1185,7 +1276,9 @@ static int usb4_set_xdomain_configured(struct tb_port *port, bool configured) * @xd: XDomain that is connected to the port * * Marks the USB4 port as being connected to another host and updates - * the link type. Returns %0 in success and negative errno in failure. + * the link type. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_configure_xdomain(struct tb_port *port, struct tb_xdomain *xd) { @@ -1205,7 +1298,7 @@ void usb4_port_unconfigure_xdomain(struct tb_port *port) } static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, - u32 value, int timeout_msec) + u32 value, int timeout_msec, unsigned long delay_usec) { ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec); @@ -1220,7 +1313,7 @@ static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, if ((val & bit) == value) return 0; - usleep_range(50, 100); + fsleep(delay_usec); } while (ktime_before(ktime_get(), timeout)); return -ETIMEDOUT; @@ -1245,8 +1338,21 @@ static int usb4_port_write_data(struct tb_port *port, const void *data, dwords); } -static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, - u8 index, u8 reg, void *buf, u8 size) +/** + * usb4_port_sb_read() - Read from sideband register + * @port: USB4 port to read + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER + * @reg: Sideband register index + * @buf: Buffer where the sideband data is copied + * @size: Size of @buf + * + * Reads data from sideband register @reg and copies it into @buf. + * + * Return: %0 on success, negative errno otherwise. + */ +int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index, + u8 reg, void *buf, u8 size) { size_t dwords = DIV_ROUND_UP(size, 4); int ret; @@ -1268,7 +1374,7 @@ static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, return ret; ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_1, - PORT_CS_1_PND, 0, 500); + PORT_CS_1_PND, 0, 500, USB4_PORT_SB_DELAY); if (ret) return ret; @@ -1285,8 +1391,21 @@ static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, return buf ? usb4_port_read_data(port, buf, dwords) : 0; } -static int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, - u8 index, u8 reg, const void *buf, u8 size) +/** + * usb4_port_sb_write() - Write to sideband register + * @port: USB4 port to write + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER + * @reg: Sideband register index + * @buf: Data to write + * @size: Size of @buf + * + * Writes @buf to sideband register @reg. + * + * Return: %0 on success, negative errno otherwise. + */ +int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, + u8 index, u8 reg, const void *buf, u8 size) { size_t dwords = DIV_ROUND_UP(size, 4); int ret; @@ -1315,7 +1434,7 @@ static int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, return ret; ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_1, - PORT_CS_1_PND, 0, 500); + PORT_CS_1_PND, 0, 500, USB4_PORT_SB_DELAY); if (ret) return ret; @@ -1370,6 +1489,8 @@ static int usb4_port_sb_op(struct tb_port *port, enum usb4_sb_target target, if (val != opcode) return usb4_port_sb_opcode_err_to_errno(val); + + fsleep(USB4_PORT_SB_DELAY); } while (ktime_before(ktime_get(), timeout)); return -ETIMEDOUT; @@ -1398,8 +1519,7 @@ static int usb4_port_set_router_offline(struct tb_port *port, bool offline) * port does not react on hotplug events anymore. This needs to be * called before retimer access is done when the USB4 links is not up. * - * Returns %0 in case of success and negative errno if there was an - * error. + * Return: %0 on success, negative errno otherwise. */ int usb4_port_router_offline(struct tb_port *port) { @@ -1407,10 +1527,12 @@ int usb4_port_router_offline(struct tb_port *port) } /** - * usb4_port_router_online() - Put the USB4 port back to online + * usb4_port_router_online() - Put the USB4 port back online * @port: USB4 port * * Makes the USB4 port functional again. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_router_online(struct tb_port *port) { @@ -1422,8 +1544,9 @@ int usb4_port_router_online(struct tb_port *port) * @port: USB4 port * * This forces the USB4 port to send broadcast RT transaction which - * makes the retimers on the link to assign index to themselves. Returns - * %0 in case of success and negative errno if there was an error. + * makes the retimers on the link assign index to themselves. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_enumerate_retimers(struct tb_port *port) { @@ -1440,6 +1563,8 @@ int usb4_port_enumerate_retimers(struct tb_port *port) * * PORT_CS_18_CPS bit reflects if the link supports CLx including * active cables (if connected on the link). + * + * Return: %true if Clx is supported, %false otherwise. */ bool usb4_port_clx_supported(struct tb_port *port) { @@ -1455,123 +1580,264 @@ bool usb4_port_clx_supported(struct tb_port *port) } /** - * usb4_port_margining_caps() - Read USB4 port marginig capabilities + * usb4_port_asym_supported() - If the port supports asymmetric link + * @port: USB4 port + * + * Checks if the port and the cable support asymmetric link. + * + * Return: %true if asymmetric link is supported, %false otherwise. + */ +bool usb4_port_asym_supported(struct tb_port *port) +{ + u32 val; + + if (!port->cap_usb4) + return false; + + if (tb_port_read(port, &val, TB_CFG_PORT, port->cap_usb4 + PORT_CS_18, 1)) + return false; + + return !!(val & PORT_CS_18_CSA); +} + +/** + * usb4_port_asym_set_link_width() - Set link width to asymmetric or symmetric + * @port: USB4 port + * @width: Asymmetric width to configure + * + * Sets USB4 port link width to @width. Can be called for widths where + * usb4_port_asym_width_supported() returned @true. + * + * Return: %0 on success, negative errno otherwise. + */ +int usb4_port_asym_set_link_width(struct tb_port *port, enum tb_link_width width) +{ + u32 val; + int ret; + + if (!port->cap_phy) + return -EINVAL; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); + if (ret) + return ret; + + val &= ~LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK; + switch (width) { + case TB_LINK_WIDTH_DUAL: + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_DUAL); + break; + case TB_LINK_WIDTH_ASYM_TX: + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_TX); + break; + case TB_LINK_WIDTH_ASYM_RX: + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_RX); + break; + default: + return -EINVAL; + } + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); +} + +/** + * usb4_port_asym_start() - Start symmetry change and wait for completion + * @port: USB4 port + * + * Start symmetry change of the link to asymmetric or symmetric + * (according to what was previously set in tb_port_set_link_width(). + * Wait for completion of the change. + * + * Return: + * * %0 - Symmetry change was successful. + * * %-ETIMEDOUT - Timeout occurred. + * * Negative errno - Other failure occurred. + */ +int usb4_port_asym_start(struct tb_port *port) +{ + int ret; + u32 val; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val &= ~PORT_CS_19_START_ASYM; + val |= FIELD_PREP(PORT_CS_19_START_ASYM, 1); + + ret = tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + /* + * Wait for PORT_CS_19_START_ASYM to be 0. This means the USB4 + * port started the symmetry transition. + */ + ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_19, + PORT_CS_19_START_ASYM, 0, 1000, + USB4_PORT_DELAY); + if (ret) + return ret; + + /* Then wait for the transtion to be completed */ + return usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_18, + PORT_CS_18_TIP, 0, 5000, USB4_PORT_DELAY); +} + +/** + * usb4_port_margining_caps() - Read USB4 port margining capabilities * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER * @caps: Array with at least two elements to hold the results + * @ncaps: Number of elements in the caps array * * Reads the USB4 port lane margining capabilities into @caps. + * + * Return: %0 on success, negative errno otherwise. */ -int usb4_port_margining_caps(struct tb_port *port, u32 *caps) +int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *caps, size_t ncaps) { int ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_READ_LANE_MARGINING_CAP, 500); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_DATA, caps, sizeof(*caps) * 2); + return usb4_port_sb_read(port, target, index, USB4_SB_DATA, caps, + sizeof(*caps) * ncaps); } /** * usb4_port_hw_margin() - Run hardware lane margining on port * @port: USB4 port - * @lanes: Which lanes to run (must match the port capabilities). Can be - * %0, %1 or %7. - * @ber_level: BER level contour value - * @timing: Perform timing margining instead of voltage - * @right_high: Use Right/high margin instead of left/low - * @results: Array with at least two elements to hold the results + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER + * @params: Parameters for USB4 hardware margining + * @results: Array to hold the results + * @nresults: Number of elements in the results array * * Runs hardware lane margining on USB4 port and returns the result in * @results. + * + * Return: %0 on success, negative errno otherwise. */ -int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, - unsigned int ber_level, bool timing, bool right_high, - u32 *results) +int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, const struct usb4_port_margining_params *params, + u32 *results, size_t nresults) { u32 val; int ret; - val = lanes; - if (timing) - val |= USB4_MARGIN_HW_TIME; - if (right_high) - val |= USB4_MARGIN_HW_RH; - if (ber_level) - val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) & - USB4_MARGIN_HW_BER_MASK; + if (WARN_ON_ONCE(!params)) + return -EINVAL; - ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, &val, sizeof(val)); + val = params->lanes; + if (params->time) + val |= USB4_MARGIN_HW_TIME; + if (params->right_high || params->upper_eye) + val |= USB4_MARGIN_HW_RHU; + if (params->ber_level) + val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level); + if (params->optional_voltage_offset_range) + val |= USB4_MARGIN_HW_OPT_VOLTAGE; + + ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, + sizeof(val)); if (ret) return ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_RUN_HW_LANE_MARGINING, 2500); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_DATA, results, sizeof(*results) * 2); + return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results, + sizeof(*results) * nresults); } /** * usb4_port_sw_margin() - Run software lane margining on port * @port: USB4 port - * @lanes: Which lanes to run (must match the port capabilities). Can be - * %0, %1 or %7. - * @timing: Perform timing margining instead of voltage - * @right_high: Use Right/high margin instead of left/low - * @counter: What to do with the error counter + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER + * @params: Parameters for USB4 software margining + * @results: Data word for the operation completion data * * Runs software lane margining on USB4 port. Read back the error - * counters by calling usb4_port_sw_margin_errors(). Returns %0 in - * success and negative errno otherwise. + * counters by calling usb4_port_sw_margin_errors(). + * + * Return: %0 on success, negative errno otherwise. */ -int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing, - bool right_high, u32 counter) +int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, const struct usb4_port_margining_params *params, + u32 *results) { u32 val; int ret; - val = lanes; - if (timing) + if (WARN_ON_ONCE(!params)) + return -EINVAL; + + val = params->lanes; + if (params->time) val |= USB4_MARGIN_SW_TIME; - if (right_high) + if (params->optional_voltage_offset_range) + val |= USB4_MARGIN_SW_OPT_VOLTAGE; + if (params->right_high) val |= USB4_MARGIN_SW_RH; - val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) & - USB4_MARGIN_SW_COUNTER_MASK; + if (params->upper_eye) + val |= USB4_MARGIN_SW_UPPER_EYE; + val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter); + val |= FIELD_PREP(USB4_MARGIN_SW_VT_MASK, params->voltage_time_offset); - ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, &val, sizeof(val)); + ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, + sizeof(val)); if (ret) return ret; - return usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500); + ret = usb4_port_sb_op(port, target, index, + USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500); + if (ret) + return ret; + + return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results, + sizeof(*results)); + } /** * usb4_port_sw_margin_errors() - Read the software margining error counters * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if target is %USB4_SB_TARGET_RETIMER * @errors: Error metadata is copied here. * * This reads back the software margining error counters from the port. - * Returns %0 in success and negative errno otherwise. + * + * Return: %0 on success, negative errno otherwise. */ -int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors) +int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *errors) { int ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_READ_SW_MARGIN_ERR, 150); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, errors, sizeof(*errors)); + return usb4_port_sb_read(port, target, index, USB4_SB_METADATA, errors, + sizeof(*errors)); } static inline int usb4_port_retimer_op(struct tb_port *port, u8 index, @@ -1587,8 +1853,10 @@ static inline int usb4_port_retimer_op(struct tb_port *port, u8 index, * @port: USB4 port * @index: Retimer index * - * Enables sideband channel transations on SBTX. Can be used when USB4 + * Enables sideband channel transactions on SBTX. Can be used when USB4 * link does not go up, for example if there is no device connected. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index) { @@ -1614,8 +1882,10 @@ int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index) * @port: USB4 port * @index: Retimer index * - * Disables sideband channel transations on SBTX. The reverse of + * Disables sideband channel transactions on SBTX. The reverse of * usb4_port_retimer_set_inbound_sbtx(). + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index) { @@ -1624,68 +1894,55 @@ int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index) } /** - * usb4_port_retimer_read() - Read from retimer sideband registers + * usb4_port_retimer_is_last() - Is the retimer last on-board retimer * @port: USB4 port * @index: Retimer index - * @reg: Sideband register to read - * @buf: Data from @reg is stored here - * @size: Number of bytes to read * - * Function reads retimer sideband registers starting from @reg. The - * retimer is connected to @port at @index. Returns %0 in case of - * success, and read data is copied to @buf. If there is no retimer - * present at given @index returns %-ENODEV. In any other failure - * returns negative errno. + * Return: + * * %1 - Retimer at @index is the last one (connected directly to the + * Type-C port). + * * %0 - Retimer at @index is not the last one. + * * %-ENODEV - Retimer is not present. + * * Negative errno - Other failure occurred. */ -int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, - u8 size) +int usb4_port_retimer_is_last(struct tb_port *port, u8 index) { - return usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, reg, buf, - size); -} + u32 metadata; + int ret; -/** - * usb4_port_retimer_write() - Write to retimer sideband registers - * @port: USB4 port - * @index: Retimer index - * @reg: Sideband register to write - * @buf: Data that is written starting from @reg - * @size: Number of bytes to write - * - * Writes retimer sideband registers starting from @reg. The retimer is - * connected to @port at @index. Returns %0 in case of success. If there - * is no retimer present at given @index returns %-ENODEV. In any other - * failure returns negative errno. - */ -int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg, - const void *buf, u8 size) -{ - return usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, reg, buf, - size); + ret = usb4_port_retimer_op(port, index, USB4_SB_OPCODE_QUERY_LAST_RETIMER, + 500); + if (ret) + return ret; + + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); + return ret ? ret : metadata & 1; } /** - * usb4_port_retimer_is_last() - Is the retimer last on-board retimer + * usb4_port_retimer_is_cable() - Is the retimer cable retimer * @port: USB4 port * @index: Retimer index * - * If the retimer at @index is last one (connected directly to the - * Type-C port) this function returns %1. If it is not returns %0. If - * the retimer is not present returns %-ENODEV. Otherwise returns - * negative errno. + * Return: + * * %1 - Retimer at @index is the last cable retimer. + * * %0 - Retimer at @index is on-board retimer. + * * %-ENODEV - Retimer is not present. + * * Negative errno - Other failure occurred. */ -int usb4_port_retimer_is_last(struct tb_port *port, u8 index) +int usb4_port_retimer_is_cable(struct tb_port *port, u8 index) { u32 metadata; int ret; - ret = usb4_port_retimer_op(port, index, USB4_SB_OPCODE_QUERY_LAST_RETIMER, + ret = usb4_port_retimer_op(port, index, USB4_SB_OPCODE_QUERY_CABLE_RETIMER, 500); if (ret) return ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); return ret ? ret : metadata & 1; } @@ -1696,9 +1953,12 @@ int usb4_port_retimer_is_last(struct tb_port *port, u8 index) * * Reads NVM sector size (in bytes) of a retimer at @index. This * operation can be used to determine whether the retimer supports NVM - * upgrade for example. Returns sector size in bytes or negative errno - * in case of error. Specifically returns %-ENODEV if there is no - * retimer at @index. + * upgrade for example. + * + * Return: + * * Sector size in bytes. + * * %-ENODEV - If there is no retimer at @index. + * * Negative errno - In case of an error. */ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index) { @@ -1710,8 +1970,8 @@ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index) if (ret) return ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); return ret ? ret : metadata & USB4_NVM_SECTOR_SIZE_MASK; } @@ -1721,10 +1981,10 @@ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index) * @index: Retimer index * @address: Start offset * - * Exlicitly sets NVM write offset. Normally when writing to NVM this is + * Explicitly 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. + * Return: %0 on success, negative errno otherwise. */ int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, unsigned int address) @@ -1736,8 +1996,8 @@ int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, metadata = (dwaddress << USB4_NVM_SET_OFFSET_SHIFT) & USB4_NVM_SET_OFFSET_MASK; - ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); if (ret) return ret; @@ -1759,8 +2019,8 @@ static int usb4_port_retimer_nvm_write_next_block(void *data, u8 index = info->index; int ret; - ret = usb4_port_retimer_write(port, index, USB4_SB_DATA, - buf, dwords * 4); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_DATA, buf, dwords * 4); if (ret) return ret; @@ -1777,9 +2037,12 @@ static int usb4_port_retimer_nvm_write_next_block(void *data, * @size: Size in bytes how much to write * * Writes @size bytes from @buf to the retimer NVM. Used for NVM - * upgrade. Returns %0 if the data was written successfully and negative - * errno in case of failure. Specifically returns %-ENODEV if there is - * no retimer at @index. + * upgrade. + * + * Return: + * * %0 - If the data was written successfully. + * * %-ENODEV - If there is no retimer at @index. + * * Negative errno - In case of an error. */ int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index, unsigned int address, const void *buf, size_t size) @@ -1805,6 +2068,8 @@ int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index, unsigned int add * successful the retimer restarts with the new NVM and may not have the * index set so one needs to call usb4_port_enumerate_retimers() to * force index to be assigned. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_port_retimer_nvm_authenticate(struct tb_port *port, u8 index) { @@ -1829,9 +2094,9 @@ int usb4_port_retimer_nvm_authenticate(struct tb_port *port, u8 index) * This can be called after usb4_port_retimer_nvm_authenticate() and * usb4_port_enumerate_retimers() to fetch status of the NVM upgrade. * - * Returns %0 if the authentication status was successfully read. The + * Return: %0 if the authentication status was successfully read. The * completion metadata (the result) is then stored into @status. If - * reading the status fails, returns negative errno. + * status read fails, returns negative errno. */ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index, u32 *status) @@ -1839,8 +2104,8 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index, u32 metadata, val; int ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_OPCODE, &val, - sizeof(val)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_OPCODE, &val, sizeof(val)); if (ret) return ret; @@ -1851,8 +2116,9 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index, return 0; case -EAGAIN: - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, - &metadata, sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, + sizeof(metadata)); if (ret) return ret; @@ -1877,8 +2143,8 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, if (dwords < USB4_DATA_DWORDS) metadata |= dwords << USB4_NVM_READ_LENGTH_SHIFT; - ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); if (ret) return ret; @@ -1886,8 +2152,8 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, if (ret) return ret; - return usb4_port_retimer_read(port, index, USB4_SB_DATA, buf, - dwords * 4); + return usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_DATA, buf, dwords * 4); } /** @@ -1898,9 +2164,12 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, * @buf: Data read from NVM is stored here * @size: Number of bytes to read * - * Reads retimer NVM and copies the contents to @buf. Returns %0 if the - * read was successful and negative errno in case of failure. - * Specifically returns %-ENODEV if there is no retimer at @index. + * Reads retimer NVM and copies the contents to @buf. + * + * Return: + * * %0 - If the read was successful. + * * %-ENODEV - If there is no retimer at @index. + * * Negative errno - In case of an error. */ int usb4_port_retimer_nvm_read(struct tb_port *port, u8 index, unsigned int address, void *buf, size_t size) @@ -1921,11 +2190,11 @@ usb4_usb3_port_max_bandwidth(const struct tb_port *port, unsigned int bw) } /** - * usb4_usb3_port_max_link_rate() - Maximum support USB3 link rate + * usb4_usb3_port_max_link_rate() - Maximum supported USB3 link rate * @port: USB3 adapter port * - * Return maximum supported link rate of a USB3 adapter in Mb/s. - * Negative errno in case of error. + * Return: Maximum supported link rate of a USB3 adapter in Mb/s. + * Negative errno in case of an error. */ int usb4_usb3_port_max_link_rate(struct tb_port *port) { @@ -1946,35 +2215,6 @@ int usb4_usb3_port_max_link_rate(struct tb_port *port) return usb4_usb3_port_max_bandwidth(port, ret); } -/** - * usb4_usb3_port_actual_link_rate() - Established USB3 link rate - * @port: USB3 adapter port - * - * Return actual established link rate of a USB3 adapter in Mb/s. If the - * link is not up returns %0 and negative errno in case of failure. - */ -int usb4_usb3_port_actual_link_rate(struct tb_port *port) -{ - int ret, lr; - u32 val; - - if (!tb_port_is_usb3_down(port) && !tb_port_is_usb3_up(port)) - return -EINVAL; - - ret = tb_port_read(port, &val, TB_CFG_PORT, - port->cap_adap + ADP_USB3_CS_4, 1); - if (ret) - return ret; - - if (!(val & ADP_USB3_CS_4_ULV)) - return 0; - - lr = val & ADP_USB3_CS_4_ALR_MASK; - ret = lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000; - - return usb4_usb3_port_max_bandwidth(port, ret); -} - static int usb4_usb3_port_cm_request(struct tb_port *port, bool request) { int ret; @@ -2006,7 +2246,8 @@ static int usb4_usb3_port_cm_request(struct tb_port *port, bool request) */ val &= ADP_USB3_CS_2_CMR; return usb4_port_wait_for_bit(port, port->cap_adap + ADP_USB3_CS_1, - ADP_USB3_CS_1_HCA, val, 1500); + ADP_USB3_CS_1_HCA, val, 1500, + USB4_PORT_DELAY); } static inline int usb4_usb3_port_set_cm_request(struct tb_port *port) @@ -2071,8 +2312,9 @@ static int usb4_usb3_port_read_allocated_bandwidth(struct tb_port *port, * @downstream_bw: Allocated downstream bandwidth is stored here * * Stores currently allocated USB3 bandwidth into @upstream_bw and - * @downstream_bw in Mb/s. Returns %0 in case of success and negative - * errno in failure. + * @downstream_bw in Mb/s. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_usb3_port_allocated_bandwidth(struct tb_port *port, int *upstream_bw, int *downstream_bw) @@ -2174,8 +2416,7 @@ static int usb4_usb3_port_write_allocated_bandwidth(struct tb_port *port, * cannot be taken away by CM). The actual new values are returned in * @upstream_bw and @downstream_bw. * - * Returns %0 in case of success and negative errno if there was a - * failure. + * Return: %0 on success, negative errno otherwise. */ int usb4_usb3_port_allocate_bandwidth(struct tb_port *port, int *upstream_bw, int *downstream_bw) @@ -2217,7 +2458,7 @@ err_request: * Releases USB3 allocated bandwidth down to what is actually consumed. * The new bandwidth is returned in @upstream_bw and @downstream_bw. * - * Returns 0% in success and negative errno in case of failure. + * Return: %0 on success, negative errno otherwise. */ int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, int *downstream_bw) @@ -2234,13 +2475,13 @@ int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, goto err_request; /* - * Always keep 1000 Mb/s to make sure xHCI has at least some + * Always keep 900 Mb/s to make sure xHCI has at least some * bandwidth available for isochronous traffic. */ - if (consumed_up < 1000) - consumed_up = 1000; - if (consumed_down < 1000) - consumed_down = 1000; + if (consumed_up < 900) + consumed_up = 900; + if (consumed_down < 900) + consumed_down = 900; ret = usb4_usb3_port_write_allocated_bandwidth(port, consumed_up, consumed_down); @@ -2269,9 +2510,12 @@ static bool is_usb4_dpin(const struct tb_port *port) * @port: DP IN adapter * @cm_id: CM ID to assign * - * Sets CM ID for the @port. Returns %0 on success and negative errno - * otherwise. Speficially returns %-EOPNOTSUPP if the @port does not - * support this. + * Sets CM ID for the @port. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the @port does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id) { @@ -2298,8 +2542,10 @@ int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id) * supported * @port: DP IN adapter to check * - * Can be called to any DP IN adapter. Returns true if the adapter - * supports USB4 bandwidth allocation mode, false otherwise. + * Can be called to any DP IN adapter. + * + * Return: %true if the adapter supports USB4 bandwidth allocation mode, + * %false otherwise. */ bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port) { @@ -2322,8 +2568,10 @@ bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port) * enabled * @port: DP IN adapter to check * - * Can be called to any DP IN adapter. Returns true if the bandwidth - * allocation mode has been enabled, false otherwise. + * Can be called to any DP IN adapter. + * + * Return: %true if the bandwidth allocation mode has been enabled, + * %false otherwise. */ bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port) { @@ -2348,9 +2596,12 @@ bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port) * @supported: Does the CM support bandwidth allocation mode * * Can be called to any DP IN adapter. Sets or clears the CM support bit - * of the DP IN adapter. Returns %0 in success and negative errno - * otherwise. Specifically returns %-OPNOTSUPP if the passed in adapter - * does not support this. + * of the DP IN adapter. + * + * * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the passed IN adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port, bool supported) @@ -2380,8 +2631,12 @@ int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port, * @port: DP IN adapter * * Reads bandwidth allocation Group ID from the DP IN adapter and - * returns it. If the adapter does not support setting Group_ID - * %-EOPNOTSUPP is returned. + * returns it. + * + * Return: + * * Group ID assigned to adapter @port. + * * %-EOPNOTSUPP - If adapter does not support setting GROUP_ID. + * * Negative errno - Another error occurred. */ int usb4_dp_port_group_id(struct tb_port *port) { @@ -2405,9 +2660,11 @@ int usb4_dp_port_group_id(struct tb_port *port) * @group_id: Group ID for the adapter * * Sets bandwidth allocation mode Group ID for the DP IN adapter. - * Returns %0 in case of success and negative errno otherwise. - * Specifically returns %-EOPNOTSUPP if the adapter does not support - * this. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_group_id(struct tb_port *port, int group_id) { @@ -2435,9 +2692,12 @@ int usb4_dp_port_set_group_id(struct tb_port *port, int group_id) * @rate: Non-reduced rate in Mb/s is placed here * @lanes: Non-reduced lanes are placed here * - * Reads the non-reduced rate and lanes from the DP IN adapter. Returns - * %0 in success and negative errno otherwise. Specifically returns - * %-EOPNOTSUPP if the adapter does not support this. + * Reads the non-reduced rate and lanes from the DP IN adapter. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_nrd(struct tb_port *port, int *rate, int *lanes) { @@ -2490,10 +2750,13 @@ int usb4_dp_port_nrd(struct tb_port *port, int *rate, int *lanes) * @rate: Non-reduced rate in Mb/s * @lanes: Non-reduced lanes * - * Before the capabilities reduction this function can be used to set - * the non-reduced values for the DP IN adapter. Returns %0 in success - * and negative errno otherwise. If the adapter does not support this - * %-EOPNOTSUPP is returned. + * Before the capabilities reduction, this function can be used to set + * the non-reduced values for the DP IN adapter. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_nrd(struct tb_port *port, int rate, int lanes) { @@ -2552,9 +2815,13 @@ int usb4_dp_port_set_nrd(struct tb_port *port, int rate, int lanes) * usb4_dp_port_granularity() - Return granularity for the bandwidth values * @port: DP IN adapter * - * Reads the programmed granularity from @port. If the DP IN adapter does - * not support bandwidth allocation mode returns %-EOPNOTSUPP and negative - * errno in other error cases. + * Reads the programmed granularity from @port. + * + * Return: + * * Granularity value of a @port. + * * %-EOPNOTSUPP - If the DP IN adapter does not support bandwidth + * allocation mode. + * * Negative errno - Another error occurred. */ int usb4_dp_port_granularity(struct tb_port *port) { @@ -2590,8 +2857,12 @@ int usb4_dp_port_granularity(struct tb_port *port) * @granularity: Granularity in Mb/s. Supported values: 1000, 500 and 250. * * Sets the granularity used with the estimated, allocated and requested - * bandwidth. Returns %0 in success and negative errno otherwise. If the - * adapter does not support this %-EOPNOTSUPP is returned. + * bandwidth. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity) { @@ -2632,10 +2903,13 @@ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity) * @bw: Estimated bandwidth in Mb/s. * * Sets the estimated bandwidth to @bw. Set the granularity by calling - * usb4_dp_port_set_granularity() before calling this. The @bw is round - * down to the closest granularity multiplier. Returns %0 in success - * and negative errno otherwise. Specifically returns %-EOPNOTSUPP if - * the adapter does not support this. + * usb4_dp_port_set_granularity() before calling this. The @bw is rounded + * down to the closest granularity multiplier. + * + * Return: + * * %0 - On success. + * * %-EOPNOTSUPP - If the adapter does not support this. + * * Negative errno - Another error occurred. */ int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw) { @@ -2666,9 +2940,10 @@ int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw) * usb4_dp_port_allocated_bandwidth() - Return allocated bandwidth * @port: DP IN adapter * - * Reads and returns allocated bandwidth for @port in Mb/s (taking into - * account the programmed granularity). Returns negative errno in case - * of error. + * Reads the allocated bandwidth for @port in Mb/s (taking into account + * the programmed granularity). + * + * Return: Allocated bandwidth in Mb/s or negative errno in case of an error. */ int usb4_dp_port_allocated_bandwidth(struct tb_port *port) { @@ -2742,8 +3017,10 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port, usleep_range(50, 100); } while (ktime_before(ktime_get(), end)); - if (val & ADP_DP_CS_8_DR) + if (val & ADP_DP_CS_8_DR) { + tb_port_warn(port, "timeout waiting for DPTX request to clear\n"); return -ETIMEDOUT; + } ret = tb_port_read(port, &val, TB_CFG_PORT, port->cap_adap + ADP_DP_CS_2, 1); @@ -2761,8 +3038,9 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port, * @bw: New allocated bandwidth in Mb/s * * Communicates the new allocated bandwidth with the DPCD (graphics - * driver). Takes into account the programmed granularity. Returns %0 in - * success and negative errno in case of error. + * driver). Takes into account the programmed granularity. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw) { @@ -2802,10 +3080,15 @@ int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw) * @port: DP IN adapter * * Reads the DPCD (graphics driver) requested bandwidth and returns it - * in Mb/s. Takes the programmed granularity into account. In case of - * error returns negative errno. Specifically returns %-EOPNOTSUPP if - * the adapter does not support bandwidth allocation mode, and %ENODATA - * if there is no active bandwidth request from the graphics driver. + * in Mb/s. Takes the programmed granularity into account. + * + * Return: + * * Requested bandwidth in Mb/s - On success. + * * %-EOPNOTSUPP - If the adapter does not support bandwidth allocation + * mode. + * * %ENODATA - If there is no active bandwidth request from the graphics + * driver. + * * Negative errno - On failure. */ int usb4_dp_port_requested_bandwidth(struct tb_port *port) { @@ -2837,8 +3120,9 @@ int usb4_dp_port_requested_bandwidth(struct tb_port *port) * @enable: Enable/disable extended encapsulation * * Enables or disables extended encapsulation used in PCIe tunneling. Caller - * needs to make sure both adapters support this before enabling. Returns %0 on - * success and negative errno otherwise. + * needs to make sure both adapters support this before enabling. + * + * Return: %0 on success, negative errno otherwise. */ int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable) { |
