@@ -733,10 +733,10 @@ static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_sideband_msg_tx *txmsg)
{
bool ret;
- mutex_lock(&mgr->qlock);
+ spin_lock(&mgr->state_lock);
ret = (txmsg->state == DRM_DP_SIDEBAND_TX_RX ||
txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT);
- mutex_unlock(&mgr->qlock);
+ spin_unlock(&mgr->state_lock);
return ret;
}
@@ -750,6 +750,7 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
check_txmsg_state(mgr, txmsg),
(4 * HZ));
mutex_lock(&mstb->mgr->qlock);
+ spin_lock(&mgr->state_lock);
if (ret > 0) {
if (txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT) {
ret = -EIO;
@@ -773,6 +774,7 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
}
}
out:
+ spin_unlock(&mgr->state_lock);
mutex_unlock(&mgr->qlock);
return ret;
@@ -1318,10 +1320,12 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr));
+ spin_lock(&mgr->state_lock);
if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) {
txmsg->seqno = -1;
txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND;
}
+ spin_unlock(&mgr->state_lock);
/* make hdr from dst mst - for replies use seqno
otherwise assign one */
@@ -1357,7 +1361,9 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
txmsg->cur_offset += tosend;
if (txmsg->cur_offset == txmsg->cur_len) {
+ spin_lock(&mgr->state_lock);
txmsg->state = DRM_DP_SIDEBAND_TX_SENT;
+ spin_unlock(&mgr->state_lock);
return 1;
}
return 0;
@@ -1386,7 +1392,9 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
list_del(&txmsg->next);
if (txmsg->seqno != -1)
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
+ spin_lock(&mgr->state_lock);
txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ spin_unlock(&mgr->state_lock);
wake_up(&mgr->tx_waitq);
}
if (list_empty(&mgr->tx_msg_downq)) {
@@ -2083,7 +2091,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
drm_dp_put_mst_branch_device(mstb);
mutex_lock(&mgr->qlock);
+ spin_lock(&mgr->state_lock);
txmsg->state = DRM_DP_SIDEBAND_TX_RX;
+ spin_unlock(&mgr->state_lock);
mstb->tx_slots[slot] = NULL;
mutex_unlock(&mgr->qlock);
@@ -2633,6 +2643,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
mutex_init(&mgr->lock);
mutex_init(&mgr->qlock);
mutex_init(&mgr->payload_lock);
+ spin_lock_init(&mgr->state_lock);
INIT_LIST_HEAD(&mgr->tx_msg_upq);
INIT_LIST_HEAD(&mgr->tx_msg_downq);
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
@@ -445,8 +445,10 @@ struct drm_dp_mst_topology_mgr {
/* messages to be transmitted */
/* qlock protects the upq/downq and in_progress,
- the mstb tx_slots and txmsg->state once they are queued */
+ the mstb tx_slots once they are queued */
struct mutex qlock;
+ /* state lock protects txmsg->state */
+ spinlock_t state_lock;
struct list_head tx_msg_downq;
struct list_head tx_msg_upq;
bool tx_down_in_progress;