mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
USB fixes for 5.16-rc5
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYbYB8g8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yngkQCgs+ObloRCx7drdoGq3PYubXIMryYAn1xbP2M7 rMnenm8sK/fE0Squh56n =CkoO -----END PGP SIGNATURE----- Merge tag 'usb-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/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"
This commit is contained in:
commit
90d9fbc16b
@ -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);
|
||||
@ -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;
|
||||
|
@ -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");
|
||||
@ -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);
|
||||
|
@ -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.
|
||||
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
@ -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:
|
||||
|
@ -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;
|
||||
@ -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)
|
||||
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -3934,7 +3934,6 @@ 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
|
||||
@ -3942,7 +3941,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
*/
|
||||
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
|
||||
@ -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)
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user