Skip to content

Commit

Permalink
Merge tag 'usb-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 5.16-rc5.  They include:

   - gadget driver fixes for reported issues

   - xhci fixes for reported problems.

   - config endpoint parsing fixes for where we got bitfields wrong

  Most of these have been in linux-next, the remaining few were not, but
  got lots of local testing in my systems and in some cloud testing
  infrastructures"

* tag 'usb-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: core: config: using bit mask instead of individual bits
  usb: core: config: fix validation of wMaxPacketValue entries
  USB: gadget: zero allocate endpoint 0 buffers
  USB: gadget: detect too-big endpoint 0 requests
  xhci: avoid race between disable slot command and host runtime suspend
  xhci: Remove CONFIG_USB_DEFAULT_PERSIST to prevent xHCI from runtime suspending
  Revert "usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default"
  • Loading branch information
Linus Torvalds committed Dec 12, 2021
2 parents 8d7ed10 + ca57373 commit 90d9fbc
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 33 deletions.
6 changes: 3 additions & 3 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
* the USB-2 spec requires such endpoints to have wMaxPacketSize = 0
* (see the end of section 5.6.3), so don't warn about them.
*/
maxp = usb_endpoint_maxp(&endpoint->desc);
maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize);
if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
cfgno, inum, asnum, d->bEndpointAddress);
Expand All @@ -422,9 +422,9 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
maxpacket_maxes = full_speed_maxpacket_maxes;
break;
case USB_SPEED_HIGH:
/* Bits 12..11 are allowed only for HS periodic endpoints */
/* Multiple-transactions bits are allowed only for HS periodic endpoints */
if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) {
i = maxp & (BIT(12) | BIT(11));
i = maxp & USB_EP_MAXP_MULT_MASK;
maxp &= ~i;
}
fallthrough;
Expand Down
15 changes: 0 additions & 15 deletions drivers/usb/dwc3/dwc3-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node, *dwc3_np;
struct device *dev = &pdev->dev;
struct property *prop;
int ret;

dwc3_np = of_get_compatible_child(np, "snps,dwc3");
Expand All @@ -658,20 +657,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
return -ENODEV;
}

prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
if (!prop) {
ret = -ENOMEM;
dev_err(dev, "unable to allocate memory for property\n");
goto node_put;
}

prop->name = "tx-fifo-resize";
ret = of_add_property(dwc3_np, prop);
if (ret) {
dev_err(dev, "unable to add property\n");
goto node_put;
}

ret = of_platform_populate(np, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
Expand Down
14 changes: 13 additions & 1 deletion drivers/usb/gadget/composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_function *f = NULL;
u8 endp;

if (w_length > USB_COMP_EP0_BUFSIZ) {
if (ctrl->bRequestType == USB_DIR_OUT) {
goto done;
} else {
/* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength;

*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
w_length = USB_COMP_EP0_BUFSIZ;
}
}

/* partial re-init of the response message; the function or the
* gadget might need to intercept e.g. a control-OUT completion
* when we delegate to it.
Expand Down Expand Up @@ -2209,7 +2221,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite,
if (!cdev->req)
return -ENOMEM;

cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
if (!cdev->req->buf)
goto fail;

Expand Down
15 changes: 14 additions & 1 deletion drivers/usb/gadget/legacy/dbgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep)
goto fail_1;
}

req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
if (!req->buf) {
err = -ENOMEM;
stp = 2;
Expand Down Expand Up @@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
void *data = NULL;
u16 len = 0;

if (length > DBGP_REQ_LEN) {
if (ctrl->bRequestType == USB_DIR_OUT) {
return err;
} else {
/* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength;

*temp = cpu_to_le16(DBGP_REQ_LEN);
length = DBGP_REQ_LEN;
}
}


if (request == USB_REQ_GET_DESCRIPTOR) {
switch (value>>8) {
case USB_DT_DEVICE:
Expand Down
16 changes: 15 additions & 1 deletion drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ enum ep0_state {
/* enough for the whole queue: most events invalidate others */
#define N_EVENT 5

#define RBUF_SIZE 256

struct dev_data {
spinlock_t lock;
refcount_t count;
Expand Down Expand Up @@ -144,7 +146,7 @@ struct dev_data {
struct dentry *dentry;

/* except this scratch i/o buffer for ep0 */
u8 rbuf [256];
u8 rbuf[RBUF_SIZE];
};

static inline void get_dev (struct dev_data *data)
Expand Down Expand Up @@ -1331,6 +1333,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);

if (w_length > RBUF_SIZE) {
if (ctrl->bRequestType == USB_DIR_OUT) {
return value;
} else {
/* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength;

*temp = cpu_to_le16(RBUF_SIZE);
w_length = RBUF_SIZE;
}
}

spin_lock (&dev->lock);
dev->setup_abort = 0;
if (dev->state == STATE_DEV_UNCONNECTED) {
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,
continue;

retval = xhci_disable_slot(xhci, i);
xhci_free_virt_device(xhci, i);
if (retval)
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
i, retval);
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
/* Delete default control endpoint resources */
xhci_free_device_endpoint_resources(xhci, virt_dev, true);
xhci_free_virt_device(xhci, slot_id);
}

static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
Expand Down
26 changes: 15 additions & 11 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3934,15 +3934,13 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_slot_ctx *slot_ctx;
int i, ret;

#ifndef CONFIG_USB_DEFAULT_PERSIST
/*
* We called pm_runtime_get_noresume when the device was attached.
* Decrement the counter here to allow controller to runtime suspend
* if no devices remain.
*/
if (xhci->quirks & XHCI_RESET_ON_RESUME)
pm_runtime_put_noidle(hcd->self.controller);
#endif

ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
/* If the host is halted due to driver unload, we still need to free the
Expand All @@ -3961,9 +3959,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
virt_dev->udev = NULL;
ret = xhci_disable_slot(xhci, udev->slot_id);
if (ret)
xhci_free_virt_device(xhci, udev->slot_id);
xhci_disable_slot(xhci, udev->slot_id);
xhci_free_virt_device(xhci, udev->slot_id);
}

int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
Expand All @@ -3973,7 +3970,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
u32 state;
int ret = 0;

command = xhci_alloc_command(xhci, false, GFP_KERNEL);
command = xhci_alloc_command(xhci, true, GFP_KERNEL);
if (!command)
return -ENOMEM;

Expand All @@ -3998,6 +3995,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);

wait_for_completion(command->completion);

if (command->status != COMP_SUCCESS)
xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n",
slot_id, command->status);

xhci_free_command(xhci, command);

return ret;
}

Expand Down Expand Up @@ -4094,23 +4100,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)

xhci_debugfs_create_slot(xhci, slot_id);

#ifndef CONFIG_USB_DEFAULT_PERSIST
/*
* If resetting upon resume, we can't put the controller into runtime
* suspend if there is a device attached.
*/
if (xhci->quirks & XHCI_RESET_ON_RESUME)
pm_runtime_get_noresume(hcd->self.controller);
#endif

/* Is this a LS or FS device under a HS hub? */
/* Hub or peripherial? */
return 1;

disable_slot:
ret = xhci_disable_slot(xhci, udev->slot_id);
if (ret)
xhci_free_virt_device(xhci, udev->slot_id);
xhci_disable_slot(xhci, udev->slot_id);
xhci_free_virt_device(xhci, udev->slot_id);

return 0;
}
Expand Down Expand Up @@ -4240,6 +4243,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,

mutex_unlock(&xhci->mutex);
ret = xhci_disable_slot(xhci, udev->slot_id);
xhci_free_virt_device(xhci, udev->slot_id);
if (!ret)
xhci_alloc_dev(hcd, udev);
kfree(command->completion);
Expand Down

0 comments on commit 90d9fbc

Please sign in to comment.