@@ -159,6 +159,14 @@ enum pd_msg_request {
159
159
PD_MSG_DATA_SOURCE_CAP ,
160
160
};
161
161
162
+ enum adev_actions {
163
+ ADEV_NONE = 0 ,
164
+ ADEV_NOTIFY_USB_AND_QUEUE_VDM ,
165
+ ADEV_QUEUE_VDM ,
166
+ ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL ,
167
+ ADEV_ATTENTION ,
168
+ };
169
+
162
170
/* Events from low level driver */
163
171
164
172
#define TCPM_CC_EVENT BIT(0)
@@ -1080,10 +1088,10 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
1080
1088
1081
1089
#define supports_modal (port ) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header)
1082
1090
1083
- static int tcpm_pd_svdm (struct tcpm_port * port , const u32 * p , int cnt ,
1084
- u32 * response )
1091
+ static int tcpm_pd_svdm (struct tcpm_port * port , struct typec_altmode * adev ,
1092
+ const u32 * p , int cnt , u32 * response ,
1093
+ enum adev_actions * adev_action )
1085
1094
{
1086
- struct typec_altmode * adev ;
1087
1095
struct typec_altmode * pdev ;
1088
1096
struct pd_mode_data * modep ;
1089
1097
int rlen = 0 ;
@@ -1099,9 +1107,6 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
1099
1107
1100
1108
modep = & port -> mode_data ;
1101
1109
1102
- adev = typec_match_altmode (port -> port_altmode , ALTMODE_DISCOVERY_MAX ,
1103
- PD_VDO_VID (p [0 ]), PD_VDO_OPOS (p [0 ]));
1104
-
1105
1110
pdev = typec_match_altmode (port -> partner_altmode , ALTMODE_DISCOVERY_MAX ,
1106
1111
PD_VDO_VID (p [0 ]), PD_VDO_OPOS (p [0 ]));
1107
1112
@@ -1127,8 +1132,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
1127
1132
break ;
1128
1133
case CMD_ATTENTION :
1129
1134
/* Attention command does not have response */
1130
- if (adev )
1131
- typec_altmode_attention (adev , p [1 ]);
1135
+ * adev_action = ADEV_ATTENTION ;
1132
1136
return 0 ;
1133
1137
default :
1134
1138
break ;
@@ -1182,23 +1186,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
1182
1186
case CMD_ENTER_MODE :
1183
1187
if (adev && pdev ) {
1184
1188
typec_altmode_update_active (pdev , true);
1185
-
1186
- if (typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt )) {
1187
- response [0 ] = VDO (adev -> svid , 1 ,
1188
- CMD_EXIT_MODE );
1189
- response [0 ] |= VDO_OPOS (adev -> mode );
1190
- return 1 ;
1191
- }
1189
+ * adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL ;
1192
1190
}
1193
1191
return 0 ;
1194
1192
case CMD_EXIT_MODE :
1195
1193
if (adev && pdev ) {
1196
1194
typec_altmode_update_active (pdev , false);
1197
-
1198
1195
/* Back to USB Operation */
1199
- WARN_ON (typec_altmode_notify (adev ,
1200
- TYPEC_STATE_USB ,
1201
- NULL ));
1196
+ * adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM ;
1197
+ return 0 ;
1202
1198
}
1203
1199
break ;
1204
1200
default :
@@ -1209,11 +1205,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
1209
1205
switch (cmd ) {
1210
1206
case CMD_ENTER_MODE :
1211
1207
/* Back to USB Operation */
1212
- if (adev )
1213
- WARN_ON (typec_altmode_notify (adev ,
1214
- TYPEC_STATE_USB ,
1215
- NULL ));
1216
- break ;
1208
+ * adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM ;
1209
+ return 0 ;
1217
1210
default :
1218
1211
break ;
1219
1212
}
@@ -1223,22 +1216,25 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
1223
1216
}
1224
1217
1225
1218
/* Informing the alternate mode drivers about everything */
1226
- if (adev )
1227
- typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
1228
-
1219
+ * adev_action = ADEV_QUEUE_VDM ;
1229
1220
return rlen ;
1230
1221
}
1231
1222
1232
1223
static void tcpm_handle_vdm_request (struct tcpm_port * port ,
1233
1224
const __le32 * payload , int cnt )
1234
1225
{
1226
+ enum adev_actions adev_action = ADEV_NONE ;
1227
+ struct typec_altmode * adev ;
1235
1228
u32 p [PD_MAX_PAYLOAD ];
1236
1229
u32 response [8 ] = { };
1237
1230
int i , rlen = 0 ;
1238
1231
1239
1232
for (i = 0 ; i < cnt ; i ++ )
1240
1233
p [i ] = le32_to_cpu (payload [i ]);
1241
1234
1235
+ adev = typec_match_altmode (port -> port_altmode , ALTMODE_DISCOVERY_MAX ,
1236
+ PD_VDO_VID (p [0 ]), PD_VDO_OPOS (p [0 ]));
1237
+
1242
1238
if (port -> vdm_state == VDM_STATE_BUSY ) {
1243
1239
/* If UFP responded busy retry after timeout */
1244
1240
if (PD_VDO_CMDT (p [0 ]) == CMDT_RSP_BUSY ) {
@@ -1253,7 +1249,31 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
1253
1249
}
1254
1250
1255
1251
if (PD_VDO_SVDM (p [0 ]))
1256
- rlen = tcpm_pd_svdm (port , p , cnt , response );
1252
+ rlen = tcpm_pd_svdm (port , adev , p , cnt , response , & adev_action );
1253
+
1254
+ if (adev ) {
1255
+ switch (adev_action ) {
1256
+ case ADEV_NONE :
1257
+ break ;
1258
+ case ADEV_NOTIFY_USB_AND_QUEUE_VDM :
1259
+ WARN_ON (typec_altmode_notify (adev , TYPEC_STATE_USB , NULL ));
1260
+ typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
1261
+ break ;
1262
+ case ADEV_QUEUE_VDM :
1263
+ typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
1264
+ break ;
1265
+ case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL :
1266
+ if (typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt )) {
1267
+ response [0 ] = VDO (adev -> svid , 1 , CMD_EXIT_MODE );
1268
+ response [0 ] |= VDO_OPOS (adev -> mode );
1269
+ rlen = 1 ;
1270
+ }
1271
+ break ;
1272
+ case ADEV_ATTENTION :
1273
+ typec_altmode_attention (adev , p [1 ]);
1274
+ break ;
1275
+ }
1276
+ }
1257
1277
1258
1278
if (rlen > 0 )
1259
1279
tcpm_queue_vdm (port , response [0 ], & response [1 ], rlen - 1 );
0 commit comments