mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 09:31:51 +00:00
pd: vdm: Add VDM related timeouts and busy response handling.
Initial VDM implementation had a very conservative 500msec timeout period. This CL adds the timeouts defined in the USB-PD specification for various commands. Additionally it adds a state to the vdm state machine to allow proper busy response handling. Signed-off-by: Todd Broch <tbroch@chromium.org> BRANCH=samus BUG=chrome-os-partner:30645 TEST=manual, Alternate mode and flashing still work. Creating a VDM responder which returns busy shows retries from initiator after at least 100msec. Change-Id: I79f5da557ca9faf63d2299bb77009f6d98a782bd Reviewed-on: https://chromium-review.googlesource.com/235682 Reviewed-by: Alec Berg <alecaberg@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> Commit-Queue: Todd Broch <tbroch@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
faf09e2905
commit
c0f64b13e9
@@ -526,7 +526,6 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
case CMD_DISCOVER_SVID:
|
||||
case CMD_DISCOVER_MODES:
|
||||
/* resend if its discovery */
|
||||
payload[0] |= VDO_CMDT(CMDT_INIT);
|
||||
rsize = 1;
|
||||
break;
|
||||
case CMD_ENTER_MODE:
|
||||
|
||||
@@ -193,6 +193,7 @@ enum vdm_states {
|
||||
/* Anything >0 represents an active state */
|
||||
VDM_STATE_READY = 1,
|
||||
VDM_STATE_BUSY = 2,
|
||||
VDM_STATE_WAIT_RSP_BUSY = 3,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
@@ -264,9 +265,13 @@ static struct pd_protocol {
|
||||
|
||||
/* PD state for Vendor Defined Messages */
|
||||
enum vdm_states vdm_state;
|
||||
/* Timeout for the current vdm state. Set to 0 for no timeout. */
|
||||
timestamp_t vdm_timeout;
|
||||
/* next Vendor Defined Message to send */
|
||||
uint32_t vdo_data[VDO_MAX_SIZE];
|
||||
uint8_t vdo_count;
|
||||
/* VDO to retry if UFP responder replied busy. */
|
||||
uint32_t vdo_retry;
|
||||
|
||||
/* Attached ChromeOS device id, RW hash, and current RO / RW image */
|
||||
uint16_t dev_id;
|
||||
@@ -716,13 +721,24 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload)
|
||||
uint32_t *rdata;
|
||||
|
||||
if (pd[port].vdm_state == VDM_STATE_BUSY) {
|
||||
pd[port].vdm_state = VDM_STATE_DONE;
|
||||
CPRINTF("VDM/%d [%02d] %08x", cnt, PD_VDO_CMD(payload[0]),
|
||||
payload[0]);
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
for (i = 1; i < cnt; i++)
|
||||
CPRINTF(" %08x", payload[i]);
|
||||
CPRINTF("\n");
|
||||
|
||||
/* If UFP responded busy retry after timeout */
|
||||
if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) {
|
||||
pd[port].vdm_timeout.val = get_time().val +
|
||||
PD_T_VDM_BUSY;
|
||||
pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY;
|
||||
pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) |
|
||||
CMDT_INIT;
|
||||
return;
|
||||
} else {
|
||||
pd[port].vdm_state = VDM_STATE_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
@@ -1355,11 +1371,36 @@ static inline int pdo_busy(int port)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr)
|
||||
{
|
||||
uint64_t timeout;
|
||||
int cmd = PD_VDO_CMD(vdm_hdr);
|
||||
|
||||
/* its not a structured VDM command */
|
||||
if (!PD_VDO_SVDM(vdm_hdr))
|
||||
return 500*MSEC;
|
||||
|
||||
switch (PD_VDO_CMDT(vdm_hdr)) {
|
||||
case CMDT_INIT:
|
||||
if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
|
||||
timeout = PD_T_VDM_WAIT_MODE_E;
|
||||
else
|
||||
timeout = PD_T_VDM_SNDR_RSP;
|
||||
break;
|
||||
default:
|
||||
if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
|
||||
timeout = PD_T_VDM_E_MODE;
|
||||
else
|
||||
timeout = PD_T_VDM_RCVR_RSP;
|
||||
break;
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static void pd_vdm_send_state_machine(int port, int incoming_packet)
|
||||
{
|
||||
int res;
|
||||
uint16_t header;
|
||||
static uint64_t vdm_timeout;
|
||||
|
||||
switch (pd[port].vdm_state) {
|
||||
case VDM_STATE_READY:
|
||||
@@ -1389,13 +1430,24 @@ static void pd_vdm_send_state_machine(int port, int incoming_packet)
|
||||
pd[port].vdm_state = VDM_STATE_ERR_SEND;
|
||||
} else {
|
||||
pd[port].vdm_state = VDM_STATE_BUSY;
|
||||
vdm_timeout = get_time().val + 500*MSEC;
|
||||
pd[port].vdm_timeout.val = get_time().val +
|
||||
vdm_get_ready_timeout(pd[port].vdo_data[0]);
|
||||
}
|
||||
break;
|
||||
case VDM_STATE_WAIT_RSP_BUSY:
|
||||
/* wait and then initiate request again */
|
||||
if (get_time().val > pd[port].vdm_timeout.val) {
|
||||
pd[port].vdo_data[0] = pd[port].vdo_retry;
|
||||
pd[port].vdo_count = 1;
|
||||
pd[port].vdm_state = VDM_STATE_READY;
|
||||
}
|
||||
break;
|
||||
case VDM_STATE_BUSY:
|
||||
/* Wait for VDM response or timeout */
|
||||
if (get_time().val > vdm_timeout)
|
||||
if (pd[port].vdm_timeout.val &&
|
||||
(get_time().val > pd[port].vdm_timeout.val)) {
|
||||
pd[port].vdm_state = VDM_STATE_ERR_TMOUT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -139,6 +139,13 @@ enum pd_errors {
|
||||
/* from USB Type-C Specification Table 5-1 */
|
||||
#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */
|
||||
|
||||
/* VDM Timers ( USB PD Spec Rev2.0 Table 6-30 )*/
|
||||
#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */
|
||||
#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */
|
||||
#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */
|
||||
#define PD_T_VDM_SNDR_RSP (30*MSEC) /* max of 30ms */
|
||||
#define PD_T_VDM_WAIT_MODE_E (100*MSEC) /* enter/exit the same max */
|
||||
|
||||
/* function table for entered mode */
|
||||
struct amode_fx {
|
||||
int (*status)(int port, uint32_t *payload);
|
||||
|
||||
Reference in New Issue
Block a user