mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 13:34:30 +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
|
* 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.
|
* (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)) {
|
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",
|
dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
|
||||||
cfgno, inum, asnum, d->bEndpointAddress);
|
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;
|
maxpacket_maxes = full_speed_maxpacket_maxes;
|
||||||
break;
|
break;
|
||||||
case USB_SPEED_HIGH:
|
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)) {
|
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;
|
maxp &= ~i;
|
||||||
}
|
}
|
||||||
fallthrough;
|
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 dwc3_qcom *qcom = platform_get_drvdata(pdev);
|
||||||
struct device_node *np = pdev->dev.of_node, *dwc3_np;
|
struct device_node *np = pdev->dev.of_node, *dwc3_np;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct property *prop;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dwc3_np = of_get_compatible_child(np, "snps,dwc3");
|
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;
|
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);
|
ret = of_platform_populate(np, NULL, NULL, dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to register dwc3 core - %d\n", 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;
|
struct usb_function *f = NULL;
|
||||||
u8 endp;
|
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
|
/* partial re-init of the response message; the function or the
|
||||||
* gadget might need to intercept e.g. a control-OUT completion
|
* gadget might need to intercept e.g. a control-OUT completion
|
||||||
* when we delegate to it.
|
* when we delegate to it.
|
||||||
@ -2209,7 +2221,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite,
|
|||||||
if (!cdev->req)
|
if (!cdev->req)
|
||||||
return -ENOMEM;
|
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)
|
if (!cdev->req->buf)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep)
|
|||||||
goto fail_1;
|
goto fail_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
|
req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
|
||||||
if (!req->buf) {
|
if (!req->buf) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
stp = 2;
|
stp = 2;
|
||||||
@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
|
|||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
u16 len = 0;
|
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) {
|
if (request == USB_REQ_GET_DESCRIPTOR) {
|
||||||
switch (value>>8) {
|
switch (value>>8) {
|
||||||
case USB_DT_DEVICE:
|
case USB_DT_DEVICE:
|
||||||
|
@ -110,6 +110,8 @@ enum ep0_state {
|
|||||||
/* enough for the whole queue: most events invalidate others */
|
/* enough for the whole queue: most events invalidate others */
|
||||||
#define N_EVENT 5
|
#define N_EVENT 5
|
||||||
|
|
||||||
|
#define RBUF_SIZE 256
|
||||||
|
|
||||||
struct dev_data {
|
struct dev_data {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
refcount_t count;
|
refcount_t count;
|
||||||
@ -144,7 +146,7 @@ struct dev_data {
|
|||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
|
|
||||||
/* except this scratch i/o buffer for ep0 */
|
/* except this scratch i/o buffer for ep0 */
|
||||||
u8 rbuf [256];
|
u8 rbuf[RBUF_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void get_dev (struct dev_data *data)
|
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_value = le16_to_cpu(ctrl->wValue);
|
||||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
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);
|
spin_lock (&dev->lock);
|
||||||
dev->setup_abort = 0;
|
dev->setup_abort = 0;
|
||||||
if (dev->state == STATE_DEV_UNCONNECTED) {
|
if (dev->state == STATE_DEV_UNCONNECTED) {
|
||||||
|
@ -717,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
retval = xhci_disable_slot(xhci, i);
|
retval = xhci_disable_slot(xhci, i);
|
||||||
|
xhci_free_virt_device(xhci, i);
|
||||||
if (retval)
|
if (retval)
|
||||||
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
|
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
|
||||||
i, retval);
|
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)
|
if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
|
||||||
/* Delete default control endpoint resources */
|
/* Delete default control endpoint resources */
|
||||||
xhci_free_device_endpoint_resources(xhci, virt_dev, true);
|
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,
|
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;
|
struct xhci_slot_ctx *slot_ctx;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
#ifndef CONFIG_USB_DEFAULT_PERSIST
|
|
||||||
/*
|
/*
|
||||||
* We called pm_runtime_get_noresume when the device was attached.
|
* We called pm_runtime_get_noresume when the device was attached.
|
||||||
* Decrement the counter here to allow controller to runtime suspend
|
* 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)
|
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
||||||
pm_runtime_put_noidle(hcd->self.controller);
|
pm_runtime_put_noidle(hcd->self.controller);
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
|
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
|
/* 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);
|
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
|
||||||
}
|
}
|
||||||
virt_dev->udev = NULL;
|
virt_dev->udev = NULL;
|
||||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
xhci_disable_slot(xhci, udev->slot_id);
|
||||||
if (ret)
|
xhci_free_virt_device(xhci, udev->slot_id);
|
||||||
xhci_free_virt_device(xhci, udev->slot_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int xhci_disable_slot(struct xhci_hcd *xhci, u32 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;
|
u32 state;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
command = xhci_alloc_command(xhci, false, GFP_KERNEL);
|
command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
||||||
if (!command)
|
if (!command)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -3998,6 +3995,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
|
|||||||
}
|
}
|
||||||
xhci_ring_cmd_db(xhci);
|
xhci_ring_cmd_db(xhci);
|
||||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
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;
|
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);
|
xhci_debugfs_create_slot(xhci, slot_id);
|
||||||
|
|
||||||
#ifndef CONFIG_USB_DEFAULT_PERSIST
|
|
||||||
/*
|
/*
|
||||||
* If resetting upon resume, we can't put the controller into runtime
|
* If resetting upon resume, we can't put the controller into runtime
|
||||||
* suspend if there is a device attached.
|
* suspend if there is a device attached.
|
||||||
*/
|
*/
|
||||||
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
||||||
pm_runtime_get_noresume(hcd->self.controller);
|
pm_runtime_get_noresume(hcd->self.controller);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Is this a LS or FS device under a HS hub? */
|
/* Is this a LS or FS device under a HS hub? */
|
||||||
/* Hub or peripherial? */
|
/* Hub or peripherial? */
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
disable_slot:
|
disable_slot:
|
||||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
xhci_disable_slot(xhci, udev->slot_id);
|
||||||
if (ret)
|
xhci_free_virt_device(xhci, udev->slot_id);
|
||||||
xhci_free_virt_device(xhci, udev->slot_id);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -4240,6 +4243,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
|||||||
|
|
||||||
mutex_unlock(&xhci->mutex);
|
mutex_unlock(&xhci->mutex);
|
||||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||||
|
xhci_free_virt_device(xhci, udev->slot_id);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
xhci_alloc_dev(hcd, udev);
|
xhci_alloc_dev(hcd, udev);
|
||||||
kfree(command->completion);
|
kfree(command->completion);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user