Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp676854ybh; Tue, 10 Mar 2020 06:18:34 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvsGYfg0YzpF9eZc5/w/J81Nl9Af7GQnz2dn4XhNpAhH/f2fdWNfyclWx0kJarB6jyAFJoa X-Received: by 2002:a9d:949:: with SMTP id 67mr1164692otp.304.1583846314726; Tue, 10 Mar 2020 06:18:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583846314; cv=none; d=google.com; s=arc-20160816; b=NSUz+tyLyRCeBt47D3sItolH7kmeNBLC9uIJ+EeACHZeBwy76FcRy7V4efRxEPscbn sAQhozY93uJyRkXxnmWtl9ipk6AfGmha6UaK4xc41xMcx8EOVz5go6j0TLA4Xpk7MOQ1 kno5LDJAZGnvfLHtQ6BR35/yr3OnAdozGenV2oiqkxqTucZ/8vkj5D4FXPV6XdFhpCLc e6pWYiRtaW8b8Lq3gXgl4V5EaOTeW8I6vXejVgjk/PAeV25pMEyIsJR3R52cJgxMqTg0 hSz4fBazcKiYbYfRX9Vu1xwLLlc+FRJ89yDhxib8hOFUwpWt41956dJ20e+uK+6Xwog3 ObBg== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=lqaeTGcG5AlOnuqDd7kITAwN0um2+zx0RbXYUTzod/w=; b=W320VoHuPz46IFVUdauOMcVoEy2V9EQqrY09k07MJkafMmCYG2K2mhaTjJKLet/gOM nSkwwUFWqlcZ+2UjmoJB4TS1EF8drIx/rFCwinJOR93Iqf5ZRT8l/SQS4dGnwS0qp9wJ 4RPOgezSCMgEdIIJT6pk4FhSQ3F7l8ULwXpjFtq9V6mVJJY2yYSRuq2rLUNaD6uagxDO aMCJwiXCQdfn13OAvL1yPKb8rcQTE6q723yWpLzeu76n+z6BWG/I96Jby8VZZ1mfdSX9 K7o5EIsqU9717MxpU6TXmkFe+sEHrS8mdubatBZl0xGXJnE9RH3j68VqqU3VZMbWUuCZ n3lw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=EW9aHg0a; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n15si7571881otr.262.2020.03.10.06.18.22; Tue, 10 Mar 2020 06:18:34 -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=@kernel.org header.s=default header.b=EW9aHg0a; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729241AbgCJNLb (ORCPT + 99 others); Tue, 10 Mar 2020 09:11:31 -0400 Received: from mail.kernel.org ([198.145.29.99]:32956 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731415AbgCJNL1 (ORCPT ); Tue, 10 Mar 2020 09:11:27 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B92832468F; Tue, 10 Mar 2020 13:11:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583845886; bh=+BK5GPDYSYK5n4u4NS1P7kWtlPNC0MyG+cbrrFurppQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EW9aHg0aBvp8n6ml8CfLcMelLNK7UuTu7GMTR7p2pj0Jwe2GcWgMZiXcQo2ZU2qkK vKRzx3GguGHzkG6/68mrUo+V7vXhJ3sqMOj9Q/eDy1L/VPX2GVXUSZIqePDH/lU0Z9 GfN30ahUkugW6WudtkupzrR9Uj+94xVmkX075VSY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jack Pham , Felipe Balbi , Sasha Levin Subject: [PATCH 4.19 10/86] usb: gadget: composite: Support more than 500mA MaxPower Date: Tue, 10 Mar 2020 13:44:34 +0100 Message-Id: <20200310124531.355543387@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200310124530.808338541@linuxfoundation.org> References: <20200310124530.808338541@linuxfoundation.org> User-Agent: quilt/0.66 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 From: Jack Pham [ Upstream commit a2035411fa1d1206cea7d5dfe833e78481844a76 ] USB 3.x SuperSpeed peripherals can draw up to 900mA of VBUS power when in configured state. However, if a configuration wanting to take advantage of this is added with MaxPower greater than 500 (currently possible if using a ConfigFS gadget) the composite driver fails to accommodate this for a couple reasons: - usb_gadget_vbus_draw() when called from set_config() and composite_resume() will be passed the MaxPower value without regard for the current connection speed, resulting in a violation for USB 2.0 since the max is 500mA. - the bMaxPower of the configuration descriptor would be incorrectly encoded, again if the connection speed is only at USB 2.0 or below, likely wrapping around U8_MAX since the 2mA multiplier corresponds to a maximum of 510mA. Fix these by adding checks against the current gadget->speed when the c->MaxPower value is used (set_config() and composite_resume()) and appropriately limit based on whether it is currently at a low-/full-/high- or super-speed connection. Because 900 is not divisible by 8, with the round-up division currently used in encode_bMaxPower() a MaxPower of 900mA will result in an encoded value of 0x71. When a host stack (including Linux and Windows) enumerates this on a single port root hub, it reads this value back and decodes (multiplies by 8) to get 904mA which is strictly greater than 900mA that is typically budgeted for that port, causing it to reject the configuration. Instead, we should be using the round-down behavior of normal integral division so that 900 / 8 -> 0x70 or 896mA to stay within range. And we might as well change it for the high/full/low case as well for consistency. N.B. USB 3.2 Gen N x 2 allows for up to 1500mA but there doesn't seem to be any any peripheral controller supported by Linux that does two lane operation, so for now keeping the clamp at 900 should be fine. Signed-off-by: Jack Pham Signed-off-by: Felipe Balbi Signed-off-by: Sasha Levin --- drivers/usb/gadget/composite.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index fea7c7e0143f2..30aefd1adbadd 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -438,9 +438,13 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, if (!val) return 0; if (speed < USB_SPEED_SUPER) - return DIV_ROUND_UP(val, 2); + return min(val, 500U) / 2; else - return DIV_ROUND_UP(val, 8); + /* + * USB 3.x supports up to 900mA, but since 900 isn't divisible + * by 8 the integral division will effectively cap to 896mA. + */ + return min(val, 900U) / 8; } static int config_buf(struct usb_configuration *config, @@ -838,6 +842,10 @@ static int set_config(struct usb_composite_dev *cdev, /* when we return, be sure our power usage is valid */ power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW; + if (gadget->speed < USB_SPEED_SUPER) + power = min(power, 500U); + else + power = min(power, 900U); done: usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) @@ -2264,7 +2272,7 @@ void composite_resume(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - u16 maxpower; + unsigned maxpower; /* REVISIT: should we have config level * suspend/resume callbacks? @@ -2278,10 +2286,14 @@ void composite_resume(struct usb_gadget *gadget) f->resume(f); } - maxpower = cdev->config->MaxPower; + maxpower = cdev->config->MaxPower ? + cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW; + if (gadget->speed < USB_SPEED_SUPER) + maxpower = min(maxpower, 500U); + else + maxpower = min(maxpower, 900U); - usb_gadget_vbus_draw(gadget, maxpower ? - maxpower : CONFIG_USB_GADGET_VBUS_DRAW); + usb_gadget_vbus_draw(gadget, maxpower); } cdev->suspended = 0; -- 2.20.1