@@ -3700,8 +3700,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
37003700 ret = 0 ;
37013701 mgr -> payload_id_table_cleared = false;
37023702
3703- memset (& mgr -> down_rep_recv , 0 , sizeof (mgr -> down_rep_recv ));
3704- memset (& mgr -> up_req_recv , 0 , sizeof (mgr -> up_req_recv ));
3703+ mgr -> reset_rx_state = true;
37053704 }
37063705
37073706out_unlock :
@@ -3859,6 +3858,11 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
38593858}
38603859EXPORT_SYMBOL (drm_dp_mst_topology_mgr_resume );
38613860
3861+ static void reset_msg_rx_state (struct drm_dp_sideband_msg_rx * msg )
3862+ {
3863+ memset (msg , 0 , sizeof (* msg ));
3864+ }
3865+
38623866static bool
38633867drm_dp_get_one_sb_msg (struct drm_dp_mst_topology_mgr * mgr , bool up ,
38643868 struct drm_dp_mst_branch * * mstb )
@@ -3937,6 +3941,34 @@ drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
39373941 return true;
39383942}
39393943
3944+ static int get_msg_request_type (u8 data )
3945+ {
3946+ return data & 0x7f ;
3947+ }
3948+
3949+ static bool verify_rx_request_type (struct drm_dp_mst_topology_mgr * mgr ,
3950+ const struct drm_dp_sideband_msg_tx * txmsg ,
3951+ const struct drm_dp_sideband_msg_rx * rxmsg )
3952+ {
3953+ const struct drm_dp_sideband_msg_hdr * hdr = & rxmsg -> initial_hdr ;
3954+ const struct drm_dp_mst_branch * mstb = txmsg -> dst ;
3955+ int tx_req_type = get_msg_request_type (txmsg -> msg [0 ]);
3956+ int rx_req_type = get_msg_request_type (rxmsg -> msg [0 ]);
3957+ char rad_str [64 ];
3958+
3959+ if (tx_req_type == rx_req_type )
3960+ return true;
3961+
3962+ drm_dp_mst_rad_to_str (mstb -> rad , mstb -> lct , rad_str , sizeof (rad_str ));
3963+ drm_dbg_kms (mgr -> dev ,
3964+ "Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n" ,
3965+ mstb , hdr -> seqno , mstb -> lct , rad_str ,
3966+ drm_dp_mst_req_type_str (rx_req_type ), rx_req_type ,
3967+ drm_dp_mst_req_type_str (tx_req_type ), tx_req_type );
3968+
3969+ return false;
3970+ }
3971+
39403972static int drm_dp_mst_handle_down_rep (struct drm_dp_mst_topology_mgr * mgr )
39413973{
39423974 struct drm_dp_sideband_msg_tx * txmsg ;
@@ -3952,9 +3984,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
39523984
39533985 /* find the message */
39543986 mutex_lock (& mgr -> qlock );
3987+
39553988 txmsg = list_first_entry_or_null (& mgr -> tx_msg_downq ,
39563989 struct drm_dp_sideband_msg_tx , next );
3957- mutex_unlock (& mgr -> qlock );
39583990
39593991 /* Were we actually expecting a response, and from this mstb? */
39603992 if (!txmsg || txmsg -> dst != mstb ) {
@@ -3963,6 +3995,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
39633995 hdr = & msg -> initial_hdr ;
39643996 drm_dbg_kms (mgr -> dev , "Got MST reply with no msg %p %d %d %02x %02x\n" ,
39653997 mstb , hdr -> seqno , hdr -> lct , hdr -> rad [0 ], msg -> msg [0 ]);
3998+
3999+ mutex_unlock (& mgr -> qlock );
4000+
4001+ goto out_clear_reply ;
4002+ }
4003+
4004+ if (!verify_rx_request_type (mgr , txmsg , msg )) {
4005+ mutex_unlock (& mgr -> qlock );
4006+
39664007 goto out_clear_reply ;
39674008 }
39684009
@@ -3978,20 +4019,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
39784019 txmsg -> reply .u .nak .nak_data );
39794020 }
39804021
3981- memset (msg , 0 , sizeof (struct drm_dp_sideband_msg_rx ));
3982- drm_dp_mst_topology_put_mstb (mstb );
3983-
3984- mutex_lock (& mgr -> qlock );
39854022 txmsg -> state = DRM_DP_SIDEBAND_TX_RX ;
39864023 list_del (& txmsg -> next );
4024+
39874025 mutex_unlock (& mgr -> qlock );
39884026
39894027 wake_up_all (& mgr -> tx_waitq );
39904028
3991- return 0 ;
3992-
39934029out_clear_reply :
3994- memset (msg , 0 , sizeof ( struct drm_dp_sideband_msg_rx ) );
4030+ reset_msg_rx_state (msg );
39954031out :
39964032 if (mstb )
39974033 drm_dp_mst_topology_put_mstb (mstb );
@@ -4073,16 +4109,20 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
40734109static int drm_dp_mst_handle_up_req (struct drm_dp_mst_topology_mgr * mgr )
40744110{
40754111 struct drm_dp_pending_up_req * up_req ;
4112+ struct drm_dp_mst_branch * mst_primary ;
4113+ int ret = 0 ;
40764114
40774115 if (!drm_dp_get_one_sb_msg (mgr , true, NULL ))
4078- goto out ;
4116+ goto out_clear_reply ;
40794117
40804118 if (!mgr -> up_req_recv .have_eomt )
40814119 return 0 ;
40824120
40834121 up_req = kzalloc (sizeof (* up_req ), GFP_KERNEL );
4084- if (!up_req )
4085- return - ENOMEM ;
4122+ if (!up_req ) {
4123+ ret = - ENOMEM ;
4124+ goto out_clear_reply ;
4125+ }
40864126
40874127 INIT_LIST_HEAD (& up_req -> next );
40884128
@@ -4093,10 +4133,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
40934133 drm_dbg_kms (mgr -> dev , "Received unknown up req type, ignoring: %x\n" ,
40944134 up_req -> msg .req_type );
40954135 kfree (up_req );
4096- goto out ;
4136+ goto out_clear_reply ;
4137+ }
4138+
4139+ mutex_lock (& mgr -> lock );
4140+ mst_primary = mgr -> mst_primary ;
4141+ if (!mst_primary || !drm_dp_mst_topology_try_get_mstb (mst_primary )) {
4142+ mutex_unlock (& mgr -> lock );
4143+ kfree (up_req );
4144+ goto out_clear_reply ;
40974145 }
4146+ mutex_unlock (& mgr -> lock );
40984147
4099- drm_dp_send_up_ack_reply (mgr , mgr -> mst_primary , up_req -> msg .req_type ,
4148+ drm_dp_send_up_ack_reply (mgr , mst_primary , up_req -> msg .req_type ,
41004149 false);
41014150
41024151 if (up_req -> msg .req_type == DP_CONNECTION_STATUS_NOTIFY ) {
@@ -4113,13 +4162,13 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
41134162 conn_stat -> peer_device_type );
41144163
41154164 mutex_lock (& mgr -> probe_lock );
4116- handle_csn = mgr -> mst_primary -> link_address_sent ;
4165+ handle_csn = mst_primary -> link_address_sent ;
41174166 mutex_unlock (& mgr -> probe_lock );
41184167
41194168 if (!handle_csn ) {
41204169 drm_dbg_kms (mgr -> dev , "Got CSN before finish topology probing. Skip it." );
41214170 kfree (up_req );
4122- goto out ;
4171+ goto out_put_primary ;
41234172 }
41244173 } else if (up_req -> msg .req_type == DP_RESOURCE_STATUS_NOTIFY ) {
41254174 const struct drm_dp_resource_status_notify * res_stat =
@@ -4136,9 +4185,22 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
41364185 mutex_unlock (& mgr -> up_req_lock );
41374186 queue_work (system_long_wq , & mgr -> up_req_work );
41384187
4139- out :
4140- memset (& mgr -> up_req_recv , 0 , sizeof (struct drm_dp_sideband_msg_rx ));
4141- return 0 ;
4188+ out_put_primary :
4189+ drm_dp_mst_topology_put_mstb (mst_primary );
4190+ out_clear_reply :
4191+ reset_msg_rx_state (& mgr -> up_req_recv );
4192+ return ret ;
4193+ }
4194+
4195+ static void update_msg_rx_state (struct drm_dp_mst_topology_mgr * mgr )
4196+ {
4197+ mutex_lock (& mgr -> lock );
4198+ if (mgr -> reset_rx_state ) {
4199+ mgr -> reset_rx_state = false;
4200+ reset_msg_rx_state (& mgr -> down_rep_recv );
4201+ reset_msg_rx_state (& mgr -> up_req_recv );
4202+ }
4203+ mutex_unlock (& mgr -> lock );
41424204}
41434205
41444206/**
@@ -4175,6 +4237,8 @@ int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u
41754237 * handled = true;
41764238 }
41774239
4240+ update_msg_rx_state (mgr );
4241+
41784242 if (esi [1 ] & DP_DOWN_REP_MSG_RDY ) {
41794243 ret = drm_dp_mst_handle_down_rep (mgr );
41804244 * handled = true;
0 commit comments