Received: by 10.223.164.202 with SMTP id h10csp1383438wrb; Wed, 15 Nov 2017 19:17:58 -0800 (PST) X-Google-Smtp-Source: AGs4zMaL7CAHjY6g7O8Ue8T7ARVwewCqzrCCz8n/Ms36S1SspQIDaN/MMbkxhTLW9Ajfe6xP1H25 X-Received: by 10.84.128.36 with SMTP id 33mr243082pla.329.1510802278857; Wed, 15 Nov 2017 19:17:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510802278; cv=none; d=google.com; s=arc-20160816; b=UZFZ17hAFJds7uYp4SZtlKs470uHRKbaOL/EExe+gODGPO5pHutpDSX+qv1fck77C8 ARtJPSaIH1M5FBsSwJnFyFM6dP6d4w5+FblTzVrNp8gJzGzmu6BAXjihWOaUkK4pimG1 HdH8kvT+I9TVAsas2UuqWx3gio2gw2JxLmgBTK1PsKSluZTZTT7P6BMDZgvYHD9Gxpxy NiRAcGPKBQmzsLtG/HRs0CpvgYsuWcH4M5jaOlXZEOL7jp4UeVmfQdWSTcn1mUxvKPSw gIiuQdrD/J6rZRPRpxleU6fUseLf1F8ybLw+dcYWZ9MBrBBULbV+PaEo2KrrUN4hKalA mosA== 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=x/70ez+/vfvGq1sgmOjZyhN1el8MPDWRyatoqm6yZcc=; b=LFldbcPC8HWQgixXdjOfCxCQbKCjXGPm0udUynFzsHACoKzMmKy3LEYdpATIMTdtNJ 29rBmFLyGHBSx4jwC9Zgn9gtASM1D1KCggXOLE4SAyLgawIUpgbSn6UoSOoa1WjWulG6 Cg+2Um+Ot4po1v+iqfwCCwVzSnjEvBPL20R1jrdh0irSM4VlAa5VS568Np5vvSNcNesf MCBPLufQkXsULgdeXefVzfVkFkKMjOMPz6eK/Lh4JBXjZjmhkCD4PncGSHZeJcZwPCkk ElK64232DiYzz49dKuBvrOKlpl3bNkB6GvW/k9Qqq3K4dFwd2RdaneqlD4YxXBR7BeTc bXyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=Ni5sNm+O; 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 x81si124732pff.17.2017.11.15.19.17.46; Wed, 15 Nov 2017 19:17:58 -0800 (PST) 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=Ni5sNm+O; 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 S932702AbdKPBCl (ORCPT + 89 others); Wed, 15 Nov 2017 20:02:41 -0500 Received: from mail-it0-f67.google.com ([209.85.214.67]:42502 "EHLO mail-it0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757640AbdKPBCX (ORCPT ); Wed, 15 Nov 2017 20:02:23 -0500 Received: by mail-it0-f67.google.com with SMTP id n134so3964111itg.1 for ; Wed, 15 Nov 2017 17:02:22 -0800 (PST) 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=x/70ez+/vfvGq1sgmOjZyhN1el8MPDWRyatoqm6yZcc=; b=Ni5sNm+OqzDO6IxHYX14wcHvhC5CBI4vp2As79se5Xvgd2vUQs33cUxj+AhYIqD1vM Hh1A9wTXLt9S9rJwFumkJedTEIjg3jYkma8DjzSrPY7ZHYRiPmAsb75ehfq+xjSkTK5x kHpdIeHW4Z+1Q0ujYHOm1egVnZNz9d4+TYBs1YawCG33BFP402+rw8DpqvSdbDZNvOU4 ZTOPr9v2QzRiJ7U5/vH4N4bHq8sa2M6L6TNkuwKl1f7CoLLMOVAhqs/49W33o6e8mJC/ DHn58S4J4mSb1DAv5ZFIohj8u/wo9eeRzWcMBH5snFG5la04dbu7lgwi5icf5PL/nfmY rY4w== 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=x/70ez+/vfvGq1sgmOjZyhN1el8MPDWRyatoqm6yZcc=; b=X+T2tQthtH5u0wYMqD9o7lzeMwIAnVcKaZqfyuuM+CK0W8xSD5nn+3vCzsmiraTRih MAf4ErtnhfEu9ktJm9VQL8+/5MqtBWxfULRZodGTUjlrDNAp6o67BHEMVd9af6D9VXK9 32wi74FRPnds0gBSER9cNznBTc+2fpbP/vUSnX1SeK3d8pP4+JFLgBF2+2h3ATBQvN2W FnHN1r8EMgK/e4EFYDVbxte42vX5qhzEklQaRxP657+ZTab8qUxdS6guadJd8FlQvkQW QjHHPzKvOJdiGBsVpwJGjS8winwQ4pYW4xQKdJ7bmWpI/+AGHDvFB/U0zyJv05qoeCbl sjMA== X-Gm-Message-State: AJaThX410p+Z30QmZkaDJEyWSdCTFcl555FJXajtteWyzXoDe0bUelTq ygiQMnTCJz6tl3rTcgW96fDoiQ== X-Received: by 10.36.98.70 with SMTP id d67mr444715itc.40.1510794141838; Wed, 15 Nov 2017 17:02:21 -0800 (PST) Received: from badhri.mtv.corp.google.com ([172.22.122.202]) by smtp.gmail.com with ESMTPSA id i62sm10151885ioe.31.2017.11.15.17.02.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Nov 2017 17:02:21 -0800 (PST) From: Badhri Jagan Sridharan X-Google-Original-From: Badhri Jagan Sridharan To: heikki.krogerus@linux.intel.com, gregkh@linuxfoundation.org, dan.carpenter@oracle.com, linux@roeck-us.net Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Subject: [PATCH 2/2 v7] typec: tcpm: Only request matching pdos Date: Wed, 15 Nov 2017 17:01:56 -0800 Message-Id: <20171116010156.25259-2-Badhri@google.com> X-Mailer: git-send-email 2.15.0.448.gf294e3d99a-goog In-Reply-To: <20171116010156.25259-1-Badhri@google.com> References: <20171116010156.25259-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 Acked-by: Heikki Krogerus Reviewed-by: Guenter Roeck --- 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 Changelog since v3: - Refactored code fixed formatting issues as suggested by heikki.krogerus@linux.intel.com Changelog since v4: - Rebase Changelog since v5: - handling the sink pdo index as pointer argument in tcpm_pd_select_pdo - ACK by heikki.krogerus@linux.intel.com Changelog since v6: - Added Reviewed-by: Guenter Roeck drivers/usb/typec/tcpm.c | 163 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 42 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 8b637a4b474b..f4d563ee7690 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -252,6 +252,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; @@ -1767,39 +1770,90 @@ static int tcpm_pd_check_request(struct tcpm_port *port) return 0; } -static int tcpm_pd_select_pdo(struct tcpm_port *port) +#define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) +#define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) + +static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, + int *src_pdo) { - unsigned int i, max_mw = 0, max_mv = 0; + unsigned int i, j, max_mw = 0, max_mv = 0, mw = 0, mv = 0, ma = 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])) { + ma = min_current(pdo, port->snk_pdo[j]); + mv = pdo_fixed_voltage(pdo); + mw = ma * mv / 1000; + if (mw > max_mw || + (mw == max_mw && mv > max_mv)) { + ret = 0; + *src_pdo = i; + *sink_pdo = j; + max_mw = mw; + max_mv = mv; + } + /* 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])) { + mw = min_power(pdo, port->snk_pdo[j]); + mv = pdo_min_voltage(pdo); + if (mw > max_mw || + (mw == max_mw && mv > max_mv)) { + ret = 0; + *src_pdo = i; + *sink_pdo = j; + max_mw = mw; + max_mv = mv; + } + } + } + } 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])) { + ma = min_current(pdo, port->snk_pdo[j]); + mv = pdo_min_voltage(pdo); + mw = ma * mv / 1000; + if (mw > max_mw || + (mw == max_mw && mv > max_mv)) { + ret = 0; + *src_pdo = i; + *sink_pdo = j; + max_mw = mw; + max_mv = mv; + } + } + } } } @@ -1811,13 +1865,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 src_pdo_index, snk_pdo_index; + u32 pdo, matching_snk_pdo; - index = tcpm_pd_select_pdo(port); - if (index < 0) + if (tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index) < 0) return -EINVAL; - pdo = port->source_caps[index]; + + pdo = port->source_caps[src_pdo_index]; + matching_snk_pdo = port->snk_pdo[snk_pdo_index]; type = pdo_type(pdo); if (type == PDO_TYPE_FIXED) @@ -1825,26 +1880,28 @@ 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_power(pdo, matching_snk_pdo); + ma = 1000 * mw / mv; } else { - ma = min(pdo_max_current(pdo), - 1000 * port->max_snk_mw / mv); + ma = min_current(pdo, 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 && + (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", @@ -1853,16 +1910,16 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) port->polarity); if (type == PDO_TYPE_BATT) { - *rdo = RDO_BATT(index + 1, mw, max_mw, flags); + *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", - index, mv, mw, + src_pdo_index, mv, mw, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } else { - *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); + *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", - index, mv, ma, + src_pdo_index, mv, ma, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } @@ -3593,6 +3650,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; @@ -3638,6 +3708,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.448.gf294e3d99a-goog From 1585292182820459608@xxx Tue Nov 28 07:00:38 +0000 2017 X-GM-THRID: 1585091602443532538 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread