Skip to content

Commit 063933f

Browse files
kyletsoadlgregkh
authored andcommitted
usb: typec: tcpm: Properly handle Alert and Status Messages
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]>
1 parent 4d2aa17 commit 063933f

File tree

2 files changed

+27
-29
lines changed

2 files changed

+27
-29
lines changed

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,20 +2188,25 @@ static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
21882188

21892189
if (!type) {
21902190
tcpm_log(port, "Alert message received with no type");
2191+
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
21912192
return;
21922193
}
21932194

21942195
/* Just handling non-battery alerts for now */
21952196
if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
2196-
switch (port->state) {
2197-
case SRC_READY:
2198-
case SNK_READY:
2197+
if (port->pwr_role == TYPEC_SOURCE) {
2198+
port->upcoming_state = GET_STATUS_SEND;
2199+
tcpm_ams_start(port, GETTING_SOURCE_SINK_STATUS);
2200+
} else {
2201+
/*
2202+
* Do not check SinkTxOk here in case the Source doesn't set its Rp to
2203+
* SinkTxOk in time.
2204+
*/
2205+
port->ams = GETTING_SOURCE_SINK_STATUS;
21992206
tcpm_set_state(port, GET_STATUS_SEND, 0);
2200-
break;
2201-
default:
2202-
tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
2203-
break;
22042207
}
2208+
} else {
2209+
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
22052210
}
22062211
}
22072212

@@ -2445,7 +2450,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
24452450
tcpm_pd_handle_state(port, BIST_RX, BIST, 0);
24462451
break;
24472452
case PD_DATA_ALERT:
2448-
tcpm_handle_alert(port, msg->payload, cnt);
2453+
if (port->state != SRC_READY && port->state != SNK_READY)
2454+
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
2455+
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
2456+
NONE_AMS, 0);
2457+
else
2458+
tcpm_handle_alert(port, msg->payload, cnt);
24492459
break;
24502460
case PD_DATA_BATT_STATUS:
24512461
case PD_DATA_GET_COUNTRY_INFO:
@@ -2769,24 +2779,16 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
27692779

27702780
switch (type) {
27712781
case PD_EXT_STATUS:
2772-
/*
2773-
* If PPS related events raised then get PPS status to clear
2774-
* (see USB PD 3.0 Spec, 6.5.2.4)
2775-
*/
2776-
if (msg->ext_msg.data[USB_PD_EXT_SDB_EVENT_FLAGS] &
2777-
USB_PD_EXT_SDB_PPS_EVENTS)
2778-
tcpm_pd_handle_state(port, GET_PPS_STATUS_SEND,
2779-
GETTING_SOURCE_SINK_STATUS, 0);
2780-
2781-
else
2782-
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
2783-
break;
27842782
case PD_EXT_PPS_STATUS:
2785-
/*
2786-
* For now the PPS status message is used to clear events
2787-
* and nothing more.
2788-
*/
2789-
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
2783+
if (port->ams == GETTING_SOURCE_SINK_STATUS) {
2784+
tcpm_ams_finish(port);
2785+
tcpm_set_state(port, ready_state(port), 0);
2786+
} else {
2787+
/* unexpected Status or PPS_Status Message */
2788+
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
2789+
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
2790+
NONE_AMS, 0);
2791+
}
27902792
break;
27912793
case PD_EXT_SOURCE_CAP_EXT:
27922794
case PD_EXT_GET_BATT_CAP:

include/linux/usb/pd_ext_sdb.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,4 @@ enum usb_pd_ext_sdb_fields {
2424
#define USB_PD_EXT_SDB_EVENT_OVP BIT(3)
2525
#define USB_PD_EXT_SDB_EVENT_CF_CV_MODE BIT(4)
2626

27-
#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \
28-
USB_PD_EXT_SDB_EVENT_OTP | \
29-
USB_PD_EXT_SDB_EVENT_OVP)
30-
3127
#endif /* __LINUX_USB_PD_EXT_SDB_H */

0 commit comments

Comments
 (0)