From patchwork Fri Mar 15 14:42:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10854889 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8C1FF1708 for ; Fri, 15 Mar 2019 14:42:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73FB22AA7F for ; Fri, 15 Mar 2019 14:42:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 684EF2AA83; Fri, 15 Mar 2019 14:42:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D46982AA7F for ; Fri, 15 Mar 2019 14:42:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729212AbfCOOm2 (ORCPT ); Fri, 15 Mar 2019 10:42:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44074 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728914AbfCOOm2 (ORCPT ); Fri, 15 Mar 2019 10:42:28 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CEC163134329; Fri, 15 Mar 2019 14:42:27 +0000 (UTC) Received: from dhcp-44-202.space.revspace.nl (ovpn-112-52.ams2.redhat.com [10.36.112.52]) by smtp.corp.redhat.com (Postfix) with ESMTP id C51761001DC0; Fri, 15 Mar 2019 14:42:24 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH] usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps Date: Fri, 15 Mar 2019 15:42:19 +0100 Message-Id: <20190315144219.5914-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Fri, 15 Mar 2019 14:42:27 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP PD 2.0 sinks are supposed to accept src-capabilities with a 3.0 header and simply ignore any src PDOs which the sink does not understand such as PPS but some 2.0 sinks instead ignore the entire PD_DATA_SOURCE_CAP message, causing contract negotiation to fail. This commit fixes such sinks not working by re-trying the contract negotiation with PD-2.0 source-caps messages if we don't have a contract after PD_N_HARD_RESET_COUNT hard-reset attempts. The problem fixed by this commit was noticed with a Type-C to VGA dongle. Signed-off-by: Hans de Goede --- The Type-C to VGA dongle on which this encountered looks like this one: https://www.aliexpress.com/item/Male-USB-3-1-Type-C-USB-C-to-Female-VGA-Adapter-Cable-10Gbps-for-New/32898274476.html --- drivers/usb/typec/tcpm/tcpm.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index f1c39a3c7534..3f8df845d1a5 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -37,6 +37,7 @@ S(SRC_ATTACHED), \ S(SRC_STARTUP), \ S(SRC_SEND_CAPABILITIES), \ + S(SRC_SEND_CAP_LOWER_PD_REVISION), \ S(SRC_NEGOTIATE_CAPABILITIES), \ S(SRC_TRANSITION_SUPPLY), \ S(SRC_READY), \ @@ -2792,6 +2793,29 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) return SNK_UNATTACHED; } +/* + * PD 2.0 sinks are supposed to accept src-capabilities with a 3.0 header and + * simply ignore any src PDOs which the sink does not understand such as PPS + * but some 2.0 sinks instead ignore the entire PD_DATA_SOURCE_CAP message, + * causing contract negotiation to fail. + * + * This function is used by the SRC_SEND_CAPABILITIES state in + * run_state_machine() to work around this. + * + * After PD_N_HARD_RESET_COUNT hard-reset attempts this function selects + * SRC_SEND_CAP_LOWER_PD_REVISION as state to set after the next timeout, + * this state will fallback to a lower PD revision and then try sending the + * src-capabilities again. + */ +static inline enum tcpm_state src_send_cap_timeout_state(struct tcpm_port *port) +{ + if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) + return HARD_RESET_SEND; + if (port->negotiated_rev > PD_REV20) + return SRC_SEND_CAP_LOWER_PD_REVISION; + return hard_reset_state(port); +} + static inline enum tcpm_state unattached_state(struct tcpm_port *port) { if (port->port_type == TYPEC_PORT_DRP) { @@ -2966,10 +2990,18 @@ static void run_state_machine(struct tcpm_port *port) /* port->hard_reset_count = 0; */ port->caps_count = 0; port->pd_capable = true; - tcpm_set_state_cond(port, hard_reset_state(port), + tcpm_set_state_cond(port, + src_send_cap_timeout_state(port), PD_T_SEND_SOURCE_CAP); } break; + case SRC_SEND_CAP_LOWER_PD_REVISION: + if (WARN_ON(port->negotiated_rev <= PD_REV20)) + break; + port->negotiated_rev--; + port->hard_reset_count = 0; + tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); + break; case SRC_NEGOTIATE_CAPABILITIES: ret = tcpm_pd_check_request(port); if (ret < 0) {