Commit 3113bf1a authored by Guenter Roeck's avatar Guenter Roeck Committed by Greg Kroah-Hartman

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: default avatarHoward Yen <howard_yen@htc.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3c41dbde
...@@ -2261,8 +2261,8 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2261,8 +2261,8 @@ static void run_state_machine(struct tcpm_port *port)
#endif #endif
port->try_src_count = 0; port->try_src_count = 0;
tcpm_swap_complete(port, 0);
tcpm_typec_connect(port); tcpm_typec_connect(port);
tcpm_check_send_discover(port); tcpm_check_send_discover(port);
/* /*
* 6.3.5 * 6.3.5
...@@ -2444,8 +2444,8 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2444,8 +2444,8 @@ static void run_state_machine(struct tcpm_port *port)
typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD); typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD);
port->pwr_opmode = TYPEC_PWR_MODE_PD; port->pwr_opmode = TYPEC_PWR_MODE_PD;
tcpm_swap_complete(port, 0);
tcpm_typec_connect(port); tcpm_typec_connect(port);
tcpm_check_send_discover(port); tcpm_check_send_discover(port);
break; break;
...@@ -2573,7 +2573,6 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2573,7 +2573,6 @@ static void run_state_machine(struct tcpm_port *port)
TYPEC_HOST); TYPEC_HOST);
port->send_discover = true; port->send_discover = true;
} }
tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0); tcpm_set_state(port, ready_state(port), 0);
break; break;
...@@ -2621,7 +2620,6 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -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); tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
break; break;
case PR_SWAP_SRC_SNK_SINK_ON: case PR_SWAP_SRC_SNK_SINK_ON:
tcpm_swap_complete(port, 0);
tcpm_set_state(port, SNK_STARTUP, 0); tcpm_set_state(port, SNK_STARTUP, 0);
break; break;
case PR_SWAP_SNK_SRC_SINK_OFF: case PR_SWAP_SNK_SRC_SINK_OFF:
...@@ -2641,7 +2639,6 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2641,7 +2639,6 @@ static void run_state_machine(struct tcpm_port *port)
*/ */
tcpm_set_pwr_role(port, TYPEC_SOURCE); tcpm_set_pwr_role(port, TYPEC_SOURCE);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY); tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
tcpm_swap_complete(port, 0);
tcpm_set_state(port, SRC_STARTUP, 0); tcpm_set_state(port, SRC_STARTUP, 0);
break; break;
...@@ -2671,12 +2668,10 @@ static void run_state_machine(struct tcpm_port *port) ...@@ -2671,12 +2668,10 @@ static void run_state_machine(struct tcpm_port *port)
case VCONN_SWAP_TURN_ON_VCONN: case VCONN_SWAP_TURN_ON_VCONN:
tcpm_set_vconn(port, true); tcpm_set_vconn(port, true);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY); tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0); tcpm_set_state(port, ready_state(port), 0);
break; break;
case VCONN_SWAP_TURN_OFF_VCONN: case VCONN_SWAP_TURN_OFF_VCONN:
tcpm_set_vconn(port, false); tcpm_set_vconn(port, false);
tcpm_swap_complete(port, 0);
tcpm_set_state(port, ready_state(port), 0); tcpm_set_state(port, ready_state(port), 0);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment