@@ -259,6 +259,7 @@ enum frs_typec_current {
259259#define ALTMODE_DISCOVERY_MAX (SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX)
260260
261261#define GET_SINK_CAP_RETRY_MS 100
262+ #define SEND_DISCOVER_RETRY_MS 100
262263
263264struct pd_mode_data {
264265 int svid_index ; /* current SVID index */
@@ -366,6 +367,8 @@ struct tcpm_port {
366367 struct kthread_work vdm_state_machine ;
367368 struct hrtimer enable_frs_timer ;
368369 struct kthread_work enable_frs ;
370+ struct hrtimer send_discover_timer ;
371+ struct kthread_work send_discover_work ;
369372 bool state_machine_running ;
370373 bool vdm_sm_running ;
371374
@@ -1178,6 +1181,16 @@ static void mod_enable_frs_delayed_work(struct tcpm_port *port, unsigned int del
11781181 }
11791182}
11801183
1184+ static void mod_send_discover_delayed_work (struct tcpm_port * port , unsigned int delay_ms )
1185+ {
1186+ if (delay_ms ) {
1187+ hrtimer_start (& port -> send_discover_timer , ms_to_ktime (delay_ms ), HRTIMER_MODE_REL );
1188+ } else {
1189+ hrtimer_cancel (& port -> send_discover_timer );
1190+ kthread_queue_work (port -> wq , & port -> send_discover_work );
1191+ }
1192+ }
1193+
11811194static void tcpm_set_state (struct tcpm_port * port , enum tcpm_state state ,
11821195 unsigned int delay_ms )
11831196{
@@ -1855,6 +1868,9 @@ static void vdm_run_state_machine(struct tcpm_port *port)
18551868 res = tcpm_ams_start (port , DISCOVER_IDENTITY );
18561869 if (res == 0 )
18571870 port -> send_discover = false;
1871+ else if (res == - EAGAIN )
1872+ mod_send_discover_delayed_work (port ,
1873+ SEND_DISCOVER_RETRY_MS );
18581874 break ;
18591875 case CMD_DISCOVER_SVID :
18601876 res = tcpm_ams_start (port , DISCOVER_SVIDS );
@@ -1880,6 +1896,7 @@ static void vdm_run_state_machine(struct tcpm_port *port)
18801896 }
18811897
18821898 if (res < 0 ) {
1899+ port -> vdm_state = VDM_STATE_ERR_BUSY ;
18831900 port -> vdm_sm_running = false;
18841901 return ;
18851902 }
@@ -3682,14 +3699,6 @@ static inline enum tcpm_state unattached_state(struct tcpm_port *port)
36823699 return SNK_UNATTACHED ;
36833700}
36843701
3685- static void tcpm_check_send_discover (struct tcpm_port * port )
3686- {
3687- if ((port -> data_role == TYPEC_HOST || port -> negotiated_rev > PD_REV20 ) &&
3688- port -> send_discover && port -> pd_capable )
3689- tcpm_send_vdm (port , USB_SID_PD , CMD_DISCOVER_IDENT , NULL , 0 );
3690- port -> send_discover = false;
3691- }
3692-
36933702static void tcpm_swap_complete (struct tcpm_port * port , int result )
36943703{
36953704 if (port -> swap_pending ) {
@@ -3926,7 +3935,18 @@ static void run_state_machine(struct tcpm_port *port)
39263935 break ;
39273936 }
39283937
3929- tcpm_check_send_discover (port );
3938+ /*
3939+ * 6.4.4.3.1 Discover Identity
3940+ * "The Discover Identity Command Shall only be sent to SOP when there is an
3941+ * Explicit Contract."
3942+ * For now, this driver only supports SOP for DISCOVER_IDENTITY, thus using
3943+ * port->explicit_contract to decide whether to send the command.
3944+ */
3945+ if (port -> explicit_contract )
3946+ mod_send_discover_delayed_work (port , 0 );
3947+ else
3948+ port -> send_discover = false;
3949+
39303950 /*
39313951 * 6.3.5
39323952 * Sending ping messages is not necessary if
@@ -4194,7 +4214,18 @@ static void run_state_machine(struct tcpm_port *port)
41944214 break ;
41954215 }
41964216
4197- tcpm_check_send_discover (port );
4217+ /*
4218+ * 6.4.4.3.1 Discover Identity
4219+ * "The Discover Identity Command Shall only be sent to SOP when there is an
4220+ * Explicit Contract."
4221+ * For now, this driver only supports SOP for DISCOVER_IDENTITY, thus using
4222+ * port->explicit_contract.
4223+ */
4224+ if (port -> explicit_contract )
4225+ mod_send_discover_delayed_work (port , 0 );
4226+ else
4227+ port -> send_discover = false;
4228+
41984229 power_supply_changed (port -> psy );
41994230 break ;
42004231
@@ -5288,6 +5319,29 @@ static void tcpm_enable_frs_work(struct kthread_work *work)
52885319 mutex_unlock (& port -> lock );
52895320}
52905321
5322+ static void tcpm_send_discover_work (struct kthread_work * work )
5323+ {
5324+ struct tcpm_port * port = container_of (work , struct tcpm_port , send_discover_work );
5325+
5326+ mutex_lock (& port -> lock );
5327+ /* No need to send DISCOVER_IDENTITY anymore */
5328+ if (!port -> send_discover )
5329+ goto unlock ;
5330+
5331+ /* Retry if the port is not idle */
5332+ if ((port -> state != SRC_READY && port -> state != SNK_READY ) || port -> vdm_sm_running ) {
5333+ mod_send_discover_delayed_work (port , SEND_DISCOVER_RETRY_MS );
5334+ goto unlock ;
5335+ }
5336+
5337+ /* Only send the Message if the port is host for PD rev2.0 */
5338+ if (port -> data_role == TYPEC_HOST || port -> negotiated_rev > PD_REV20 )
5339+ tcpm_send_vdm (port , USB_SID_PD , CMD_DISCOVER_IDENT , NULL , 0 );
5340+
5341+ unlock :
5342+ mutex_unlock (& port -> lock );
5343+ }
5344+
52915345static int tcpm_dr_set (struct typec_port * p , enum typec_data_role data )
52925346{
52935347 struct tcpm_port * port = typec_get_drvdata (p );
@@ -6093,6 +6147,14 @@ static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer)
60936147 return HRTIMER_NORESTART ;
60946148}
60956149
6150+ static enum hrtimer_restart send_discover_timer_handler (struct hrtimer * timer )
6151+ {
6152+ struct tcpm_port * port = container_of (timer , struct tcpm_port , send_discover_timer );
6153+
6154+ kthread_queue_work (port -> wq , & port -> send_discover_work );
6155+ return HRTIMER_NORESTART ;
6156+ }
6157+
60966158struct tcpm_port * tcpm_register_port (struct device * dev , struct tcpc_dev * tcpc )
60976159{
60986160 struct tcpm_port * port ;
@@ -6123,12 +6185,15 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
61236185 kthread_init_work (& port -> vdm_state_machine , vdm_state_machine_work );
61246186 kthread_init_work (& port -> event_work , tcpm_pd_event_handler );
61256187 kthread_init_work (& port -> enable_frs , tcpm_enable_frs_work );
6188+ kthread_init_work (& port -> send_discover_work , tcpm_send_discover_work );
61266189 hrtimer_init (& port -> state_machine_timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
61276190 port -> state_machine_timer .function = state_machine_timer_handler ;
61286191 hrtimer_init (& port -> vdm_state_machine_timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
61296192 port -> vdm_state_machine_timer .function = vdm_state_machine_timer_handler ;
61306193 hrtimer_init (& port -> enable_frs_timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
61316194 port -> enable_frs_timer .function = enable_frs_timer_handler ;
6195+ hrtimer_init (& port -> send_discover_timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
6196+ port -> send_discover_timer .function = send_discover_timer_handler ;
61326197
61336198 spin_lock_init (& port -> pd_event_lock );
61346199
0 commit comments