Skip to content

Commit

Permalink
thunderbolt: Add support for DisplayPort bandwidth allocation mode
Browse files Browse the repository at this point in the history
The USB4 spec defines an optional feature that allows the connection
manager to negotiate with the graphics through DPCD registers changes in
the bandwidth allocation dynamically. This is referred as "bandwidth
allocation mode" in the spec. The connection manager uses DP IN adapters
registers to communicate with the graphics, and also gets notifications
from these adapters when the graphics wants to change the bandwidth
allocation. Both the connection manager and the graphics driver needs to
support this.

We check if the DP IN adapter supports this and if it does enable it
before establishing a DP tunnel. Then we react on DP_BW notifications
coming from the DP IN adapter and update the bandwidth allocation
accordingly (within the maximum common capabilities the DP IN/OUT
support).

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
  • Loading branch information
Mika Westerberg committed Jan 17, 2023
1 parent 630f211 commit 6ce3563
Show file tree
Hide file tree
Showing 7 changed files with 1,023 additions and 56 deletions.
50 changes: 42 additions & 8 deletions drivers/thunderbolt/ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ static int check_config_address(struct tb_cfg_address addr,
static struct tb_cfg_result decode_error(const struct ctl_pkg *response)
{
struct cfg_error_pkg *pkg = response->buffer;
struct tb_ctl *ctl = response->ctl;
struct tb_cfg_result res = { 0 };
res.response_route = tb_cfg_get_route(&pkg->header);
res.response_port = 0;
Expand All @@ -239,13 +238,6 @@ static struct tb_cfg_result decode_error(const struct ctl_pkg *response)
if (res.err)
return res;

if (pkg->zero1)
tb_ctl_warn(ctl, "pkg->zero1 is %#x\n", pkg->zero1);
if (pkg->zero2)
tb_ctl_warn(ctl, "pkg->zero2 is %#x\n", pkg->zero2);
if (pkg->zero3)
tb_ctl_warn(ctl, "pkg->zero3 is %#x\n", pkg->zero3);

res.err = 1;
res.tb_error = pkg->error;
res.response_port = pkg->port;
Expand Down Expand Up @@ -416,6 +408,7 @@ static int tb_async_error(const struct ctl_pkg *pkg)
case TB_CFG_ERROR_LINK_ERROR:
case TB_CFG_ERROR_HEC_ERROR_DETECTED:
case TB_CFG_ERROR_FLOW_CONTROL_ERROR:
case TB_CFG_ERROR_DP_BW:
return true;

default:
Expand Down Expand Up @@ -735,6 +728,47 @@ void tb_ctl_stop(struct tb_ctl *ctl)

/* public interface, commands */

/**
* tb_cfg_ack_notification() - Ack notification
* @ctl: Control channel to use
* @route: Router that originated the event
* @error: Pointer to the notification package
*
* Call this as response for non-plug notification to ack it. Returns
* %0 on success or an error code on failure.
*/
int tb_cfg_ack_notification(struct tb_ctl *ctl, u64 route,
const struct cfg_error_pkg *error)
{
struct cfg_ack_pkg pkg = {
.header = tb_cfg_make_header(route),
};
const char *name;

switch (error->error) {
case TB_CFG_ERROR_LINK_ERROR:
name = "link error";
break;
case TB_CFG_ERROR_HEC_ERROR_DETECTED:
name = "HEC error";
break;
case TB_CFG_ERROR_FLOW_CONTROL_ERROR:
name = "flow control error";
break;
case TB_CFG_ERROR_DP_BW:
name = "DP_BW";
break;
default:
name = "unknown";
break;
}

tb_ctl_dbg(ctl, "acking %s (%#x) notification on %llx\n", name,
error->error, route);

return tb_ctl_tx(ctl, &pkg, sizeof(pkg), TB_CFG_PKG_NOTIFY_ACK);
}

/**
* tb_cfg_ack_plug() - Ack hot plug/unplug event
* @ctl: Control channel to use
Expand Down
2 changes: 2 additions & 0 deletions drivers/thunderbolt/ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ static inline struct tb_cfg_header tb_cfg_make_header(u64 route)
return header;
}

int tb_cfg_ack_notification(struct tb_ctl *ctl, u64 route,
const struct cfg_error_pkg *error);
int tb_cfg_ack_plug(struct tb_ctl *ctl, u64 route, u32 port, bool unplug);
struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route);
struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
Expand Down
Loading

0 comments on commit 6ce3563

Please sign in to comment.