Received: by 10.223.164.221 with SMTP id h29csp3164719wrb; Wed, 18 Oct 2017 13:24:13 -0700 (PDT) X-Received: by 10.99.3.213 with SMTP id 204mr14630664pgd.407.1508358253513; Wed, 18 Oct 2017 13:24:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508358253; cv=none; d=google.com; s=arc-20160816; b=RIR568Ac7cwMUe5aRxDzQ9OLqYWIo9713q8lVj+bp1GFuWhJxosxuDmimTRxqt+KPC x10YgXrMgbABT+MjdOp9RlTFqsL1u4ViCTr4Zi8serAIKCuflqepUyvq9WrWfOe/RqqM sOP4aXP7j9I0rkxny/ghPnQclwmClpO/DucMuGK0Px25ouGSSqOZIzsVIxyoLL6u7p3E mE6GB3i+36YzpbCKj0C+A8UtDGwZ2ri5EeebIwbsLdAf5Ii6acRQK1Zk++53c+qCNig7 PF5aZqaMEJsMhBYfT/CXYdNM6W9xCZkOdPR8gGbbOGko3Fp4cYVQ4jRFiietPDMrJHlq aJig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=qNMWJdX7N06P3AeAPPyfJ4HAKQhBKnP8MEY1vGmrUkk=; b=RBN3go4XX7cX0B0wC0JV/BBJF33a40wKFaPIUfXy9FLhHOrNop8CtzzwFB5ECyc6Ot WFInQx/lcXTd0kLvuV6X9tRfUjqMAn0zrWBJ7jeDkkvMQuPVisG0hSR5dz7ZiwQsCNg+ 6ttZnIgPrwNbIBOAjZGg+UEikCGUb6inORnNbaA3GMnx7spL9/02de1kyJemeXezR5xl 3xKzp27vsWAD7wFqTT7o1yMzsrpxMgbhLFaE6EQAEdxulCQDXmCso63ft26wHOBvnnX+ YCO2G7+p7l+clnTdmwvNvcq3tNWKqwpLmAKYuFJO9JsgTbGJzuCfYDYoyxCtgSxCwD1z 5Buw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=BwQ/eqD7; 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 b34si6676843pld.702.2017.10.18.13.23.58; Wed, 18 Oct 2017 13:24:13 -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=BwQ/eqD7; 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 S1751619AbdJRUXV (ORCPT + 99 others); Wed, 18 Oct 2017 16:23:21 -0400 Received: from mail-it0-f65.google.com ([209.85.214.65]:55026 "EHLO mail-it0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751576AbdJRUXS (ORCPT ); Wed, 18 Oct 2017 16:23:18 -0400 Received: by mail-it0-f65.google.com with SMTP id 72so7416611itk.3 for ; Wed, 18 Oct 2017 13:23:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=qNMWJdX7N06P3AeAPPyfJ4HAKQhBKnP8MEY1vGmrUkk=; b=BwQ/eqD7jy92EIF22sLsHoxgCvbKqycn7lqNHS4Yi9mT/DfPKTuAR2sjTWAZqzI7vd j3P0ZLMbfetE5OSVooqsG3bmb7PSTFSqPAqRhA+H7xgQIyJHSn9q8/dMhHV2oYDwVcmc 6iV/q4EDWCPBGe2N0+iOX9znhrj8+U+kZ8qDHHjoHSP4WYMfChUqdtSeXZYDKu9TAzaB RFjjlcr6Eepb5FkhdB7GaliPSXrdWEbiar6oSGUwptG8eQdq07+yUgrp8qm0VriY7GD5 n/TYffFyVqv02puiMdgOXoCS5AjsSoin1HAJ/Q9yQ1RgMH4zGlt3JdDKe//OHpyZiQzF yj/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=qNMWJdX7N06P3AeAPPyfJ4HAKQhBKnP8MEY1vGmrUkk=; b=f41pNuJWIvq+3Kb0YCade1zT+TjkGJSLIPPUxsbNQJ2AGM5n8DlYpengIEpaxE8JV2 Wu+FEZiEMKQ/XAL6b9BQxpNDwBZbfV43GqifZD4kdCBWb96orENUmZ9bsroCFKRF1NUY neBCPfUPUSIz5aBiMgoPIruldXGMICGNbrpv+vMzL8bO0NcagfYiyAYNhflzdzNFyFnB XeC3sEBv4EHFysWb675NzFB/2ykNDang/8SwrTKeSXgXL5C3bYpUFawYFKoESZHQpqKG 6zXX9mpsGCZ2M2WAikqBC92bipQdkeHSs0vdfPQWNxeT/crAKU/lR/en6xzzdK+qOwmO oPUg== X-Gm-Message-State: AMCzsaUqi0aTHreKR6PM/p3+Dk+cAGs0vf/1t5WSJ1H1/nigkvUHARL1 y1gomRXRJ7g3UP8JqltXP2jSzA== X-Google-Smtp-Source: ABhQp+SFv0iaFleyOBcnED2qEM5XqlEQqV6CAlXsESBjcTUk0D4djtSRLdxcPPG8WuDP4CyMaqzKNw== X-Received: by 10.36.69.222 with SMTP id c91mr11932034itd.125.1508358197085; Wed, 18 Oct 2017 13:23:17 -0700 (PDT) Received: from badhri.mtv.corp.google.com ([172.22.122.202]) by smtp.gmail.com with ESMTPSA id k19sm4673315itb.18.2017.10.18.13.23.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Oct 2017 13:23:16 -0700 (PDT) From: Badhri Jagan Sridharan X-Google-Original-From: Badhri Jagan Sridharan To: heikki.krogerus@linux.intel.com, gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Subject: [PATCH 1/2 v3] typec: tcpm: Validate source and sink caps Date: Wed, 18 Oct 2017 13:22:47 -0700 Message-Id: <20171018202248.8278-1-Badhri@google.com> X-Mailer: git-send-email 2.15.0.rc1.287.g2b38de12cc-goog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The source and sink caps should follow the following rules. This patch validates whether the src_caps/snk_caps adheres to it. 6.4.1 Capabilities Message A Capabilities message (Source Capabilities message or Sink Capabilities message) shall have at least one Power Data Object for vSafe5V. The Capabilities message shall also contain the sending Port’s information followed by up to 6 additional Power Data Objects. Power Data Objects in a Capabilities message shall be sent in the following order: 1. The vSafe5V Fixed Supply Object shall always be the first object. 2. The remaining Fixed Supply Objects, if present, shall be sent in voltage order; lowest to highest. 3. The Battery Supply Objects, if present shall be sent in Minimum Voltage order; lowest to highest. 4. The Variable Supply (non-battery) Objects, if present, shall be sent in Minimum Voltage order; lowest to highest. Errors in source/sink_caps of the local port will prevent the port registration. Whereas, errors in source caps of partner device would only log them. Signed-off-by: Badhri Jagan Sridharan --- Changelog since v1: - rebased on top drivers/usb/typec/tcpm.c as suggested by gregkh@linuxfoundation.org - renamed nr_snk_*_pdo as suggested by dan.carpenter@oracle.com - removed stale comment as suggested by linux@roeck-us.net - removed the tests for nr_snk_*_pdo as suggested by dan.carpenter@oracle.com - Fixed sytling as suggested by dan.carpenter@oracle.com - renamed tcpm_get_nr_type_pdos to nr_type_pdos as suggested by dan.carpenter@oracle.com - fixed nr_type_pdos as suggested by dan.carpenter@oracle.com - tcpm_pd_select_pdo now checks for all matching variable/batt pdos instead of the first matching one. Changelog since v2: - refactored error messages as suggested by heikki.krogerus@linux.intel.com drivers/usb/typec/tcpm.c | 116 +++++++++++++++++++++++++++++++++++++++++++---- include/linux/usb/pd.h | 2 + include/linux/usb/tcpm.h | 4 +- 3 files changed, 111 insertions(+), 11 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 8483d3e33853..e3f8b3da46b0 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -1256,6 +1256,86 @@ static void vdm_state_machine_work(struct work_struct *work) mutex_unlock(&port->lock); } +static const char * const pdo_err[] = { + "", + " err: source/sink caps should atleast have vSafe5V", + " err: vSafe5V Fixed Supply Object Shall always be the first object", + " err: PDOs should be in the following order: Fixed; Battery; Variable", + " err: Fixed supply pdos should be in increasing order of their fixed voltage", + " err: Variable/Battery supply pdos should be in increasing order of their minimum voltage", + " err: Variable/Batt supply pdos cannot have same min/max voltage", +}; + +static int tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, + unsigned int nr_pdo) +{ + unsigned int i; + + /* Should at least contain vSafe5v */ + if (nr_pdo < 1) + return 1; + + /* The vSafe5V Fixed Supply Object Shall always be the first object */ + if (pdo_type(pdo[0]) != PDO_TYPE_FIXED || + pdo_fixed_voltage(pdo[0]) != VSAFE5V) + return 2; + + for (i = 1; i < nr_pdo; i++) { + if (pdo_type(pdo[i]) < pdo_type(pdo[i - 1])) { + return 3; + } else if (pdo_type(pdo[i]) == pdo_type(pdo[i - 1])) { + enum pd_pdo_type type = pdo_type(pdo[i]); + + switch (type) { + /* + * The remaining Fixed Supply Objects, if + * present, shall be sent in voltage order; + * lowest to highest. + */ + case PDO_TYPE_FIXED: + if (pdo_fixed_voltage(pdo[i]) <= + pdo_fixed_voltage(pdo[i - 1])) + return 4; + break; + /* + * The Battery Supply Objects and Variable + * supply, if present shall be sent in Minimum + * Voltage order; lowest to highest. + */ + case PDO_TYPE_VAR: + case PDO_TYPE_BATT: + if (pdo_min_voltage(pdo[i]) < + pdo_min_voltage(pdo[i - 1])) + return 5; + else if ((pdo_min_voltage(pdo[i]) == + pdo_min_voltage(pdo[i - 1])) && + (pdo_max_voltage(pdo[i]) == + pdo_min_voltage(pdo[i - 1]))) + return 6; + break; + default: + tcpm_log_force(port, " Unknown pdo type"); + } + } + } + + return 0; +} + +static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, + unsigned int nr_pdo) +{ + int err_index = tcpm_caps_err(port, pdo, nr_pdo); + + if (err_index) { + tcpm_log_force(port, " %s", pdo_err[err_index]); + return -EINVAL; + } + + return 0; +} + + /* * PD (data, control) command handling functions */ @@ -1278,6 +1358,9 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_log_source_caps(port); + tcpm_validate_caps(port, port->source_caps, + port->nr_source_caps); + /* * This message may be received even if VBUS is not * present. This is quite unexpected; see USB PD @@ -3444,9 +3527,12 @@ static int tcpm_copy_vdos(u32 *dest_vdo, const u32 *src_vdo, return nr_vdo; } -void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, - unsigned int nr_pdo) +int tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, + unsigned int nr_pdo) { + if (tcpm_validate_caps(port, pdo, nr_pdo)) + return -EINVAL; + mutex_lock(&port->lock); port->nr_src_pdo = tcpm_copy_pdos(port->src_pdo, pdo, nr_pdo); switch (port->state) { @@ -3466,16 +3552,20 @@ void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, break; } mutex_unlock(&port->lock); + return 0; } EXPORT_SYMBOL_GPL(tcpm_update_source_capabilities); -void tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, - unsigned int nr_pdo, - unsigned int max_snk_mv, - unsigned int max_snk_ma, - unsigned int max_snk_mw, - unsigned int operating_snk_mw) +int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, + unsigned int nr_pdo, + unsigned int max_snk_mv, + unsigned int max_snk_ma, + unsigned int max_snk_mw, + unsigned int operating_snk_mw) { + if (tcpm_validate_caps(port, pdo, nr_pdo)) + return -EINVAL; + mutex_lock(&port->lock); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, pdo, nr_pdo); port->max_snk_mv = max_snk_mv; @@ -3494,6 +3584,7 @@ void tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, break; } mutex_unlock(&port->lock); + return 0; } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); @@ -3529,7 +3620,15 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) init_completion(&port->tx_complete); init_completion(&port->swap_complete); + tcpm_debugfs_init(port); + if (tcpm_validate_caps(port, tcpc->config->src_pdo, + tcpc->config->nr_src_pdo) || + tcpm_validate_caps(port, tcpc->config->snk_pdo, + tcpc->config->nr_snk_pdo)) { + err = -EINVAL; + goto out_destroy_wq; + } port->nr_src_pdo = tcpm_copy_pdos(port->src_pdo, tcpc->config->src_pdo, tcpc->config->nr_src_pdo); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, @@ -3584,7 +3683,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) } } - tcpm_debugfs_init(port); mutex_lock(&port->lock); tcpm_init(port); mutex_unlock(&port->lock); diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index e00051ced806..b3d41d7409b3 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -148,6 +148,8 @@ enum pd_pdo_type { (PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \ PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma)) +#define VSAFE5V 5000 /* mv units */ + #define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */ #define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */ #define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 073197f0d2bb..bc419f93c90e 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -183,9 +183,9 @@ struct tcpm_port; struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc); void tcpm_unregister_port(struct tcpm_port *port); -void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, +int tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, unsigned int nr_pdo); -void tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, +int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, unsigned int nr_pdo, unsigned int max_snk_mv, unsigned int max_snk_ma, -- 2.15.0.rc1.287.g2b38de12cc-goog From 1582976190179366445@xxx Thu Nov 02 17:28:56 +0000 2017 X-GM-THRID: 1582976190179366445 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread