Skip to content

Commit

Permalink
Merge tag 'usb-5.4-rc6' 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:
 "The USB sub-maintainers woke up this past week and sent a bunch of
  tiny fixes. Here are a lot of small patches that that resolve a bunch
  of reported issues in the USB core, drivers, serial drivers, gadget
  drivers, and of course, xhci :)

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (31 commits)
  usb: dwc3: gadget: fix race when disabling ep with cancelled xfers
  usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host
  usb: cdns3: gadget: reset EP_CLAIMED flag while unloading
  USB: serial: whiteheat: fix line-speed endianness
  USB: serial: whiteheat: fix potential slab corruption
  USB: gadget: Reject endpoints with 0 maxpacket value
  UAS: Revert commit 3ae62a4 ("UAS: fix alignment of scatter/gather segments")
  usb-storage: Revert commit 747668d ("usb-storage: Set virt_boundary_mask to avoid SG overflows")
  usbip: Fix free of unallocated memory in vhci tx
  usbip: tools: Fix read_usb_vudc_device() error path handling
  usb: xhci: fix __le32/__le64 accessors in debugfs code
  usb: xhci: fix Immediate Data Transfer endianness
  xhci: Fix use-after-free regression in xhci clear hub TT implementation
  USB: ldusb: fix control-message timeout
  USB: ldusb: use unsigned size format specifiers
  USB: ldusb: fix ring-buffer locking
  USB: Skip endpoints with 0 maxpacket length
  usb: cdns3: gadget: Don't manage pullups
  usb: dwc3: remove the call trace of USBx_GFLADJ
  usb: gadget: configfs: fix concurrent issue between composite APIs
  ...
  • Loading branch information
Linus Torvalds committed Nov 3, 2019
2 parents 56cfd25 + d8eca64 commit 3a69c9e
Show file tree
Hide file tree
Showing 27 changed files with 267 additions and 97 deletions.
37 changes: 28 additions & 9 deletions drivers/usb/cdns3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2329,8 +2329,6 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev)
writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, &regs->usb_conf);

cdns3_configure_dmult(priv_dev, NULL);

cdns3_gadget_pullup(&priv_dev->gadget, 1);
}

/**
Expand All @@ -2345,9 +2343,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
{
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
unsigned long flags;
enum usb_device_speed max_speed = driver->max_speed;

spin_lock_irqsave(&priv_dev->lock, flags);
priv_dev->gadget_driver = driver;

/* limit speed if necessary */
max_speed = min(driver->max_speed, gadget->max_speed);

switch (max_speed) {
case USB_SPEED_FULL:
writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
break;
case USB_SPEED_HIGH:
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
break;
case USB_SPEED_SUPER:
break;
default:
dev_err(priv_dev->dev,
"invalid maximum_speed parameter %d\n",
max_speed);
/* fall through */
case USB_SPEED_UNKNOWN:
/* default to superspeed */
max_speed = USB_SPEED_SUPER;
break;
}

cdns3_gadget_config(priv_dev);
spin_unlock_irqrestore(&priv_dev->lock, flags);
return 0;
Expand Down Expand Up @@ -2381,6 +2405,8 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val,
!(val & EP_CMD_EPRST), 1, 100);

priv_ep->flags &= ~EP_CLAIMED;
}

/* disable interrupt for device */
Expand Down Expand Up @@ -2575,12 +2601,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
/* Check the maximum_speed parameter */
switch (max_speed) {
case USB_SPEED_FULL:
writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
break;
case USB_SPEED_HIGH:
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
break;
case USB_SPEED_SUPER:
break;
default:
Expand Down Expand Up @@ -2713,8 +2734,6 @@ static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
/* disable interrupt for device */
writel(0, &priv_dev->regs->usb_ien);

cdns3_gadget_pullup(&priv_dev->gadget, 0);

return 0;
}

Expand Down
1 change: 0 additions & 1 deletion drivers/usb/cdns3/host-export.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#ifdef CONFIG_USB_CDNS3_HOST

int cdns3_host_init(struct cdns3 *cdns);
void cdns3_host_exit(struct cdns3 *cdns);

#else

Expand Down
1 change: 1 addition & 0 deletions drivers/usb/cdns3/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include "core.h"
#include "drd.h"
#include "host-export.h"

static int __cdns3_host_init(struct cdns3 *cdns)
{
Expand Down
5 changes: 5 additions & 0 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,

/* Validate the wMaxPacketSize field */
maxp = usb_endpoint_maxp(&endpoint->desc);
if (maxp == 0) {
dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
cfgno, inum, asnum, d->bEndpointAddress);
goto skip_to_next_endpoint_or_interface_descriptor;
}

/* Find the highest legal maxpacket size for this endpoint */
i = 0; /* additional transactions per microframe */
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ config USB_DWC3_MESON_G12A
depends on ARCH_MESON || COMPILE_TEST
default USB_DWC3
select USB_ROLE_SWITCH
select REGMAP_MMIO
help
Support USB2/3 functionality in Amlogic G12A platforms.
Say 'Y' or 'M' if you have one such device.
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/dwc3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)

reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
dft = reg & DWC3_GFLADJ_30MHZ_MASK;
if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
"request value same as default, ignoring\n")) {
if (dft != dwc->fladj) {
reg &= ~DWC3_GFLADJ_30MHZ_MASK;
reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)

ret = platform_device_add_properties(dwc->dwc3, p);
if (ret < 0)
return ret;
goto err;

ret = dwc3_pci_quirks(dwc);
if (ret)
Expand Down
6 changes: 6 additions & 0 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)

dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
}

while (!list_empty(&dep->cancelled_list)) {
req = next_request(&dep->cancelled_list);

dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
}
}

/**
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/gadget/composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -2170,14 +2170,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req);

kfree(cdev->os_desc_req->buf);
cdev->os_desc_req->buf = NULL;
usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
cdev->os_desc_req = NULL;
}
if (cdev->req) {
if (cdev->setup_pending)
usb_ep_dequeue(cdev->gadget->ep0, cdev->req);

kfree(cdev->req->buf);
cdev->req->buf = NULL;
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
cdev->req = NULL;
}
cdev->next_string_id = 0;
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
Expand Down
110 changes: 105 additions & 5 deletions drivers/usb/gadget/configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ struct gadget_info {
bool use_os_desc;
char b_vendor_code;
char qw_sign[OS_STRING_QW_SIGN_LEN];
spinlock_t spinlock;
bool unbind;
};

static inline struct gadget_info *to_gadget_info(struct config_item *item)
Expand Down Expand Up @@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
int ret;

/* the gi->lock is hold by the caller */
gi->unbind = 0;
cdev->gadget = gadget;
set_gadget_data(gadget, cdev);
ret = composite_dev_prepare(composite, cdev);
Expand Down Expand Up @@ -1376,31 +1379,128 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
unsigned long flags;

/* the gi->lock is hold by the caller */

cdev = get_gadget_data(gadget);
gi = container_of(cdev, struct gadget_info, cdev);
spin_lock_irqsave(&gi->spinlock, flags);
gi->unbind = 1;
spin_unlock_irqrestore(&gi->spinlock, flags);

kfree(otg_desc[0]);
otg_desc[0] = NULL;
purge_configs_funcs(gi);
composite_dev_cleanup(cdev);
usb_ep_autoconfig_reset(cdev->gadget);
spin_lock_irqsave(&gi->spinlock, flags);
cdev->gadget = NULL;
set_gadget_data(gadget, NULL);
spin_unlock_irqrestore(&gi->spinlock, flags);
}

static int configfs_composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
unsigned long flags;
int ret;

cdev = get_gadget_data(gadget);
if (!cdev)
return 0;

gi = container_of(cdev, struct gadget_info, cdev);
spin_lock_irqsave(&gi->spinlock, flags);
cdev = get_gadget_data(gadget);
if (!cdev || gi->unbind) {
spin_unlock_irqrestore(&gi->spinlock, flags);
return 0;
}

ret = composite_setup(gadget, ctrl);
spin_unlock_irqrestore(&gi->spinlock, flags);
return ret;
}

static void configfs_composite_disconnect(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
unsigned long flags;

cdev = get_gadget_data(gadget);
if (!cdev)
return;

gi = container_of(cdev, struct gadget_info, cdev);
spin_lock_irqsave(&gi->spinlock, flags);
cdev = get_gadget_data(gadget);
if (!cdev || gi->unbind) {
spin_unlock_irqrestore(&gi->spinlock, flags);
return;
}

composite_disconnect(gadget);
spin_unlock_irqrestore(&gi->spinlock, flags);
}

static void configfs_composite_suspend(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
unsigned long flags;

cdev = get_gadget_data(gadget);
if (!cdev)
return;

gi = container_of(cdev, struct gadget_info, cdev);
spin_lock_irqsave(&gi->spinlock, flags);
cdev = get_gadget_data(gadget);
if (!cdev || gi->unbind) {
spin_unlock_irqrestore(&gi->spinlock, flags);
return;
}

composite_suspend(gadget);
spin_unlock_irqrestore(&gi->spinlock, flags);
}

static void configfs_composite_resume(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
unsigned long flags;

cdev = get_gadget_data(gadget);
if (!cdev)
return;

gi = container_of(cdev, struct gadget_info, cdev);
spin_lock_irqsave(&gi->spinlock, flags);
cdev = get_gadget_data(gadget);
if (!cdev || gi->unbind) {
spin_unlock_irqrestore(&gi->spinlock, flags);
return;
}

composite_resume(gadget);
spin_unlock_irqrestore(&gi->spinlock, flags);
}

static const struct usb_gadget_driver configfs_driver_template = {
.bind = configfs_composite_bind,
.unbind = configfs_composite_unbind,

.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
.setup = configfs_composite_setup,
.reset = configfs_composite_disconnect,
.disconnect = configfs_composite_disconnect,

.suspend = composite_suspend,
.resume = composite_resume,
.suspend = configfs_composite_suspend,
.resume = configfs_composite_resume,

.max_speed = USB_SPEED_SUPER,
.driver = {
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/gadget/udc/atmel_usba_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req)
next_fifo_transaction(ep, req);
if (req->last_transaction) {
usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
if (ep_is_control(ep))
usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
} else {
usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
if (ep_is_control(ep))
usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
}
}
Expand Down
11 changes: 11 additions & 0 deletions drivers/usb/gadget/udc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep)
if (ep->enabled)
goto out;

/* UDC drivers can't handle endpoints with maxpacket size 0 */
if (usb_endpoint_maxp(ep->desc) == 0) {
/*
* We should log an error message here, but we can't call
* dev_err() because there's no way to find the gadget
* given only ep.
*/
ret = -EINVAL;
goto out;
}

ret = ep->ops->enable(ep, ep->desc);
if (ret)
goto out;
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/gadget/udc/fsl_udc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2576,7 +2576,7 @@ static int fsl_udc_remove(struct platform_device *pdev)
dma_pool_destroy(udc_controller->td_pool);
free_irq(udc_controller->irq, udc_controller);
iounmap(dr_regs);
if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE))
release_mem_region(res->start, resource_size(res));

/* free udc --wait for the release() finished */
Expand Down
11 changes: 6 additions & 5 deletions drivers/usb/gadget/udc/renesas_usb3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1544,10 +1544,10 @@ static void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr)
static bool usb3_std_req_set_address(struct renesas_usb3 *usb3,
struct usb_ctrlrequest *ctrl)
{
if (ctrl->wValue >= 128)
if (le16_to_cpu(ctrl->wValue) >= 128)
return true; /* stall */

usb3_set_device_address(usb3, ctrl->wValue);
usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue));
usb3_set_p0_con_for_no_data(usb3);

return false;
Expand Down Expand Up @@ -1582,6 +1582,7 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
struct renesas_usb3_ep *usb3_ep;
int num;
u16 status = 0;
__le16 tx_data;

switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
Expand All @@ -1604,10 +1605,10 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
}

if (!stall) {
status = cpu_to_le16(status);
tx_data = cpu_to_le16(status);
dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n",
usb_req_to_usb3_req(usb3->ep0_req));
usb3_pipe0_internal_xfer(usb3, &status, sizeof(status),
usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data),
usb3_pipe0_get_status_completion);
}

Expand Down Expand Up @@ -1772,7 +1773,7 @@ static bool usb3_std_req_set_sel(struct renesas_usb3 *usb3,
static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3,
struct usb_ctrlrequest *ctrl)
{
if (ctrl->wValue > 0)
if (le16_to_cpu(ctrl->wValue) > 0)
usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
else
usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
Expand Down
Loading

0 comments on commit 3a69c9e

Please sign in to comment.