From: Lyude Paul <lyude@redhat.com>
To: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
Cc: Thomas Zimmermann <tzimmermann@suse.de>,
Jani Nikula <jani.nikula@intel.com>,
Daniel Vetter <daniel.vetter@ffwll.ch>,
open list <linux-kernel@vger.kernel.org>,
Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>,
David Airlie <airlied@linux.ie>, Fangzhi Zuo <Jerry.Zuo@amd.com>,
Daniel Vetter <daniel@ffwll.ch>, Wayne Lin <Wayne.Lin@amd.com>
Subject: [Intel-gfx] [RFC v2 15/18] drm/display/dp_mst: Skip releasing payloads if last connected port isn't connected
Date: Mon, 8 Aug 2022 19:52:00 -0400 [thread overview]
Message-ID: <20220808235203.123892-16-lyude@redhat.com> (raw)
In-Reply-To: <20220808235203.123892-1-lyude@redhat.com>
In the past, we've ran into strange issues regarding errors in response to
trying to destroy payloads after a port has been unplugged. We fixed this
back in:
This is intended to replace the workaround that was added here:
commit 3769e4c0af5b ("drm/dp_mst: Avoid to mess up payload table by ports in stale topology")
which was intended fix to some of the payload leaks that were observed
before, where we would attempt to determine if the port was still connected
to the topology before updating payloads using
drm_dp_mst_port_downstream_of_branch. This wasn't a particularly good
solution, since one of the points of still having port and mstb validation
is to avoid sending messages to newly disconnected branches wherever
possible - thus the required use of drm_dp_mst_port_downstream_of_branch
would indicate something may be wrong with said validation.
It seems like it may have just been races and luck that made
drm_dp_mst_port_downstream_of_branch work however, as while I was trying to
figure out the true cause of this issue when removing the legacy MST code -
I discovered an important excerpt in section 2.14.2.3.3.6 of the DP 2.0
specs:
"BAD_PARAM - This reply is transmitted when a Message Transaction parameter
is in error; for example, the next port number is invalid or /no device is
connected/ to the port associated with the port number."
Sure enough - removing the calls to drm_dp_mst_port_downstream_of_branch()
and instead checking the ->ddps field of the parent port to see whether we
should release a given payload or not seems to totally fix the issue. This
does actually make sense to me, as it seems the implication is that given a
topology where an MSTB is removed, the payload for the MST parent's port
will be released automatically if that port is also marked as disconnected.
However, if there's another parent in the chain after that which is
connected - payloads must be released there with an ALLOCATE_PAYLOAD
message.
So, let's do that!
Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: Wayne Lin <Wayne.Lin@amd.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Fangzhi Zuo <Jerry.Zuo@amd.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Sean Paul <sean@poorly.run>
Acked-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/display/drm_dp_mst_topology.c | 51 +++++++------------
1 file changed, 17 insertions(+), 34 deletions(-)
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index a5460cadf2c8..e9cf09a4b2a4 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3128,7 +3128,7 @@ static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm
static struct drm_dp_mst_branch *
drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_branch *mstb,
- int *port_num)
+ struct drm_dp_mst_port **last_port)
{
struct drm_dp_mst_branch *rmstb = NULL;
struct drm_dp_mst_port *found_port;
@@ -3144,7 +3144,8 @@ drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) {
rmstb = found_port->parent;
- *port_num = found_port->port_num;
+ *last_port = found_port;
+ drm_dp_mst_get_port_malloc(found_port);
} else {
/* Search again, starting from this parent */
mstb = found_port->parent;
@@ -3161,7 +3162,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
int pbn)
{
struct drm_dp_sideband_msg_tx *txmsg;
- struct drm_dp_mst_branch *mstb;
+ struct drm_dp_mst_branch *mstb = NULL;
int ret, port_num;
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
int i;
@@ -3169,12 +3170,22 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
port_num = port->port_num;
mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
if (!mstb) {
- mstb = drm_dp_get_last_connected_port_and_mstb(mgr,
- port->parent,
- &port_num);
+ struct drm_dp_mst_port *rport = NULL;
+ bool ddps;
+ mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &rport);
if (!mstb)
return -EINVAL;
+
+ ddps = rport->ddps;
+ port_num = rport->port_num;
+ drm_dp_mst_put_port_malloc(rport);
+
+ /* If the port is currently marked as disconnected, don't send a payload message */
+ if (!ddps) {
+ ret = -EINVAL;
+ goto fail_put;
+ }
}
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
@@ -3375,7 +3386,6 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_s
struct drm_dp_mst_port *port;
int i, j;
int cur_slots = start_slot;
- bool skip;
mutex_lock(&mgr->payload_lock);
for (i = 0; i < mgr->max_payloads; i++) {
@@ -3390,16 +3400,6 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_s
port = container_of(vcpi, struct drm_dp_mst_port,
vcpi);
- mutex_lock(&mgr->lock);
- skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
- mutex_unlock(&mgr->lock);
-
- if (skip) {
- drm_dbg_kms(mgr->dev,
- "Virtual channel %d is not in current topology\n",
- i);
- continue;
- }
/* Validated ports don't matter if we're releasing
* VCPI
*/
@@ -3500,7 +3500,6 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
struct drm_dp_mst_port *port;
int i;
int ret = 0;
- bool skip;
mutex_lock(&mgr->payload_lock);
for (i = 0; i < mgr->max_payloads; i++) {
@@ -3510,13 +3509,6 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
- mutex_lock(&mgr->lock);
- skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
- mutex_unlock(&mgr->lock);
-
- if (skip)
- continue;
-
drm_dbg_kms(mgr->dev, "payload %d %d\n", i, mgr->payloads[i].payload_state);
if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
@@ -4769,18 +4761,9 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port)
{
- bool skip;
-
if (!port->vcpi.vcpi)
return;
- mutex_lock(&mgr->lock);
- skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
- mutex_unlock(&mgr->lock);
-
- if (skip)
- return;
-
drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
port->vcpi.num_slots = 0;
port->vcpi.pbn = 0;
--
2.37.1
next prev parent reply other threads:[~2022-08-08 23:58 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-08 23:51 [Intel-gfx] [RFC v2 00/18] drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 01/18] drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table) Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 02/18] drm/amdgpu/dm/mst: Rename get_payload_table() Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 03/18] drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 04/18] drm/display/dp_mst: Call them time slots, not VCPI slots Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 05/18] drm/display/dp_mst: Fix confusing docs for drm_dp_atomic_release_time_slots() Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 07/18] drm/display/dp_mst: Add helper for finding payloads in atomic MST state Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 08/18] drm/display/dp_mst: Add nonblocking helpers for DP MST Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 09/18] drm/display/dp_mst: Don't open code modeset checks for releasing time slots Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 10/18] drm/display/dp_mst: Fix modeset tracking in drm_dp_atomic_release_vcpi_slots() Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 11/18] drm/nouveau/kms: Cache DP encoders in nouveau_connector Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 12/18] drm/nouveau/kms: Pull mst state in for all modesets Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 13/18] drm/display/dp_mst: Add helpers for serializing SST <-> MST transitions Lyude Paul
2022-08-09 23:42 ` [Intel-gfx] [RFC v3] " Lyude Paul
2022-08-08 23:51 ` [Intel-gfx] [RFC v2 14/18] drm/display/dp_mst: Drop all ports from topology on CSNs before queueing link address work Lyude Paul
2022-08-08 23:52 ` Lyude Paul [this message]
2022-08-08 23:52 ` [Intel-gfx] [RFC v2 16/18] drm/display/dp_mst: Maintain time slot allocations when deleting payloads Lyude Paul
2022-08-08 23:52 ` [Intel-gfx] [RFC v2 17/18] drm/radeon: Drop legacy MST support Lyude Paul
2022-08-08 23:52 ` [Intel-gfx] [RFC v2 18/18] drm/display/dp_mst: Move all payload info into the atomic state Lyude Paul
2022-08-09 0:21 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only Patchwork
2022-08-09 0:43 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2022-08-10 0:25 ` [Intel-gfx] ✓ Fi.CI.BAT: success for drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only (rev2) Patchwork
2022-08-10 3:08 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
2022-08-10 20:35 ` [Intel-gfx] ✓ Fi.CI.BAT: success for drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only (rev3) Patchwork
2022-08-11 9:46 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220808235203.123892-16-lyude@redhat.com \
--to=lyude@redhat.com \
--cc=Bhawanpreet.Lakha@amd.com \
--cc=Jerry.Zuo@amd.com \
--cc=Wayne.Lin@amd.com \
--cc=airlied@linux.ie \
--cc=amd-gfx@lists.freedesktop.org \
--cc=daniel.vetter@ffwll.ch \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox