Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Thunderbolt driver - capabilities lookup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2018, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "tb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #define CAP_OFFSET_MAX		0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define VSE_CAP_OFFSET_MAX	0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define TMU_ACCESS_EN		BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static int tb_port_enable_tmu(struct tb_port *port, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	struct tb_switch *sw = port->sw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	u32 value, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	 * Legacy devices need to have TMU access enabled before port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	 * space can be fully accessed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	if (tb_switch_is_light_ridge(sw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		offset = 0x26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	else if (tb_switch_is_eagle_ridge(sw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		offset = 0x2a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	ret = tb_sw_read(sw, &value, TB_CFG_SWITCH, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		value |= TMU_ACCESS_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		value &= ~TMU_ACCESS_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	return tb_sw_write(sw, &value, TB_CFG_SWITCH, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static void tb_port_dummy_read(struct tb_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	 * When reading from next capability pointer location in port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	 * config space the read data is not cleared on LR. To avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	 * reading stale data on next read perform one dummy read after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	 * port capabilities are walked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	if (tb_switch_is_light_ridge(port->sw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		u32 dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		tb_port_read(port, &dummy, TB_CFG_PORT, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * tb_port_next_cap() - Return next capability in the linked list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * @port: Port to find the capability for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * @offset: Previous capability offset (%0 for start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * Returns dword offset of the next capability in port config space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * capability list and returns it. Passing %0 returns the first entry in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * the capability list. If no next capability is found returns %0. In case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * of failure returns negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) int tb_port_next_cap(struct tb_port *port, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct tb_cap_any header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (!offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		return port->config.first_cap_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	ret = tb_port_read(port, &header, TB_CFG_PORT, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return header.basic.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static int __tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		struct tb_cap_any header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		offset = tb_port_next_cap(port, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		if (offset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		ret = tb_port_read(port, &header, TB_CFG_PORT, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		if (header.basic.cap == cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	} while (offset > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * tb_port_find_cap() - Find port capability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @port: Port to find the capability for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * @cap: Capability to look
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * Returns offset to start of capability or %-ENOENT if no such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * capability was found. Negative errno is returned if there was an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	ret = tb_port_enable_tmu(port, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	ret = __tb_port_find_cap(port, cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	tb_port_dummy_read(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	tb_port_enable_tmu(port, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  * tb_switch_next_cap() - Return next capability in the linked list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  * @sw: Switch to find the capability for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  * @offset: Previous capability offset (%0 for start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * Finds dword offset of the next capability in router config space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * capability list and returns it. Passing %0 returns the first entry in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * the capability list. If no next capability is found returns %0. In case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * of failure returns negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	struct tb_cap_any header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	if (!offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		return sw->config.first_cap_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	switch (header.basic.cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	case TB_SWITCH_CAP_TMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		ret = header.basic.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	case TB_SWITCH_CAP_VSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		if (!header.extended_short.length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			ret = header.extended_long.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			ret = header.extended_short.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		tb_sw_dbg(sw, "unknown capability %#x at %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			  header.basic.cap, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return ret >= VSE_CAP_OFFSET_MAX ? 0 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * tb_switch_find_cap() - Find switch capability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * @sw Switch to find the capability for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * @cap: Capability to look
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * Returns offset to start of capability or %-ENOENT if no such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * capability was found. Negative errno is returned if there was an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		struct tb_cap_any header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		offset = tb_switch_next_cap(sw, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		if (offset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		if (header.basic.cap == cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	} while (offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * tb_switch_find_vse_cap() - Find switch vendor specific capability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * @sw: Switch to find the capability for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * @vsec: Vendor specific capability to look
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  * Functions enumerates vendor specific capabilities (VSEC) of a switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * and returns offset when capability matching @vsec is found. If no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * such capability is found returns %-ENOENT. In case of error returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		struct tb_cap_any header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		offset = tb_switch_next_cap(sw, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		if (offset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		if (header.extended_short.cap == TB_SWITCH_CAP_VSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		    header.extended_short.vsec_id == vsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	} while (offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }