Received: by 2002:a25:b323:0:0:0:0:0 with SMTP id l35csp1742287ybj; Fri, 20 Sep 2019 15:57:54 -0700 (PDT) X-Google-Smtp-Source: APXvYqzbvqHiuaxXdsYwa04dlBFqB90VADxy2Ee0QXMskNbMUsJ0JYF7u0M99oV8fHr6dSwEKOqj X-Received: by 2002:a05:6402:32f:: with SMTP id q15mr22235909edw.143.1569020274337; Fri, 20 Sep 2019 15:57:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1569020274; cv=none; d=google.com; s=arc-20160816; b=hjF/vHBj6N7PdUoNw1KV3eJ44ki6fdVG5xK2a3kYBIFPgf2E6lQh5q4bemOYJfiMyq S7rZP5YgBCCyluy2p9YpS9M4SXv4qr2piYMtjeGfzJ2Aoby3ScoXaBWdw3WXwkBmCOPY Ly4h9wgVZpYQ8e9rLKv4/FQje50EXMtfSkO+1HROPWlmrTM9TjHhchMBzG9hqKZ1gYCs u1eT6vAijgyzgHcT7CX8qIbbFit0M20Zp0rm0L9LP2bp8f6KATW24bPWlj4Xz+eBY9rE RF0DPHgYLZBrJMn6OgI56nGTZLNhbOvkVobkmY6fd8R1HUqGc8azE0BQje0AVgYPbmIP 0pbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=tx8vtK5bTkWKGgQeG8002cHxlevjtY1VIp0qcrlwyDA=; b=Oz4sFg6fuzLikhiiKWLCt7k8yhcG2B+QDSUHxb5b0kefPMSBxG8DiXgTY9EuVeAgl8 0JPWuLfu5Rdrbt56EyAUH+7kQoWi29X8QUcx/FEsBVI9p1l37kj7HnN5GoPOD7c64hge IGuwfiQU8BYMiif9Ya4Ib1JZogNDjvqG0VxecYXEbx5fWAcd60Uc/O6M2xkETBJ33cFm QnrhH9j9UD8CfmPsz7GqmVcKAKhLtfu3YW3BfZ6Uv6BHvc4thRKqgB9U8suRscoOTV1T Er+v/9pepQfhTKIg5x+0QcLUhpCf3X5TPjTWgt0mh74eV5mFyvW9IrilYxFmBTwpFJX1 DedA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=FpJEPenr; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y23si2286601edb.208.2019.09.20.15.57.31; Fri, 20 Sep 2019 15:57:54 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=FpJEPenr; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406729AbfITDZe (ORCPT + 99 others); Thu, 19 Sep 2019 23:25:34 -0400 Received: from mail-vk1-f202.google.com ([209.85.221.202]:52550 "EHLO mail-vk1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390917AbfITDZd (ORCPT ); Thu, 19 Sep 2019 23:25:33 -0400 Received: by mail-vk1-f202.google.com with SMTP id 70so2154522vki.19 for ; Thu, 19 Sep 2019 20:25:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=tx8vtK5bTkWKGgQeG8002cHxlevjtY1VIp0qcrlwyDA=; b=FpJEPenrCiJFddqH8B7LWDR78NmhNNZJo9ikjFfQgKyH2Y8FkJXhUI+r11OYB/fg7X iS/5u+5RiH1roCVMI89Y9ywy2JwU+I0CyxBN1afaQMsqlKp0RWwSmEljq1Rw4Uf3mHvn e0EFcAMO1CEJOkjNciq22hHO3OGidPIQqzUNeS04btYpVWYe/nNtClHvkcy7MzzyDlI6 wbxiBpfacp2GKl9jNc70jkZHAARzc/za3FtjTUPpKzfF/aNcNHCv8lYrZNqIalRqc95U p19Aj7xgSOUPUdBWFlTrrFlb2TGJQbFEnQaAKbTc9tD7gpctNNszr+2bjasDIZY8ZC3W iLhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=tx8vtK5bTkWKGgQeG8002cHxlevjtY1VIp0qcrlwyDA=; b=A/Tr8hmL1GaNBm1g53HIXnWGoR7BaWUIHFaSBQ9xs5HyGUnSePDfiI9+u1p7o2dCeh M0BivSBash1mKgSbtZflrkBLRGZjQuv3noZvQi02xZH3x/cd/vDR0g5BYN2K9az7o8sx bRN7jSJtNfRyriH47MQSj/6Dv4p1BunXUnreMl1cLaweXnab5jwRXDnCN4omLSSORT5m VKKL+ILHIl0W4ZGKiQUXDZBDpxSkaiAozNZeZEsPNH3XdtQU12HgLJp8vd3I83btsm7U vF1a2mutZXdmkI8nTmDYQlhnlcHT9H8dH6jOgrUPzg7/6CDqnrbvCaxq/nDvvJ852ZVD bldw== X-Gm-Message-State: APjAAAVEAZc0KIMBiuv6d2gAmcN1G5zbKXUwEHwSUn6O4lQGyqlseBig yeJilhpLJ6lCkOivrHo1W6ZqkDpl59eV X-Received: by 2002:a1f:a6cd:: with SMTP id p196mr6870673vke.25.1568949931402; Thu, 19 Sep 2019 20:25:31 -0700 (PDT) Date: Fri, 20 Sep 2019 11:24:37 +0800 In-Reply-To: <20190920032437.242187-1-kyletso@google.com> Message-Id: <20190920032437.242187-3-kyletso@google.com> Mime-Version: 1.0 References: <20190920032437.242187-1-kyletso@google.com> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog Subject: [PATCH v3 2/2] usb: typec: tcpm: AMS for PD2.0 From: Kyle Tso To: linux@roeck-us.net, heikki.krogerus@linux.intel.com, gregkh@linuxfoundation.org Cc: badhri@google.com, hdegoede@redhat.com, Adam.Thomson.Opensource@diasemi.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Kyle Tso Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org AMS is defined in PD2.0 as well. Remove the filter in tcpm_ams_start and change the CC for Collision Avoidance only if the negotiated revision is higher than PD2.0. Signed-off-by: Kyle Tso --- Changelog since v2: - N/A; This is the first version. drivers/usb/typec/tcpm/tcpm.c | 129 +++++++++++++++------------------- 1 file changed, 57 insertions(+), 72 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 7d1c30c33097..aca1c5bbe870 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -391,6 +391,12 @@ struct pd_rx_event { struct pd_message msg; }; +static const char * const pd_rev[] = { + [PD_REV10] = "rev1", + [PD_REV20] = "rev2", + [PD_REV30] = "rev3", +}; + #define tcpm_cc_is_sink(cc) \ ((cc) == TYPEC_CC_RP_DEF || (cc) == TYPEC_CC_RP_1_5 || \ (cc) == TYPEC_CC_RP_3_0) @@ -431,8 +437,6 @@ struct pd_rx_event { (tcpm_port_is_sink(port) && \ ((port)->cc1 == TYPEC_CC_RP_3_0 || (port)->cc2 == TYPEC_CC_RP_3_0)) -#define support_ams(port) ((port)->negotiated_rev >= PD_REV30) - static enum tcpm_state tcpm_default_state(struct tcpm_port *port) { if (port->port_type == TYPEC_PORT_DRP) { @@ -679,14 +683,9 @@ static int tcpm_ams_finish(struct tcpm_port *port) { int ret = 0; - if (!support_ams(port)) { - port->upcoming_state = INVALID_STATE; - return -EOPNOTSUPP; - } - tcpm_log(port, "AMS %s finished", tcpm_ams_str[port->ams]); - if (port->pwr_role == TYPEC_SOURCE) + if (port->negotiated_rev >= PD_REV30 && port->pwr_role == TYPEC_SOURCE) tcpm_set_cc(port, SINK_TX_OK); port->in_ams = false; @@ -723,12 +722,13 @@ static int tcpm_pd_transmit(struct tcpm_port *port, case TCPC_TX_SUCCESS: port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK; /* + * USB PD rev 2.0, 8.3.2.2.1: * USB PD rev 3.0, 8.3.2.1.3: * "... Note that every AMS is Interruptible until the first * Message in the sequence has been successfully sent (GoodCRC * Message received)." */ - if (support_ams(port) && port->ams != NONE_AMS) + if (port->ams != NONE_AMS) port->in_ams = true; break; case TCPC_TX_DISCARDED: @@ -994,20 +994,18 @@ static void tcpm_set_state(struct tcpm_port *port, enum tcpm_state state, unsigned int delay_ms) { if (delay_ms) { - tcpm_log(port, "pending state change %s -> %s @ %u ms%s%s", + tcpm_log(port, "pending state change %s -> %s @ %u ms [%s %s]", tcpm_states[port->state], tcpm_states[state], delay_ms, - support_ams(port) ? " in AMS " : "", - support_ams(port) ? tcpm_ams_str[port->ams] : ""); + pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]); port->delayed_state = state; mod_delayed_work(port->wq, &port->state_machine, msecs_to_jiffies(delay_ms)); port->delayed_runtime = jiffies + msecs_to_jiffies(delay_ms); port->delay_ms = delay_ms; } else { - tcpm_log(port, "state change %s -> %s%s%s", + tcpm_log(port, "state change %s -> %s [%s %s]", tcpm_states[port->state], tcpm_states[state], - support_ams(port) ? " in AMS " : "", - support_ams(port) ? tcpm_ams_str[port->ams] : ""); + pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]); port->delayed_state = INVALID_STATE; port->prev_state = port->state; port->state = state; @@ -1029,12 +1027,11 @@ static void tcpm_set_state_cond(struct tcpm_port *port, enum tcpm_state state, tcpm_set_state(port, state, delay_ms); else tcpm_log(port, - "skipped %sstate change %s -> %s [%u ms], context state %s%s%s", + "skipped %sstate change %s -> %s [%u ms], context state %s [%s %s]", delay_ms ? "delayed " : "", tcpm_states[port->state], tcpm_states[state], delay_ms, tcpm_states[port->enter_state], - support_ams(port) ? " in AMS " : "", - support_ams(port) ? tcpm_ams_str[port->ams] : ""); + pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]); } static void tcpm_queue_message(struct tcpm_port *port, @@ -1100,11 +1097,6 @@ static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams) { int ret = 0; - if (!support_ams(port)) { - port->upcoming_state = INVALID_STATE; - return -EOPNOTSUPP; - } - tcpm_log(port, "AMS %s start", tcpm_ams_str[ams]); if (!tcpm_ams_interruptible(port) && ams != HARD_RESET) { @@ -1132,24 +1124,41 @@ static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams) } } else if (tcpm_vdm_ams(port)) { /* tSinkTx is enforced in vdm_run_state_machine */ - tcpm_set_cc(port, SINK_TX_NG); + if (port->negotiated_rev >= PD_REV30) + tcpm_set_cc(port, SINK_TX_NG); return ret; } - cc_req = port->cc_req; - tcpm_set_cc(port, SINK_TX_NG); - if (port->state == SRC_READY || - port->state == SRC_STARTUP || - port->state == SRC_SOFT_RESET_WAIT_SNK_TX || - port->state == SOFT_RESET || - port->state == SOFT_RESET_SEND) - tcpm_set_state(port, AMS_START, cc_req == SINK_TX_OK ? - PD_T_SINK_TX : 0); - else - tcpm_set_state(port, SRC_READY, cc_req == SINK_TX_OK ? - PD_T_SINK_TX : 0); + if (port->negotiated_rev >= PD_REV30) { + cc_req = port->cc_req; + tcpm_set_cc(port, SINK_TX_NG); + } + + switch (port->state) { + case SRC_READY: + case SRC_STARTUP: + case SRC_SOFT_RESET_WAIT_SNK_TX: + case SOFT_RESET: + case SOFT_RESET_SEND: + if (port->negotiated_rev >= PD_REV30) + tcpm_set_state(port, AMS_START, + cc_req == SINK_TX_OK ? + PD_T_SINK_TX : 0); + else + tcpm_set_state(port, AMS_START, 0); + break; + default: + if (port->negotiated_rev >= PD_REV30) + tcpm_set_state(port, SRC_READY, + cc_req == SINK_TX_OK ? + PD_T_SINK_TX : 0); + else + tcpm_set_state(port, SRC_READY, 0); + break; + } } else { - if (!tcpm_sink_tx_ok(port) && + if (port->negotiated_rev >= PD_REV30 && + !tcpm_sink_tx_ok(port) && ams != SOFT_RESET_AMS && ams != HARD_RESET) { port->upcoming_state = INVALID_STATE; @@ -1565,13 +1574,13 @@ static void vdm_run_state_machine(struct tcpm_port *port) break; } - if (res == -EAGAIN) + if (res < 0) return; } port->vdm_state = VDM_STATE_SEND_MESSAGE; mod_delayed_work(port->wq, &port->vdm_state_machine, - (res != -EOPNOTSUPP) && + (port->negotiated_rev >= PD_REV30) && (port->pwr_role == TYPEC_SOURCE) && (PD_VDO_CMDT(port->vdo_data[0]) == CMDT_INIT) ? PD_T_SINK_TX : 0); @@ -1975,7 +1984,6 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, { enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); enum tcpm_state next_state; - int ret = 0; switch (type) { case PD_CTRL_GOOD_CRC: @@ -2094,11 +2102,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, tcpm_ams_finish(port); if (port->pwr_role == TYPEC_SOURCE) { port->upcoming_state = SRC_SEND_CAPABILITIES; - ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EOPNOTSUPP) - tcpm_set_state(port, - SRC_SEND_CAPABILITIES, - 0); + tcpm_ams_start(port, POWER_NEGOTIATION); } else { tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); } @@ -3254,9 +3258,7 @@ static void run_state_machine(struct tcpm_port *port) port->ams == FAST_ROLE_SWAP) tcpm_ams_finish(port); port->upcoming_state = SRC_SEND_CAPABILITIES; - ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EOPNOTSUPP) - tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); + tcpm_ams_start(port, POWER_NEGOTIATION); break; case SRC_SEND_CAPABILITIES: port->caps_count++; @@ -3620,11 +3622,7 @@ static void run_state_machine(struct tcpm_port *port) * thus set upcoming_state to INVALID_STATE. */ port->upcoming_state = INVALID_STATE; - ret = tcpm_ams_start(port, HARD_RESET); - if (ret == -EOPNOTSUPP) { - tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL); - tcpm_set_state(port, HARD_RESET_START, 0); - } + tcpm_ams_start(port, HARD_RESET); break; case HARD_RESET_START: port->hard_reset_count++; @@ -3709,9 +3707,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_pd_send_control(port, PD_CTRL_ACCEPT); if (port->pwr_role == TYPEC_SOURCE) { port->upcoming_state = SRC_SEND_CAPABILITIES; - ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EOPNOTSUPP) - tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); + tcpm_ams_start(port, POWER_NEGOTIATION); } else { tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); } @@ -3721,9 +3717,7 @@ static void run_state_machine(struct tcpm_port *port) if (port->ams != NONE_AMS) tcpm_ams_finish(port); port->upcoming_state = SOFT_RESET_SEND; - ret = tcpm_ams_start(port, SOFT_RESET_AMS); - if (ret == -EOPNOTSUPP) - tcpm_set_state(port, SOFT_RESET_SEND, 0); + tcpm_ams_start(port, SOFT_RESET_AMS); break; case SOFT_RESET_SEND: port->message_id = 0; @@ -3930,7 +3924,7 @@ static void run_state_machine(struct tcpm_port *port) port->vbus_present ? PD_T_PS_SOURCE_OFF : 0); break; - /* Collision Avoidance state */ + /* AMS intermediate state */ case AMS_START: if (port->upcoming_state == INVALID_STATE) { tcpm_set_state(port, port->pwr_role == TYPEC_SOURCE ? @@ -4392,9 +4386,6 @@ static int tcpm_dr_set(const struct typec_capability *cap, if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; - } else if (ret == -EOPNOTSUPP) { - port->upcoming_state = INVALID_STATE; - tcpm_set_state(port, DR_SWAP_SEND, 0); } } @@ -4447,9 +4438,6 @@ static int tcpm_pr_set(const struct typec_capability *cap, if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; - } else if (ret == -EOPNOTSUPP) { - port->upcoming_state = INVALID_STATE; - tcpm_set_state(port, PR_SWAP_SEND, 0); } port->swap_status = 0; @@ -4496,9 +4484,6 @@ static int tcpm_vconn_set(const struct typec_capability *cap, if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; - } else if (ret == -EOPNOTSUPP) { - port->upcoming_state = INVALID_STATE; - tcpm_set_state(port, VCONN_SWAP_SEND, 0); } port->swap_status = 0; @@ -4570,7 +4555,7 @@ static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) port->upcoming_state = SNK_NEGOTIATE_PPS_CAPABILITIES; ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EAGAIN || ret == -EOPNOTSUPP) { + if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; } @@ -4632,7 +4617,7 @@ static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) port->upcoming_state = SNK_NEGOTIATE_PPS_CAPABILITIES; ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EAGAIN || ret == -EOPNOTSUPP) { + if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; } @@ -4688,7 +4673,7 @@ static int tcpm_pps_activate(struct tcpm_port *port, bool activate) else port->upcoming_state = SNK_NEGOTIATE_CAPABILITIES; ret = tcpm_ams_start(port, POWER_NEGOTIATION); - if (ret == -EAGAIN || ret == -EOPNOTSUPP) { + if (ret == -EAGAIN) { port->upcoming_state = INVALID_STATE; goto port_unlock; } -- 2.23.0.351.gc4317032e6-goog