Skip to content

Commit

Permalink
usb: typec: tcpm: Properly handle Alert and Status Messages
Browse files Browse the repository at this point in the history
When receiving Alert Message, if it is not unexpected but is
unsupported for some reason, the port should return Not_Supported
Message response.

Also, according to PD3.0 Spec 6.5.2.1.4 Event Flags Field, the
OTP/OVP/OCP flags in the Event Flags field in Status Message no longer
require Get_PPS_Status Message to clear them. Thus remove it when
receiving Status Message with those flags being set.

In addition, add the missing AMS operations for Status Message.

Fixes: 64f7c49 ("typec: tcpm: Add support for sink PPS related messages")
Fixes: 0908c5a ("usb: typec: tcpm: AMS and Collision Avoidance")
Signed-off-by: Kyle Tso <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Cc: stable <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
kyletsoadl authored and gregkh committed Jun 4, 2021
1 parent 4d2aa17 commit 063933f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
52 changes: 27 additions & 25 deletions drivers/usb/typec/tcpm/tcpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2188,20 +2188,25 @@ static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,

if (!type) {
tcpm_log(port, "Alert message received with no type");
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
return;
}

/* Just handling non-battery alerts for now */
if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
switch (port->state) {
case SRC_READY:
case SNK_READY:
if (port->pwr_role == TYPEC_SOURCE) {
port->upcoming_state = GET_STATUS_SEND;
tcpm_ams_start(port, GETTING_SOURCE_SINK_STATUS);
} else {
/*
* Do not check SinkTxOk here in case the Source doesn't set its Rp to
* SinkTxOk in time.
*/
port->ams = GETTING_SOURCE_SINK_STATUS;
tcpm_set_state(port, GET_STATUS_SEND, 0);
break;
default:
tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
break;
}
} else {
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
}
}

Expand Down Expand Up @@ -2445,7 +2450,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
tcpm_pd_handle_state(port, BIST_RX, BIST, 0);
break;
case PD_DATA_ALERT:
tcpm_handle_alert(port, msg->payload, cnt);
if (port->state != SRC_READY && port->state != SNK_READY)
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
NONE_AMS, 0);
else
tcpm_handle_alert(port, msg->payload, cnt);
break;
case PD_DATA_BATT_STATUS:
case PD_DATA_GET_COUNTRY_INFO:
Expand Down Expand Up @@ -2769,24 +2779,16 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,

switch (type) {
case PD_EXT_STATUS:
/*
* If PPS related events raised then get PPS status to clear
* (see USB PD 3.0 Spec, 6.5.2.4)
*/
if (msg->ext_msg.data[USB_PD_EXT_SDB_EVENT_FLAGS] &
USB_PD_EXT_SDB_PPS_EVENTS)
tcpm_pd_handle_state(port, GET_PPS_STATUS_SEND,
GETTING_SOURCE_SINK_STATUS, 0);

else
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
break;
case PD_EXT_PPS_STATUS:
/*
* For now the PPS status message is used to clear events
* and nothing more.
*/
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
if (port->ams == GETTING_SOURCE_SINK_STATUS) {
tcpm_ams_finish(port);
tcpm_set_state(port, ready_state(port), 0);
} else {
/* unexpected Status or PPS_Status Message */
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
NONE_AMS, 0);
}
break;
case PD_EXT_SOURCE_CAP_EXT:
case PD_EXT_GET_BATT_CAP:
Expand Down
4 changes: 0 additions & 4 deletions include/linux/usb/pd_ext_sdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,4 @@ enum usb_pd_ext_sdb_fields {
#define USB_PD_EXT_SDB_EVENT_OVP BIT(3)
#define USB_PD_EXT_SDB_EVENT_CF_CV_MODE BIT(4)

#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \
USB_PD_EXT_SDB_EVENT_OTP | \
USB_PD_EXT_SDB_EVENT_OVP)

#endif /* __LINUX_USB_PD_EXT_SDB_H */

0 comments on commit 063933f

Please sign in to comment.