Skip to content

Commit 3769e4c

Browse files
Wayne LinLyude
authored andcommitted
drm/dp_mst: Avoid to mess up payload table by ports in stale topology
[Why] After unplug/hotplug hub from the system, userspace might start to clear stale payloads gradually. If we call drm_dp_mst_deallocate_vcpi() to release stale VCPI of those ports which are not relating to current topology, we have chane to wrongly clear active payload table entry for current topology. E.g. We have allocated VCPI 1 in current payload table and we call drm_dp_mst_deallocate_vcpi() to clean VCPI 1 in stale topology. In drm_dp_mst_deallocate_vcpi(), it will call drm_dp_mst_put_payload_id() tp put VCPI 1 and which means ID 1 is available again. Thereafter, if we want to allocate a new payload stream, it will find ID 1 is available by drm_dp_mst_assign_payload_id(). However, ID 1 is being used [How] Check target sink is relating to current topology or not before doing any payload table update. Searching upward to find the target sink's relevant root branch device. If the found root branch device is not the same root of current topology, don't update payload table. Changes since v1: * Change debug macro to use drm_dbg_kms() instead * Amend the commit message to add Cc tag. Signed-off-by: Wayne Lin <[email protected]> Cc: [email protected] Signed-off-by: Lyude Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Lyude Paul <[email protected]>
1 parent 35d3e8c commit 3769e4c

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

drivers/gpu/drm/drm_dp_mst_topology.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port);
9494
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port);
9595
static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
9696

97+
static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port,
98+
struct drm_dp_mst_branch *branch);
99+
97100
#define DBG_PREFIX "[dp_mst]"
98101

99102
#define DP_STR(x) [DP_ ## x] = #x
@@ -3366,6 +3369,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
33663369
struct drm_dp_mst_port *port;
33673370
int i, j;
33683371
int cur_slots = 1;
3372+
bool skip;
33693373

33703374
mutex_lock(&mgr->payload_lock);
33713375
for (i = 0; i < mgr->max_payloads; i++) {
@@ -3380,6 +3384,14 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
33803384
port = container_of(vcpi, struct drm_dp_mst_port,
33813385
vcpi);
33823386

3387+
mutex_lock(&mgr->lock);
3388+
skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
3389+
mutex_unlock(&mgr->lock);
3390+
3391+
if (skip) {
3392+
drm_dbg_kms("Virtual channel %d is not in current topology\n", i);
3393+
continue;
3394+
}
33833395
/* Validated ports don't matter if we're releasing
33843396
* VCPI
33853397
*/
@@ -3479,6 +3491,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
34793491
struct drm_dp_mst_port *port;
34803492
int i;
34813493
int ret = 0;
3494+
bool skip;
34823495

34833496
mutex_lock(&mgr->payload_lock);
34843497
for (i = 0; i < mgr->max_payloads; i++) {
@@ -3488,6 +3501,13 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
34883501

34893502
port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
34903503

3504+
mutex_lock(&mgr->lock);
3505+
skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
3506+
mutex_unlock(&mgr->lock);
3507+
3508+
if (skip)
3509+
continue;
3510+
34913511
drm_dbg_kms(mgr->dev, "payload %d %d\n", i, mgr->payloads[i].payload_state);
34923512
if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
34933513
ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
@@ -4574,9 +4594,18 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
45744594
void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
45754595
struct drm_dp_mst_port *port)
45764596
{
4597+
bool skip;
4598+
45774599
if (!port->vcpi.vcpi)
45784600
return;
45794601

4602+
mutex_lock(&mgr->lock);
4603+
skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
4604+
mutex_unlock(&mgr->lock);
4605+
4606+
if (skip)
4607+
return;
4608+
45804609
drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
45814610
port->vcpi.num_slots = 0;
45824611
port->vcpi.pbn = 0;

0 commit comments

Comments
 (0)