summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2017-08-10 21:15:40 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-08-18 15:57:15 -0700
commit3113bf1a5da35fef410f551f947f16a74d71f0a9 (patch)
treee50f176ba5f0fa49833d5387da2d49dacf35c555
parent3c41dbde20881959998832b5b9900dfdd6fcb770 (diff)
staging: typec: tcpm: Report role swap complete after entering READY state
Role swap requests fail unless the current role is either SRC_READY or SNK_READY. This works fine for VCONN and data role swaps, where we immediately enter READY state after reporting a successful role swap to user space. However, on power role changes, the role swap is currently reported as successful while power negotiation is still in process. User space does not know this, and may request another role swap immediately after a power role swap is reported to be complete. This second role swap will fail with -EAGAIN. To fix the problem, report role swap completion after power negotiation is complete and the state machine enters SRC_READY or SNK_READY state. This is better anyway since it captures errors due to failed power negotiations. It also simplifies the code since the number of calls needed to report successful role swaps is reduced. Reported-by: Howard Yen <howard_yen@htc.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/typec/tcpm.c9
1 files changed, 2 insertions, 7 deletions
diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index bad620fe323a..c52b33623304 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2261,8 +2261,8 @@ static void run_state_machine(struct tcpm_port *port)
#endif
port->try_src_count = 0;
+ tcpm_swap_complete(port, 0);
tcpm_typec_connect(port);
-
tcpm_check_send_discover(port);
/*
* 6.3.5
@@ -2444,8 +2444,8 @@ static void run_state_machine(struct tcpm_port *port)
typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD);
port->pwr_opmode = TYPEC_PWR_MODE_PD;
+ tcpm_swap_complete(port, 0);
tcpm_typec_connect(port);
-
tcpm_check_send_discover(port);
break;
@@ -2573,7 +2573,6 @@ static void run_state_machine(struct tcpm_port *port)
TYPEC_HOST);
port->send_discover = true;
}
- tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0);
break;
@@ -2621,7 +2620,6 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case PR_SWAP_SRC_SNK_SINK_ON:
- tcpm_swap_complete(port, 0);
tcpm_set_state(port, SNK_STARTUP, 0);
break;
case PR_SWAP_SNK_SRC_SINK_OFF:
@@ -2641,7 +2639,6 @@ static void run_state_machine(struct tcpm_port *port)
*/
tcpm_set_pwr_role(port, TYPEC_SOURCE);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
- tcpm_swap_complete(port, 0);
tcpm_set_state(port, SRC_STARTUP, 0);
break;
@@ -2671,12 +2668,10 @@ static void run_state_machine(struct tcpm_port *port)
case VCONN_SWAP_TURN_ON_VCONN:
tcpm_set_vconn(port, true);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
- tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0);
break;
case VCONN_SWAP_TURN_OFF_VCONN:
tcpm_set_vconn(port, false);
- tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0);
break;