Skip to content

Commit

Permalink
Merge tag 'usb-3.4-rc4' 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 Kroah-Hartman:
 "Here are a number of tiny USB fixes for 3.4-rc4.

  Most of them are in the USB gadget area, but a few other minor USB
  driver and core fixes are here as well.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'usb-3.4-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (36 commits)
  USB: serial: cp210x: Fixed usb_control_msg timeout values
  USB: ehci-tegra: don't call set_irq_flags(IRQF_VALID)
  USB: yurex: Fix missing URB_NO_TRANSFER_DMA_MAP flag in urb
  USB: yurex: Remove allocation of coherent buffer for setup-packet buffer
  drivers/usb/misc/usbtest.c: add kfrees
  USB: ehci-fsl: Fix kernel crash on mpc5121e
  uwb: fix error handling
  uwb: fix use of del_timer_sync() in interrupt
  EHCI: always clear the STS_FLR status bit
  EHCI: fix criterion for resuming the root hub
  USB: sierra: avoid QMI/wwan interface on MC77xx
  usb: usbtest: avoid integer overflow in alloc_sglist()
  usb: usbtest: avoid integer overflow in test_ctrl_queue()
  USB: fix deadlock in bConfigurationValue attribute method
  usb: gadget: eliminate NULL pointer dereference (bugfix)
  usb: gadget: uvc: Remove non-required locking from 'uvc_queue_next_buffer' routine
  usb: gadget: rndis: fix Missing req->context assignment
  usb: musb: omap: fix the error check for pm_runtime_get_sync
  usb: gadget: udc-core: fix asymmetric calls in remove_driver
  usb: musb: omap: fix crash when musb glue (omap) gets initialized
  ...
  • Loading branch information
Linus Torvalds committed Apr 20, 2012
2 parents c1acb0b + 2d5733f commit 1cd653a
Show file tree
Hide file tree
Showing 24 changed files with 151 additions and 76 deletions.
3 changes: 0 additions & 3 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,6 @@ void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *udev = *pdev;
int i;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);

/* mark the device as inactive, so any further urb submissions for
* this device (and any of its children) will fail immediately.
Expand All @@ -1690,9 +1689,7 @@ void usb_disconnect(struct usb_device **pdev)
* so that the hardware is now fully quiesced.
*/
dev_dbg (&udev->dev, "unregistering device\n");
mutex_lock(hcd->bandwidth_mutex);
usb_disable_device(udev, 0);
mutex_unlock(hcd->bandwidth_mutex);
usb_hcd_synchronize_unlinks(udev);

usb_remove_ep_devs(&udev->ep0);
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1136,8 +1136,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
* Deallocates hcd/hardware state for the endpoints (nuking all or most
* pending urbs) and usbcore state for the interfaces, so that usbcore
* must usb_set_configuration() before any interfaces could be used.
*
* Must be called with hcd->bandwidth_mutex held.
*/
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
Expand Down Expand Up @@ -1190,7 +1188,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
}
/* Remove endpoints from the host controller internal state */
mutex_lock(hcd->bandwidth_mutex);
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
mutex_unlock(hcd->bandwidth_mutex);
/* Second pass: remove endpoint pointers */
}
for (i = skip_ep0; i < 16; ++i) {
Expand Down Expand Up @@ -1750,7 +1750,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
mutex_lock(hcd->bandwidth_mutex);
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device(dev, 1); /* Skip ep0 */

Expand All @@ -1763,6 +1762,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
* host controller will not allow submissions to dropped endpoints. If
* this call fails, the device state is unchanged.
*/
mutex_lock(hcd->bandwidth_mutex);
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) {
mutex_unlock(hcd->bandwidth_mutex);
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/dwc3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,11 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)

for (i = 0; i < dwc->num_event_buffers; i++) {
evt = dwc->ev_buffs[i];
if (evt) {
if (evt)
dwc3_free_one_event_buffer(dwc, evt);
dwc->ev_buffs[i] = NULL;
}
}

kfree(dwc->ev_buffs);
}

/**
Expand Down
12 changes: 10 additions & 2 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,

dwc->test_mode_nr = wIndex >> 8;
dwc->test_mode = true;
break;
default:
return -EINVAL;
}
break;

Expand Down Expand Up @@ -559,15 +562,20 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
length = trb->size & DWC3_TRB_SIZE_MASK;

if (dwc->ep0_bounced) {
unsigned transfer_size = ur->length;
unsigned maxp = ep0->endpoint.maxpacket;

transfer_size += (maxp - (transfer_size % maxp));
transferred = min_t(u32, ur->length,
ep0->endpoint.maxpacket - length);
transfer_size - length);
memcpy(ur->buf, dwc->ep0_bounce, transferred);
dwc->ep0_bounced = false;
} else {
transferred = ur->length - length;
ur->actual += transferred;
}

ur->actual += transferred;

if ((epnum & 1) && ur->actual < ur->length) {
/* for some reason we did not get everything out */

Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/gadget/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
if (code == FUNCTIONFS_INTERFACE_REVMAP) {
struct ffs_function *func = ffs->func;
ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
} else if (gadget->ops->ioctl) {
} else if (gadget && gadget->ops->ioctl) {
ret = gadget->ops->ioctl(gadget, code, value);
} else {
ret = -ENOTTY;
Expand Down Expand Up @@ -1382,6 +1382,7 @@ static void functionfs_unbind(struct ffs_data *ffs)
ffs->ep0req = NULL;
ffs->gadget = NULL;
ffs_data_put(ffs);
clear_bit(FFS_FL_BOUND, &ffs->flags);
}
}

Expand Down
1 change: 1 addition & 0 deletions drivers/usb/gadget/f_rndis.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
if (buf) {
memcpy(req->buf, buf, n);
req->complete = rndis_response_complete;
req->context = rndis;
rndis_free_response(rndis->config, buf);
value = n;
}
Expand Down
25 changes: 16 additions & 9 deletions drivers/usb/gadget/fsl_udc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
: (1 << (ep_index(ep)));

/* check if the pipe is empty */
if (!(list_empty(&ep->queue))) {
if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) {
/* Add td to the end */
struct fsl_req *lastreq;
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
Expand Down Expand Up @@ -918,10 +918,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -ENOMEM;
}

/* Update ep0 state */
if ((ep_index(ep) == 0))
udc->ep0_state = DATA_STATE_XMIT;

/* irq handler advances the queue */
if (req != NULL)
list_add_tail(&req->queue, &ep->queue);
Expand Down Expand Up @@ -1279,7 +1275,8 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
udc->ep0_dir = USB_DIR_OUT;

ep = &udc->eps[0];
udc->ep0_state = WAIT_FOR_OUT_STATUS;
if (udc->ep0_state != DATA_STATE_XMIT)
udc->ep0_state = WAIT_FOR_OUT_STATUS;

req->ep = ep;
req->req.length = 0;
Expand Down Expand Up @@ -1384,6 +1381,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,

list_add_tail(&req->queue, &ep->queue);
udc->ep0_state = DATA_STATE_XMIT;
if (ep0_prime_status(udc, EP_DIR_OUT))
ep0stall(udc);

return;
stall:
ep0stall(udc);
Expand Down Expand Up @@ -1492,6 +1492,14 @@ static void setup_received_irq(struct fsl_udc *udc,
spin_lock(&udc->lock);
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
? DATA_STATE_XMIT : DATA_STATE_RECV;
/*
* If the data stage is IN, send status prime immediately.
* See 2.0 Spec chapter 8.5.3.3 for detail.
*/
if (udc->ep0_state == DATA_STATE_XMIT)
if (ep0_prime_status(udc, EP_DIR_OUT))
ep0stall(udc);

} else {
/* No data phase, IN status from gadget */
udc->ep0_dir = USB_DIR_IN;
Expand Down Expand Up @@ -1520,9 +1528,8 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,

switch (udc->ep0_state) {
case DATA_STATE_XMIT:
/* receive status phase */
if (ep0_prime_status(udc, EP_DIR_OUT))
ep0stall(udc);
/* already primed at setup_received_irq */
udc->ep0_state = WAIT_FOR_OUT_STATUS;
break;
case DATA_STATE_RECV:
/* send status phase */
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/gadget/g_ffs.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ static struct usb_composite_driver gfs_driver = {
static struct ffs_data *gfs_ffs_data;
static unsigned long gfs_registered;

static int gfs_init(void)
static int __init gfs_init(void)
{
ENTER();

return functionfs_init();
}
module_init(gfs_init);

static void gfs_exit(void)
static void __exit gfs_exit(void)
{
ENTER();

Expand Down
17 changes: 10 additions & 7 deletions drivers/usb/gadget/s3c-hsotg.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
/* currently we allocate TX FIFOs for all possible endpoints,
* and assume that they are all the same size. */

for (ep = 0; ep <= 15; ep++) {
for (ep = 1; ep <= 15; ep++) {
val = addr;
val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
addr += size;
Expand Down Expand Up @@ -741,7 +741,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
/* write size / packets */
writel(epsize, hsotg->regs + epsize_reg);

if (using_dma(hsotg)) {
if (using_dma(hsotg) && !continuing) {
unsigned int dma_reg;

/* write DMA address to control register, buffer already
Expand Down Expand Up @@ -1696,10 +1696,12 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
reg |= mpsval;
writel(reg, regs + S3C_DIEPCTL(ep));

reg = readl(regs + S3C_DOEPCTL(ep));
reg &= ~S3C_DxEPCTL_MPS_MASK;
reg |= mpsval;
writel(reg, regs + S3C_DOEPCTL(ep));
if (ep) {
reg = readl(regs + S3C_DOEPCTL(ep));
reg &= ~S3C_DxEPCTL_MPS_MASK;
reg |= mpsval;
writel(reg, regs + S3C_DOEPCTL(ep));
}

return;

Expand Down Expand Up @@ -1919,7 +1921,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
ints & S3C_DIEPMSK_TxFIFOEmpty) {
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
s3c_hsotg_trytx(hsotg, hs_ep);
if (!using_dma(hsotg))
s3c_hsotg_trytx(hsotg, hs_ep);
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/gadget/udc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
if (udc_is_newstyle(udc)) {
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
usb_gadget_disconnect(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
} else {
usb_gadget_stop(udc->gadget, udc->driver);
}
Expand Down Expand Up @@ -411,8 +411,12 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);

if (sysfs_streq(buf, "connect")) {
if (udc_is_newstyle(udc))
usb_gadget_udc_start(udc->gadget, udc->driver);
usb_gadget_connect(udc->gadget);
} else if (sysfs_streq(buf, "disconnect")) {
if (udc_is_newstyle(udc))
usb_gadget_udc_stop(udc->gadget, udc->driver);
usb_gadget_disconnect(udc->gadget);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
Expand Down
4 changes: 1 addition & 3 deletions drivers/usb/gadget/uvc_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,11 +543,11 @@ static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
return ret;
}

/* called with queue->irqlock held.. */
static struct uvc_buffer *
uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
unsigned long flags;

if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
Expand All @@ -556,14 +556,12 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
return buf;
}

spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
nextbuf = NULL;
spin_unlock_irqrestore(&queue->irqlock, flags);

buf->buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.timestamp);
Expand Down
7 changes: 6 additions & 1 deletion drivers/usb/host/ehci-fsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
u32 portsc;
struct usb_hcd *hcd = ehci_to_hcd(ehci);
void __iomem *non_ehci = hcd->regs;
struct fsl_usb2_platform_data *pdata;

pdata = hcd->self.controller->platform_data;

portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
Expand All @@ -234,7 +237,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
/* fall through */
case FSL_USB2_PHY_UTMI:
/* enable UTMI PHY */
setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
if (pdata->have_sysif_regs)
setbits32(non_ehci + FSL_SOC_USB_CTRL,
CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
Expand Down
9 changes: 7 additions & 2 deletions drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,8 +858,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
goto dead;
}

/*
* We don't use STS_FLR, but some controllers don't like it to
* remain on, so mask it out along with the other status bits.
*/
masked_status = status & (INTR_MASK | STS_FLR);

/* Shared IRQ? */
masked_status = status & INTR_MASK;
if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
spin_unlock(&ehci->lock);
return IRQ_NONE;
Expand Down Expand Up @@ -910,7 +915,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
pcd_status = status;

/* resume root hub? */
if (!(cmd & CMD_RUN))
if (ehci->rh_state == EHCI_RH_SUSPENDED)
usb_hcd_resume_root_hub(hcd);

/* get per-port change detect bits */
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/host/ehci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
err = -ENODEV;
goto fail;
}
set_irq_flags(irq, IRQF_VALID);

#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
Expand Down
9 changes: 6 additions & 3 deletions drivers/usb/misc/usbtest.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ alloc_sglist(int nents, int max, int vary)
unsigned i;
unsigned size = max;

sg = kmalloc(nents * sizeof *sg, GFP_KERNEL);
sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
if (!sg)
return NULL;
sg_init_table(sg, nents);
Expand Down Expand Up @@ -904,6 +904,9 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
struct ctrl_ctx context;
int i;

if (param->sglen == 0 || param->iterations > UINT_MAX / param->sglen)
return -EOPNOTSUPP;

spin_lock_init(&context.lock);
context.dev = dev;
init_completion(&context.complete);
Expand Down Expand Up @@ -1981,8 +1984,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)

/* queued control messaging */
case 10:
if (param->sglen == 0)
break;
retval = 0;
dev_info(&intf->dev,
"TEST 10: queue %d control calls, %d times\n",
Expand Down Expand Up @@ -2276,6 +2277,8 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (status < 0) {
WARNING(dev, "couldn't get endpoints, %d\n",
status);
kfree(dev->buf);
kfree(dev);
return status;
}
/* may find bulk or ISO pipes */
Expand Down
Loading

0 comments on commit 1cd653a

Please sign in to comment.