^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) }