Commit 87212b51 authored by Lyude Paul's avatar Lyude Paul

drm/dp_mst: Reprobe path resources in CSN handler

We used to punt off reprobing path resources to the link address probe
work, but now that we handle CSNs asynchronously from the driver's HPD
handling we can do whatever the heck we want from the CSN!

So, reprobe the path resources from drm_dp_mst_handle_conn_stat(). Also,
get rid of the path resource reprobing code in
drm_dp_check_and_send_link_address() since it's needlessly complicated
when we already reprobe path resources from
drm_dp_handle_link_address_port(). And finally, teach
drm_dp_send_enum_path_resources() to return 1 on PBN changes so we know
if we need to send another hotplug or not.

This fixes issues where we've indicated to userspace that a port has
just been connected, before we actually probed it's available PBN -
something that results in unexpected atomic check failures.
Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Fixes: cd82d82c ("drm/dp_mst: Add branch bandwidth validation to MST atomic check")
Cc: Mikita Lipski <mikita.lipski@amd.com>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20200306234623.547525-4-lyude@redhat.comReviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Tested-by: default avatarHans de Goede <hdegoede@redhat.com>
parent fcf46380
...@@ -2302,12 +2302,16 @@ drm_dp_mst_handle_link_address_port(struct drm_dp_mst_branch *mstb, ...@@ -2302,12 +2302,16 @@ drm_dp_mst_handle_link_address_port(struct drm_dp_mst_branch *mstb,
mutex_unlock(&mgr->lock); mutex_unlock(&mgr->lock);
} }
if (old_ddps != port->ddps) { /*
if (port->ddps) { * Reprobe PBN caps on both hotplug, and when re-probing the link
if (!port->input) { * for our parent mstb
drm_dp_send_enum_path_resources(mgr, mstb, */
port); if (old_ddps != port->ddps || !created) {
} if (port->ddps && !port->input) {
ret = drm_dp_send_enum_path_resources(mgr, mstb,
port);
if (ret == 1)
changed = true;
} else { } else {
port->full_pbn = 0; port->full_pbn = 0;
} }
...@@ -2401,11 +2405,10 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, ...@@ -2401,11 +2405,10 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
port->ddps = conn_stat->displayport_device_plug_status; port->ddps = conn_stat->displayport_device_plug_status;
if (old_ddps != port->ddps) { if (old_ddps != port->ddps) {
if (port->ddps) { if (port->ddps && !port->input)
dowork = true; drm_dp_send_enum_path_resources(mgr, mstb, port);
} else { else
port->full_pbn = 0; port->full_pbn = 0;
}
} }
new_pdt = port->input ? DP_PEER_DEVICE_NONE : conn_stat->peer_device_type; new_pdt = port->input ? DP_PEER_DEVICE_NONE : conn_stat->peer_device_type;
...@@ -2556,13 +2559,6 @@ static int drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mg ...@@ -2556,13 +2559,6 @@ static int drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mg
if (port->input || !port->ddps) if (port->input || !port->ddps)
continue; continue;
if (!port->full_pbn) {
drm_modeset_lock(&mgr->base.lock, NULL);
drm_dp_send_enum_path_resources(mgr, mstb, port);
drm_modeset_unlock(&mgr->base.lock);
changed = true;
}
if (port->mstb) if (port->mstb)
mstb_child = drm_dp_mst_topology_get_mstb_validated( mstb_child = drm_dp_mst_topology_get_mstb_validated(
mgr, port->mstb); mgr, port->mstb);
...@@ -2990,6 +2986,7 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr, ...@@ -2990,6 +2986,7 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
if (ret > 0) { if (ret > 0) {
ret = 0;
path_res = &txmsg->reply.u.path_resources; path_res = &txmsg->reply.u.path_resources;
if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) { if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
...@@ -3002,13 +2999,22 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr, ...@@ -3002,13 +2999,22 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
path_res->port_number, path_res->port_number,
path_res->full_payload_bw_number, path_res->full_payload_bw_number,
path_res->avail_payload_bw_number); path_res->avail_payload_bw_number);
/*
* If something changed, make sure we send a
* hotplug
*/
if (port->full_pbn != path_res->full_payload_bw_number ||
port->fec_capable != path_res->fec_capable)
ret = 1;
port->full_pbn = path_res->full_payload_bw_number; port->full_pbn = path_res->full_payload_bw_number;
port->fec_capable = path_res->fec_capable; port->fec_capable = path_res->fec_capable;
} }
} }
kfree(txmsg); kfree(txmsg);
return 0; return ret;
} }
static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb) static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
...@@ -3595,13 +3601,9 @@ drm_dp_mst_topology_mgr_invalidate_mstb(struct drm_dp_mst_branch *mstb) ...@@ -3595,13 +3601,9 @@ drm_dp_mst_topology_mgr_invalidate_mstb(struct drm_dp_mst_branch *mstb)
/* The link address will need to be re-sent on resume */ /* The link address will need to be re-sent on resume */
mstb->link_address_sent = false; mstb->link_address_sent = false;
list_for_each_entry(port, &mstb->ports, next) { list_for_each_entry(port, &mstb->ports, next)
/* The PBN for each port will also need to be re-probed */
port->full_pbn = 0;
if (port->mstb) if (port->mstb)
drm_dp_mst_topology_mgr_invalidate_mstb(port->mstb); drm_dp_mst_topology_mgr_invalidate_mstb(port->mstb);
}
} }
/** /**
......
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