All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jack Pham <jackp@codeaurora.org>
To: Felipe Balbi <balbi@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, Jack Pham <jackp@codeaurora.org>
Subject: [PATCH 2/2] usb: gadget: composite: Support more than 500mA MaxPower
Date: Tue, 22 Oct 2019 23:57:53 -0700	[thread overview]
Message-ID: <20191023065753.32722-2-jackp@codeaurora.org> (raw)
In-Reply-To: <20191023065753.32722-1-jackp@codeaurora.org>

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 UINT8_MAX since
   the 2mA multiplier corresponds to a maximum of 610mA.

Fix these by adding checks against the current gadget->speed
when the c->MaxPower value is used and appropriately limit
based on whether it is currently at a low-/full-/high- or super-
speed connection.

Incidentally, 900 is not divisble by 8, so even for super-speed
the bMaxPower neds to be capped at 896mA, otherwise due to the
round-up division a MaxPower of 900 will result in an encoded
value of 904mA and many host stacks (including Linux and Windows)
of a root port will reject the configuration.

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 <jackp@codeaurora.org>
---
 drivers/usb/gadget/composite.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e1db94d1fe2e..92ce3018f482 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -438,9 +438,10 @@ 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 DIV_ROUND_UP(min(val, 500U), 2);
 	else
-		return DIV_ROUND_UP(val, 8);
+		/* USB 3.x supports 900mA, but that isn't divisible by 8... */
+		return DIV_ROUND_UP(min(val, 896U), 8);
 }
 
 static int config_buf(struct usb_configuration *config,
@@ -852,6 +853,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)
@@ -2289,6 +2294,10 @@ void composite_resume(struct usb_gadget *gadget)
 		}
 
 		maxpower = cdev->config->MaxPower;
+		if (gadget->speed < USB_SPEED_SUPER)
+			maxpower = min_t(u16, maxpower, 500U);
+		else
+			maxpower = min_t(u16, maxpower, 900U);
 
 		usb_gadget_vbus_draw(gadget, maxpower ?
 			maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
-- 
2.21.0


  reply	other threads:[~2019-10-23  6:58 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-23  6:57 [PATCH 1/2] usb: gadget: composite: Fix bMaxPower for SuperSpeedPlus Jack Pham
2019-10-23  6:57 ` Jack Pham [this message]
2019-10-23  7:02   ` [PATCH 2/2] usb: gadget: composite: Support more than 500mA MaxPower Jack Pham
2019-10-23  7:49   ` Felipe Balbi
2019-10-23  8:31     ` jackp
2019-10-29 11:03       ` Felipe Balbi
2019-10-30  2:11         ` Jack Pham
2019-10-30 11:39           ` Felipe Balbi
2019-10-26  1:04 ` [PATCH v2 " Jack Pham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191023065753.32722-2-jackp@codeaurora.org \
    --to=jackp@codeaurora.org \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.