@@ -3700,8 +3700,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
3700
3700
ret = 0 ;
3701
3701
mgr -> payload_id_table_cleared = false;
3702
3702
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;
3705
3704
}
3706
3705
3707
3706
out_unlock :
@@ -3859,6 +3858,11 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
3859
3858
}
3860
3859
EXPORT_SYMBOL (drm_dp_mst_topology_mgr_resume );
3861
3860
3861
+ static void reset_msg_rx_state (struct drm_dp_sideband_msg_rx * msg )
3862
+ {
3863
+ memset (msg , 0 , sizeof (* msg ));
3864
+ }
3865
+
3862
3866
static bool
3863
3867
drm_dp_get_one_sb_msg (struct drm_dp_mst_topology_mgr * mgr , bool up ,
3864
3868
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,
3937
3941
return true;
3938
3942
}
3939
3943
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
+
3940
3972
static int drm_dp_mst_handle_down_rep (struct drm_dp_mst_topology_mgr * mgr )
3941
3973
{
3942
3974
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)
3952
3984
3953
3985
/* find the message */
3954
3986
mutex_lock (& mgr -> qlock );
3987
+
3955
3988
txmsg = list_first_entry_or_null (& mgr -> tx_msg_downq ,
3956
3989
struct drm_dp_sideband_msg_tx , next );
3957
- mutex_unlock (& mgr -> qlock );
3958
3990
3959
3991
/* Were we actually expecting a response, and from this mstb? */
3960
3992
if (!txmsg || txmsg -> dst != mstb ) {
@@ -3963,6 +3995,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
3963
3995
hdr = & msg -> initial_hdr ;
3964
3996
drm_dbg_kms (mgr -> dev , "Got MST reply with no msg %p %d %d %02x %02x\n" ,
3965
3997
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
+
3966
4007
goto out_clear_reply ;
3967
4008
}
3968
4009
@@ -3978,20 +4019,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
3978
4019
txmsg -> reply .u .nak .nak_data );
3979
4020
}
3980
4021
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 );
3985
4022
txmsg -> state = DRM_DP_SIDEBAND_TX_RX ;
3986
4023
list_del (& txmsg -> next );
4024
+
3987
4025
mutex_unlock (& mgr -> qlock );
3988
4026
3989
4027
wake_up_all (& mgr -> tx_waitq );
3990
4028
3991
- return 0 ;
3992
-
3993
4029
out_clear_reply :
3994
- memset (msg , 0 , sizeof ( struct drm_dp_sideband_msg_rx ) );
4030
+ reset_msg_rx_state (msg );
3995
4031
out :
3996
4032
if (mstb )
3997
4033
drm_dp_mst_topology_put_mstb (mstb );
@@ -4073,16 +4109,20 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
4073
4109
static int drm_dp_mst_handle_up_req (struct drm_dp_mst_topology_mgr * mgr )
4074
4110
{
4075
4111
struct drm_dp_pending_up_req * up_req ;
4112
+ struct drm_dp_mst_branch * mst_primary ;
4113
+ int ret = 0 ;
4076
4114
4077
4115
if (!drm_dp_get_one_sb_msg (mgr , true, NULL ))
4078
- goto out ;
4116
+ goto out_clear_reply ;
4079
4117
4080
4118
if (!mgr -> up_req_recv .have_eomt )
4081
4119
return 0 ;
4082
4120
4083
4121
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
+ }
4086
4126
4087
4127
INIT_LIST_HEAD (& up_req -> next );
4088
4128
@@ -4093,10 +4133,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
4093
4133
drm_dbg_kms (mgr -> dev , "Received unknown up req type, ignoring: %x\n" ,
4094
4134
up_req -> msg .req_type );
4095
4135
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 ;
4097
4145
}
4146
+ mutex_unlock (& mgr -> lock );
4098
4147
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 ,
4100
4149
false);
4101
4150
4102
4151
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)
4113
4162
conn_stat -> peer_device_type );
4114
4163
4115
4164
mutex_lock (& mgr -> probe_lock );
4116
- handle_csn = mgr -> mst_primary -> link_address_sent ;
4165
+ handle_csn = mst_primary -> link_address_sent ;
4117
4166
mutex_unlock (& mgr -> probe_lock );
4118
4167
4119
4168
if (!handle_csn ) {
4120
4169
drm_dbg_kms (mgr -> dev , "Got CSN before finish topology probing. Skip it." );
4121
4170
kfree (up_req );
4122
- goto out ;
4171
+ goto out_put_primary ;
4123
4172
}
4124
4173
} else if (up_req -> msg .req_type == DP_RESOURCE_STATUS_NOTIFY ) {
4125
4174
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)
4136
4185
mutex_unlock (& mgr -> up_req_lock );
4137
4186
queue_work (system_long_wq , & mgr -> up_req_work );
4138
4187
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 );
4142
4204
}
4143
4205
4144
4206
/**
@@ -4175,6 +4237,8 @@ int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u
4175
4237
* handled = true;
4176
4238
}
4177
4239
4240
+ update_msg_rx_state (mgr );
4241
+
4178
4242
if (esi [1 ] & DP_DOWN_REP_MSG_RDY ) {
4179
4243
ret = drm_dp_mst_handle_down_rep (mgr );
4180
4244
* handled = true;
0 commit comments