Commit 0bd680cd authored by Mika Westerberg's avatar Mika Westerberg

thunderbolt: Add USB3 bandwidth management

USB3 supports both isochronous and non-isochronous traffic. The former
requires guaranteed bandwidth and can take up to 90% of the total
bandwidth. With USB4 USB3 is tunneled over USB4 fabric which means that
we need to make sure there is enough bandwidth allocated for the USB3
tunnels in addition to DisplayPort tunnels.

Whereas DisplayPort bandwidth management is static and done before the
DP tunnel is established, the USB3 bandwidth management is dynamic and
allows increasing and decreasing the allocated bandwidth according to
what is currently consumed. This is done through host router USB3
downstream adapter registers.

This adds USB3 bandwidth management to the software connection manager
so that we always try to allocate maximum bandwidth for DP tunnels and
what is left is allocated for USB3.
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 5b7b8c0a
......@@ -570,21 +570,20 @@ bool tb_path_is_invalid(struct tb_path *path)
}
/**
* tb_path_switch_on_path() - Does the path go through certain switch
* tb_path_port_on_path() - Does the path go through certain port
* @path: Path to check
* @sw: Switch to check
* @port: Switch to check
*
* Goes over all hops on path and checks if @sw is any of them.
* Goes over all hops on path and checks if @port is any of them.
* Direction does not matter.
*/
bool tb_path_switch_on_path(const struct tb_path *path,
const struct tb_switch *sw)
bool tb_path_port_on_path(const struct tb_path *path, const struct tb_port *port)
{
int i;
for (i = 0; i < path->path_length; i++) {
if (path->hops[i].in_port->sw == sw ||
path->hops[i].out_port->sw == sw)
if (path->hops[i].in_port == port ||
path->hops[i].out_port == port)
return true;
}
......
This diff is collapsed.
......@@ -789,8 +789,8 @@ void tb_path_free(struct tb_path *path);
int tb_path_activate(struct tb_path *path);
void tb_path_deactivate(struct tb_path *path);
bool tb_path_is_invalid(struct tb_path *path);
bool tb_path_switch_on_path(const struct tb_path *path,
const struct tb_switch *sw);
bool tb_path_port_on_path(const struct tb_path *path,
const struct tb_port *port);
int tb_drom_read(struct tb_switch *sw);
int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid);
......
This diff is collapsed.
......@@ -29,10 +29,16 @@ enum tb_tunnel_type {
* @init: Optional tunnel specific initialization
* @activate: Optional tunnel specific activation/deactivation
* @consumed_bandwidth: Return how much bandwidth the tunnel consumes
* @release_unused_bandwidth: Release all unused bandwidth
* @reclaim_available_bandwidth: Reclaim back available bandwidth
* @list: Tunnels are linked using this field
* @type: Type of the tunnel
* @max_bw: Maximum bandwidth (Mb/s) available for the tunnel (only for DP).
* @max_up: Maximum upstream bandwidth (Mb/s) available for the tunnel.
* Only set if the bandwidth needs to be limited.
* @max_down: Maximum downstream bandwidth (Mb/s) available for the tunnel.
* Only set if the bandwidth needs to be limited.
* @allocated_up: Allocated upstream bandwidth (only for USB3)
* @allocated_down: Allocated downstream bandwidth (only for USB3)
*/
struct tb_tunnel {
struct tb *tb;
......@@ -44,9 +50,16 @@ struct tb_tunnel {
int (*activate)(struct tb_tunnel *tunnel, bool activate);
int (*consumed_bandwidth)(struct tb_tunnel *tunnel, int *consumed_up,
int *consumed_down);
int (*release_unused_bandwidth)(struct tb_tunnel *tunnel);
void (*reclaim_available_bandwidth)(struct tb_tunnel *tunnel,
int *available_up,
int *available_down);
struct list_head list;
enum tb_tunnel_type type;
unsigned int max_bw;
int max_up;
int max_down;
int allocated_up;
int allocated_down;
};
struct tb_tunnel *tb_tunnel_discover_pci(struct tb *tb, struct tb_port *down);
......@@ -54,24 +67,30 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
struct tb_port *down);
struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in);
struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
struct tb_port *out, int max_bw);
struct tb_port *out, int max_up,
int max_down);
struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
struct tb_port *dst, int transmit_ring,
int transmit_path, int receive_ring,
int receive_path);
struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *tb, struct tb_port *down);
struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, struct tb_port *up,
struct tb_port *down);
struct tb_port *down, int max_up,
int max_down);
void tb_tunnel_free(struct tb_tunnel *tunnel);
int tb_tunnel_activate(struct tb_tunnel *tunnel);
int tb_tunnel_restart(struct tb_tunnel *tunnel);
void tb_tunnel_deactivate(struct tb_tunnel *tunnel);
bool tb_tunnel_is_invalid(struct tb_tunnel *tunnel);
bool tb_tunnel_switch_on_path(const struct tb_tunnel *tunnel,
const struct tb_switch *sw);
bool tb_tunnel_port_on_path(const struct tb_tunnel *tunnel,
const struct tb_port *port);
int tb_tunnel_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up,
int *consumed_down);
int tb_tunnel_release_unused_bandwidth(struct tb_tunnel *tunnel);
void tb_tunnel_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
int *available_up,
int *available_down);
static inline bool tb_tunnel_is_pci(const struct tb_tunnel *tunnel)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment