Skip to content

Commit 5a64967

Browse files
Wayne LinLyude
authored andcommitted
drm/dp_mst: Have DP_Tx send one msg at a time
[Why] Noticed this while testing MST with the 4 ports MST hub from StarTech.com. Sometimes can't light up monitors normally and get the error message as 'sideband msg build failed'. Look into aux transactions, found out that source sometimes will send out another down request before receiving the down reply of the previous down request. On the other hand, in drm_dp_get_one_sb_msg(), current code doesn't handle the interleaved replies case. Hence, source can't build up message completely and can't light up monitors. [How] For good compatibility, enforce source to send out one down request at a time. Add a flag, is_waiting_for_dwn_reply, to determine if the source can send out a down request immediately or not. - Check the flag before calling process_single_down_tx_qlock to send out a msg - Set the flag when successfully send out a down request - Clear the flag when successfully build up a down reply - Clear the flag when find erros during sending out a down request - Clear the flag when find errors during building up a down reply - Clear the flag when timeout occurs during waiting for a down reply - Use drm_dp_mst_kick_tx() to try to send another down request in queue at the end of drm_dp_mst_wait_tx_reply() (attempt to send out messages in queue when errors occur) Cc: Lyude Paul <[email protected]> Signed-off-by: Wayne Lin <[email protected]> Signed-off-by: Lyude Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 7617e96 commit 5a64967

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

drivers/gpu/drm/drm_dp_mst_topology.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,8 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
11901190
txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
11911191
mstb->tx_slots[txmsg->seqno] = NULL;
11921192
}
1193+
mgr->is_waiting_for_dwn_reply = false;
1194+
11931195
}
11941196
out:
11951197
if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) {
@@ -1199,6 +1201,7 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
11991201
}
12001202
mutex_unlock(&mgr->qlock);
12011203

1204+
drm_dp_mst_kick_tx(mgr);
12021205
return ret;
12031206
}
12041207

@@ -2741,9 +2744,11 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
27412744
ret = process_single_tx_qlock(mgr, txmsg, false);
27422745
if (ret == 1) {
27432746
/* txmsg is sent it should be in the slots now */
2747+
mgr->is_waiting_for_dwn_reply = true;
27442748
list_del(&txmsg->next);
27452749
} else if (ret) {
27462750
DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
2751+
mgr->is_waiting_for_dwn_reply = false;
27472752
list_del(&txmsg->next);
27482753
if (txmsg->seqno != -1)
27492754
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
@@ -2783,7 +2788,8 @@ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
27832788
drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
27842789
}
27852790

2786-
if (list_is_singular(&mgr->tx_msg_downq))
2791+
if (list_is_singular(&mgr->tx_msg_downq) &&
2792+
!mgr->is_waiting_for_dwn_reply)
27872793
process_single_down_tx_qlock(mgr);
27882794
mutex_unlock(&mgr->qlock);
27892795
}
@@ -3701,6 +3707,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
37013707
mutex_lock(&mgr->qlock);
37023708
txmsg->state = DRM_DP_SIDEBAND_TX_RX;
37033709
mstb->tx_slots[slot] = NULL;
3710+
mgr->is_waiting_for_dwn_reply = false;
37043711
mutex_unlock(&mgr->qlock);
37053712

37063713
wake_up_all(&mgr->tx_waitq);
@@ -3710,6 +3717,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
37103717
no_msg:
37113718
drm_dp_mst_topology_put_mstb(mstb);
37123719
clear_down_rep_recv:
3720+
mutex_lock(&mgr->qlock);
3721+
mgr->is_waiting_for_dwn_reply = false;
3722+
mutex_unlock(&mgr->qlock);
37133723
memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
37143724

37153725
return 0;
@@ -4520,7 +4530,7 @@ static void drm_dp_tx_work(struct work_struct *work)
45204530
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
45214531

45224532
mutex_lock(&mgr->qlock);
4523-
if (!list_empty(&mgr->tx_msg_downq))
4533+
if (!list_empty(&mgr->tx_msg_downq) && !mgr->is_waiting_for_dwn_reply)
45244534
process_single_down_tx_qlock(mgr);
45254535
mutex_unlock(&mgr->qlock);
45264536
}

include/drm/drm_dp_mst_helper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ struct drm_dp_mst_topology_mgr {
605605
* &drm_dp_sideband_msg_tx.state once they are queued
606606
*/
607607
struct mutex qlock;
608+
609+
/**
610+
* @is_waiting_for_dwn_reply: indicate whether is waiting for down reply
611+
*/
612+
bool is_waiting_for_dwn_reply;
613+
608614
/**
609615
* @tx_msg_downq: List of pending down replies.
610616
*/

0 commit comments

Comments
 (0)