// SPDX-License-Identifier: GPL-2.0 /* * Thunderbolt driver - path/tunnel functionality * * Copyright (c) 2014 Andreas Noever <[email protected]> * Copyright (C) 2019, Intel Corporation */ #include <linux/slab.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/ktime.h> #include "tb.h" static void tb_dump_hop(const struct tb_path_hop *hop, const struct tb_regs_hop *regs) { … } static struct tb_port *tb_path_find_dst_port(struct tb_port *src, int src_hopid, int dst_hopid) { … } static int tb_path_find_src_hopid(struct tb_port *src, const struct tb_port *dst, int dst_hopid) { … } /** * tb_path_discover() - Discover a path * @src: First input port of a path * @src_hopid: Starting HopID of a path (%-1 if don't care) * @dst: Expected destination port of the path (%NULL if don't care) * @dst_hopid: HopID to the @dst (%-1 if don't care) * @last: Last port is filled here if not %NULL * @name: Name of the path * @alloc_hopid: Allocate HopIDs for the ports * * Follows a path starting from @src and @src_hopid to the last output * port of the path. Allocates HopIDs for the visited ports (if * @alloc_hopid is true). Call tb_path_free() to release the path and * allocated HopIDs when the path is not needed anymore. * * Note function discovers also incomplete paths so caller should check * that the @dst port is the expected one. If it is not, the path can be * cleaned up by calling tb_path_deactivate() before tb_path_free(). * * Return: Discovered path on success, %NULL in case of failure */ struct tb_path *tb_path_discover(struct tb_port *src, int src_hopid, struct tb_port *dst, int dst_hopid, struct tb_port **last, const char *name, bool alloc_hopid) { … } /** * tb_path_alloc() - allocate a thunderbolt path between two ports * @tb: Domain pointer * @src: Source port of the path * @src_hopid: HopID used for the first ingress port in the path * @dst: Destination port of the path * @dst_hopid: HopID used for the last egress port in the path * @link_nr: Preferred link if there are dual links on the path * @name: Name of the path * * Creates path between two ports starting with given @src_hopid. Reserves * HopIDs for each port (they can be different from @src_hopid depending on * how many HopIDs each port already have reserved). If there are dual * links on the path, prioritizes using @link_nr but takes into account * that the lanes may be bonded. * * Return: Returns a tb_path on success or NULL on failure. */ struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid, struct tb_port *dst, int dst_hopid, int link_nr, const char *name) { … } /** * tb_path_free() - free a path * @path: Path to free * * Frees a path. The path does not need to be deactivated. */ void tb_path_free(struct tb_path *path) { … } static void __tb_path_deallocate_nfc(struct tb_path *path, int first_hop) { … } static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index, bool clear_fc) { … } /** * tb_path_deactivate_hop() - Deactivate one path in path config space * @port: Lane or protocol adapter * @hop_index: HopID of the path to be cleared * * This deactivates or clears a single path config space entry at * @hop_index. Returns %0 in success and negative errno otherwise. */ int tb_path_deactivate_hop(struct tb_port *port, int hop_index) { … } static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop) { … } void tb_path_deactivate(struct tb_path *path) { … } /** * tb_path_activate() - activate a path * @path: Path to activate * * Activate a path starting with the last hop and iterating backwards. The * caller must fill path->hops before calling tb_path_activate(). * * Return: Returns 0 on success or an error code on failure. */ int tb_path_activate(struct tb_path *path) { … } /** * tb_path_is_invalid() - check whether any ports on the path are invalid * @path: Path to check * * Return: Returns true if the path is invalid, false otherwise. */ bool tb_path_is_invalid(struct tb_path *path) { … } /** * tb_path_port_on_path() - Does the path go through certain port * @path: Path to check * @port: Switch to check * * Goes over all hops on path and checks if @port is any of them. * Direction does not matter. */ bool tb_path_port_on_path(const struct tb_path *path, const struct tb_port *port) { … }