Received: by 10.223.164.221 with SMTP id h29csp3164867wrb; Wed, 18 Oct 2017 13:24:24 -0700 (PDT) X-Received: by 10.84.217.201 with SMTP id d9mr16199392plj.0.1508358264616; Wed, 18 Oct 2017 13:24:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508358264; cv=none; d=google.com; s=arc-20160816; b=Ey4PDIHSV1SAD+5c4eydYB4OCB/m1nTsAzQ+ABEHJ8+4fI1dhq38AJKXsyQpta+fYd HroyvzTnnJINQQjJ1tkcx39aiUCzvJrmUfxxAkCaua9mEyOxQSHzL56IgQZvnnLuOA27 9yiNI91x4bi0rKxSZ87+zcIAxiT/Nzejs7lJvFMX7Ip7B+ldEE+vieScmcu9K4D4rr8s DIJSaYR6a26MSfHk17P3HQFSGgDtzZE+bQhuDdx0WogP8fJCOEuAOWR3gswDs9Ygo0Qm SiD4r7RsPMy9KcEUBG7DottQaXYvdW4kiiNCO9hi0Qt+qmagj1A2LyenYQD9mdCvWjRl 7dfg== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=1cUSf4P1ju7QVUL2G/39NZ39CJxqqYMjo8+VXACBURo=; b=GfvxUErcP4kPJJ8EBfGFdOsWWHl9mGgjQhplIEepTpL3vLfII+xmAFXSYbpwyZHOA8 9SgnokMEn+aZHBZds7z9cemIKxZexT7vGROjbhcN7CvFq0E9S0eg+0eWVW2NHDPnB0ii 8ov8ao9gtqysNNKMc3k9Bo0GIt+8jV/B6wkY+PNnoFH+pP7GP2mazUCcQuu52GnnonNd 5Wa9NS7ZKMJLbcKI0v1+UXAN99VI4zj7k0CkVmC83erRA4SngkJXlT8gGQl7+KmjHzc2 z/i0kfmfZMls3nmIa5WB6Ub/FcGoqoARjlSYZcYlfM4gCT4xYeXIvMfaJ/AnKvJhel+H jwlA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=eNRc724q; 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 188si7900008pfc.467.2017.10.18.13.24.10; Wed, 18 Oct 2017 13:24:24 -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=eNRc724q; 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 S1751660AbdJRUX0 (ORCPT + 99 others); Wed, 18 Oct 2017 16:23:26 -0400 Received: from mail-io0-f193.google.com ([209.85.223.193]:47276 "EHLO mail-io0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751576AbdJRUXV (ORCPT ); Wed, 18 Oct 2017 16:23:21 -0400 Received: by mail-io0-f193.google.com with SMTP id h70so7596714ioi.4 for ; Wed, 18 Oct 2017 13:23:21 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=1cUSf4P1ju7QVUL2G/39NZ39CJxqqYMjo8+VXACBURo=; b=eNRc724q0UlD+mDxaHDinJmbzRJd5GWw59T1gckyMAG8z9RKCtrjwA4MFvXU92lrhs bZnuJQ0k1rpxcOdxcW3lW+vvrEnu7zWIdwuFcBep9d1I+qvH6LU4jOzt1+pUsGIck2jv L00kUujIED/89uzG1vXbqVrykrV6HS8rOHwcOPOA2SmW5xQ2NCrMG+4cph4unAjKQX+B yx8ZVxCiAD4SYuW/WLL/XE4e/IL5/aITc7Fley/sebruvQtmyRiSJrAzHmzcOIBGyuSl D/1S/su/SRmuZxjp2J1Bbaqh6NWhLuajldS5YpZmH8G6osKYRJu7YOfEak1EdXehZ71r lzYw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=1cUSf4P1ju7QVUL2G/39NZ39CJxqqYMjo8+VXACBURo=; b=tgH8OVEFJRe0s4lUw5ehA7Ee2UzaG5wSzt45lbmOOP4nDt+v68yh658lTPcgzsNRsh iT1Cf+oUxnt5OmG6A9WxU7KDSTquZMzwHVBsoJkhTi6lm8DQfIGouVMfHDG8KUVSfX9d VFuym1vs3o6JKWZ6AG6p9KPOhBNt6cudb/2+8fuwHP6r1VkfgjYRPiWlUYqXjst099hq Q/87TM5nOdUaezLetT0pxJQFuGcQHx52eTFr9c3HTajuYwfrMq9C5akHCb55vP7jL2X5 1KsU49tSKo+HnvtPUTvACD9E4X3KnTwLk8jRL86bYRzi+V2DPisRPUywWGD1tVfW+8CA mg7g== X-Gm-Message-State: AMCzsaVkWYk+bPxD6ZPo3H5EYUsRGE7iSDzWvzD3duAeIEOYdKGwm2N6 /6Dn3yjgdnp0uSCADSWVpfwvxg== X-Google-Smtp-Source: AOwi7QDB+J6gFU23q/+Q3JRcAwH3i/Xf4XCTH2vgeQ3m0qEdFtdp4xPWLPTJvOj4mzguZ9zQZnN71g== X-Received: by 10.107.16.13 with SMTP id y13mr22020863ioi.117.1508358200683; Wed, 18 Oct 2017 13:23:20 -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.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Oct 2017 13:23:20 -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 2/2] typec: tcpm: Only request matching pdos Date: Wed, 18 Oct 2017 13:22:48 -0700 Message-Id: <20171018202248.8278-2-Badhri@google.com> X-Mailer: git-send-email 2.15.0.rc1.287.g2b38de12cc-goog In-Reply-To: <20171018202248.8278-1-Badhri@google.com> References: <20171018202248.8278-1-Badhri@google.com> 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 At present, TCPM code assumes that local device supports variable/batt pdos and always selects the pdo with highest possible power within the board limit. This assumption might not hold good for all devices. To overcome this, this patch makes TCPM only accept a source_pdo when there is a matching sink pdo. For Fixed pdos: The voltage should match between the incoming source_cap and the registered snk_pdo For Variable/Batt pdos: The incoming source_cap voltage range should fall within the registered snk_pdo's voltage range. Also, when the cap_mismatch bit is set, the max_power/current should be set to the max_current/power of the sink_pdo. This is according to: "If the Capability Mismatch bit is set to one The Maximum Operating Current/Power field may contain a value larger than the maximum current/power offered in the Source Capabilities message’s PDO as referenced by the Object position field. This enables the Sink to indicate that it requires more current/power than is being offered. If the Sink requires a different voltage this will be indicated by its Sink Capabilities message. Signed-off-by: Badhri Jagan Sridharan --- Changelog since v1: - Rebased the patch on top of drivers/usb/type/tcpm.c - Added duplicate pdo check for variable/batt pdo. - Fixed tabs as suggested by dan.carpenter@oracle.com Changelog since v2: - Rebase drivers/usb/typec/tcpm.c | 155 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 120 insertions(+), 35 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index e3f8b3da46b0..1b37333dc63b 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -261,6 +261,9 @@ struct tcpm_port { unsigned int nr_src_pdo; u32 snk_pdo[PDO_MAX_OBJECTS]; unsigned int nr_snk_pdo; + unsigned int nr_fixed; /* number of fixed sink PDOs */ + unsigned int nr_var; /* number of variable sink PDOs */ + unsigned int nr_batt; /* number of battery sink PDOs */ u32 snk_vdo[VDO_MAX_OBJECTS]; unsigned int nr_snk_vdo; @@ -1762,39 +1765,92 @@ static int tcpm_pd_check_request(struct tcpm_port *port) return 0; } -static int tcpm_pd_select_pdo(struct tcpm_port *port) +static void tcpm_pd_evaluate_pdo(struct tcpm_port *port, int src_pdo_index, + int snk_pdo_index, int *max_mw, int *max_mv, + int *selected_src_pdo, + int *matching_snk_pdo) { - unsigned int i, max_mw = 0, max_mv = 0; + unsigned int mv = 0, ma = 0, mw = 0; + u32 src_pdo = port->source_caps[src_pdo_index]; + u32 snk_pdo = port->snk_pdo[snk_pdo_index]; + enum pd_pdo_type type = pdo_type(src_pdo); + + mv = (type == PDO_TYPE_FIXED) ? pdo_fixed_voltage(src_pdo) : + pdo_min_voltage(src_pdo); + + if (type == PDO_TYPE_BATT) { + mw = min(pdo_max_power(src_pdo), pdo_max_power(snk_pdo)); + } else { + ma = min(pdo_max_current(src_pdo), pdo_max_current(snk_pdo)); + mw = ma * mv / 1000; + } + + /* Perfer higher voltages if available */ + if (mw > *max_mw || (mw == *max_mw && mv > *max_mv)) { + *selected_src_pdo = src_pdo_index; + *matching_snk_pdo = snk_pdo_index; + *max_mw = mw; + *max_mv = mv; + } +} + +static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo) +{ + unsigned int i, j, max_mw = 0, max_mv = 0; int ret = -EINVAL; /* - * Select the source PDO providing the most power while staying within - * the board's voltage limits. Prefer PDO providing exp + * Select the source PDO providing the most power which has a + * matchig sink cap. */ for (i = 0; i < port->nr_source_caps; i++) { u32 pdo = port->source_caps[i]; enum pd_pdo_type type = pdo_type(pdo); - unsigned int mv, ma, mw; - - if (type == PDO_TYPE_FIXED) - mv = pdo_fixed_voltage(pdo); - else - mv = pdo_min_voltage(pdo); - - if (type == PDO_TYPE_BATT) { - mw = pdo_max_power(pdo); - } else { - ma = min(pdo_max_current(pdo), - port->max_snk_ma); - mw = ma * mv / 1000; - } - /* Perfer higher voltages if available */ - if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && - mv <= port->max_snk_mv) { - ret = i; - max_mw = mw; - max_mv = mv; + if (type == PDO_TYPE_FIXED) { + for (j = 0; j < port->nr_fixed; j++) { + if (pdo_fixed_voltage(pdo) == + pdo_fixed_voltage(port->snk_pdo[j])) { + tcpm_pd_evaluate_pdo(port, i, j, + &max_mw, &max_mv, + &ret, sink_pdo); + /* There could only be one fixed pdo + * at a specific voltage level. + * So breaking here. + */ + break; + } + } + } else if (type == PDO_TYPE_BATT) { + for (j = port->nr_fixed; + j < port->nr_fixed + + port->nr_batt; + j++) { + if (pdo_min_voltage(pdo) >= + pdo_min_voltage(port->snk_pdo[j]) && + pdo_max_voltage(pdo) <= + pdo_max_voltage(port->snk_pdo[j])) { + tcpm_pd_evaluate_pdo(port, i, j, + &max_mw, &max_mv, + &ret, sink_pdo); + } + } + } else if (type == PDO_TYPE_VAR) { + for (j = port->nr_fixed + + port->nr_batt; + j < port->nr_fixed + + port->nr_batt + + port->nr_var; + j++) { + if (pdo_min_voltage(pdo) >= + pdo_min_voltage(port->snk_pdo[j]) && + pdo_max_voltage(pdo) <= + pdo_max_voltage(port->snk_pdo[j])) { + tcpm_pd_evaluate_pdo(port, i, j, + &max_mw, &max_mv, + &ret, sink_pdo); + } + } } } @@ -1806,13 +1862,14 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) unsigned int mv, ma, mw, flags; unsigned int max_ma, max_mw; enum pd_pdo_type type; - int index; - u32 pdo; + int index, snk_pdo_index; + u32 pdo, matching_snk_pdo; - index = tcpm_pd_select_pdo(port); + index = tcpm_pd_select_pdo(port, &snk_pdo_index); if (index < 0) return -EINVAL; pdo = port->source_caps[index]; + matching_snk_pdo = port->snk_pdo[snk_pdo_index]; type = pdo_type(pdo); if (type == PDO_TYPE_FIXED) @@ -1820,26 +1877,32 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) else mv = pdo_min_voltage(pdo); - /* Select maximum available current within the board's power limit */ + /* Select maximum available current within the sink pdo's limit */ if (type == PDO_TYPE_BATT) { - mw = pdo_max_power(pdo); - ma = 1000 * min(mw, port->max_snk_mw) / mv; + mw = min(pdo_max_power(pdo), pdo_max_power(matching_snk_pdo)); + ma = 1000 * mw / mv; } else { ma = min(pdo_max_current(pdo), - 1000 * port->max_snk_mw / mv); + pdo_max_current(matching_snk_pdo)); + mw = ma * mv / 1000; } - ma = min(ma, port->max_snk_ma); flags = RDO_USB_COMM | RDO_NO_SUSPEND; /* Set mismatch bit if offered power is less than operating power */ - mw = ma * mv / 1000; max_ma = ma; max_mw = mw; if (mw < port->operating_snk_mw) { flags |= RDO_CAP_MISMATCH; - max_mw = port->operating_snk_mw; - max_ma = max_mw * 1000 / mv; + if (type == PDO_TYPE_BATT) { + if (pdo_max_power(matching_snk_pdo) > + pdo_max_power(pdo)) + max_mw = pdo_max_power(matching_snk_pdo); + } else { + if (pdo_max_current(matching_snk_pdo) > + pdo_max_current(pdo)) + max_ma = pdo_max_current(matching_snk_pdo); + } } tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", @@ -3588,6 +3651,19 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); +static int nr_type_pdos(const u32 *pdo, unsigned int nr_pdo, + enum pd_pdo_type type) +{ + int count = 0; + int i; + + for (i = 0; i < nr_pdo; i++) { + if (pdo_type(pdo[i]) == type) + count++; + } + return count; +} + struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) { struct tcpm_port *port; @@ -3633,6 +3709,15 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) tcpc->config->nr_src_pdo); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, tcpc->config->nr_snk_pdo); + port->nr_fixed = nr_type_pdos(port->snk_pdo, + port->nr_snk_pdo, + PDO_TYPE_FIXED); + port->nr_var = nr_type_pdos(port->snk_pdo, + port->nr_snk_pdo, + PDO_TYPE_VAR); + port->nr_batt = nr_type_pdos(port->snk_pdo, + port->nr_snk_pdo, + PDO_TYPE_BATT); port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, tcpc->config->nr_snk_vdo); -- 2.15.0.rc1.287.g2b38de12cc-goog From 1584184399447927651@xxx Thu Nov 16 01:32:54 +0000 2017 X-GM-THRID: 1584184399447927651 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread