Skip to content

Commit

Permalink
Merge tag 'usb-5.5-rc2' 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 driver fixes for reported issues for 5.5-rc2

  There's the usual gadget and xhci fixes, as well as some other
  problems that syzbot has been finding during it's fuzzing runs. Full
  details are in the shortlog.

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

* tag 'usb-5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits)
  usb: dwc3: pci: add ID for the Intel Comet Lake -H variant
  xhci: make sure interrupts are restored to correct state
  xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour.
  xhci: Increase STS_HALT timeout in xhci_suspend()
  usb: xhci: only set D3hot for pci device
  xhci: fix USB3 device initiated resume race with roothub autosuspend
  xhci: Fix memory leak in xhci_add_in_port()
  USB: Fix incorrect DMA allocations for local memory pool drivers
  usb: gadget: fix wrong endpoint desc
  usb: dwc3: ep0: Clear started flag on completion
  usb: dwc3: gadget: Clear started flag for non-IOC
  usb: dwc3: gadget: Fix logical condition
  USB: atm: ueagle-atm: add missing endpoint check
  USB: adutux: fix interface sanity check
  USB: idmouse: fix interface sanity checks
  USB: serial: io_edgeport: fix epic endpoint lookup
  usb: mon: Fix a deadlock in usbmon between mmap and read
  usb: common: usb-conn-gpio: Don't log an error on probe deferral
  usb: core: urb: fix URB structure initialization function
  usb: typec: fix use after free in typec_register_port()
  ...
  • Loading branch information
Linus Torvalds committed Dec 14, 2019
2 parents 81d5598 + 3c3caae commit a1b85b3
Show file tree
Hide file tree
Showing 22 changed files with 135 additions and 67 deletions.
18 changes: 12 additions & 6 deletions drivers/usb/atm/ueagle-atm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2124,10 +2124,11 @@ static void uea_intr(struct urb *urb)
/*
* Start the modem : init the data and start kernel thread
*/
static int uea_boot(struct uea_softc *sc)
static int uea_boot(struct uea_softc *sc, struct usb_interface *intf)
{
int ret, size;
struct intr_pkt *intr;
int ret = -ENOMEM;
int size;

uea_enters(INS_TO_USBDEV(sc));

Expand All @@ -2152,6 +2153,11 @@ static int uea_boot(struct uea_softc *sc)
if (UEA_CHIP_VERSION(sc) == ADI930)
load_XILINX_firmware(sc);

if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
ret = -ENODEV;
goto err0;
}

intr = kmalloc(size, GFP_KERNEL);
if (!intr)
goto err0;
Expand All @@ -2163,8 +2169,7 @@ static int uea_boot(struct uea_softc *sc)
usb_fill_int_urb(sc->urb_int, sc->usb_dev,
usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
intr, size, uea_intr, sc,
sc->usb_dev->actconfig->interface[0]->altsetting[0].
endpoint[0].desc.bInterval);
intf->cur_altsetting->endpoint[0].desc.bInterval);

ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
if (ret < 0) {
Expand All @@ -2179,6 +2184,7 @@ static int uea_boot(struct uea_softc *sc)
sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
if (IS_ERR(sc->kthread)) {
uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
ret = PTR_ERR(sc->kthread);
goto err2;
}

Expand All @@ -2193,7 +2199,7 @@ static int uea_boot(struct uea_softc *sc)
kfree(intr);
err0:
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
return ret;
}

/*
Expand Down Expand Up @@ -2548,7 +2554,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
}
}

ret = uea_boot(sc);
ret = uea_boot(sc, intf);
if (ret < 0)
goto error;

Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/common/usb-conn-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ static int usb_conn_probe(struct platform_device *pdev)

info->vbus = devm_regulator_get(dev, "vbus");
if (IS_ERR(info->vbus)) {
dev_err(dev, "failed to get vbus\n");
if (PTR_ERR(info->vbus) != -EPROBE_DEFER)
dev_err(dev, "failed to get vbus\n");
return PTR_ERR(info->vbus);
}

Expand Down
42 changes: 21 additions & 21 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_pio_for_control)
return ret;
if (hcd_uses_dma(hcd)) {
if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret)
return ret;
urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
} else if (hcd_uses_dma(hcd)) {
if (object_is_on_stack(urb->setup_packet)) {
WARN_ONCE(1, "setup packet is on stack\n");
return -EAGAIN;
Expand All @@ -1424,23 +1434,22 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
urb->setup_dma))
return -EAGAIN;
urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
} else if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret)
return ret;
urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
}
}

dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
if (hcd_uses_dma(hcd)) {
if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (ret == 0)
urb->transfer_flags |= URB_MAP_LOCAL;
} else if (hcd_uses_dma(hcd)) {
if (urb->num_sgs) {
int n;

Expand Down Expand Up @@ -1491,15 +1500,6 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
else
urb->transfer_flags |= URB_DMA_MAP_SINGLE;
}
} else if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (ret == 0)
urb->transfer_flags |= URB_MAP_LOCAL;
}
if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
URB_SETUP_MAP_LOCAL)))
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/core/urb.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void usb_init_urb(struct urb *urb)
if (urb) {
memset(urb, 0, sizeof(*urb));
kref_init(&urb->kref);
INIT_LIST_HEAD(&urb->urb_list);
INIT_LIST_HEAD(&urb->anchor_list);
}
}
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee
#define PCI_DEVICE_ID_INTEL_CMLLP 0x02ee
#define PCI_DEVICE_ID_INTEL_CMLH 0x06ee
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
Expand Down Expand Up @@ -308,6 +309,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
(kernel_ulong_t) &dwc3_pci_mrfld_properties, },

{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLLP),
(kernel_ulong_t) &dwc3_pci_intel_properties, },

{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
(kernel_ulong_t) &dwc3_pci_intel_properties, },

Expand Down
8 changes: 8 additions & 0 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,9 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
struct dwc3_ep *dep = dwc->eps[event->endpoint_number];
u8 cmd;

switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
dwc3_ep0_xfer_complete(dwc, event);
Expand All @@ -1129,7 +1132,12 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
case DWC3_DEPEVT_XFERINPROGRESS:
case DWC3_DEPEVT_RXTXFIFOEVT:
case DWC3_DEPEVT_STREAMEVT:
break;
case DWC3_DEPEVT_EPCMDCMPLT:
cmd = DEPEVT_PARAMETER_CMD(event->parameters);

if (cmd == DWC3_DEPCMD_ENDTRANSFER)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
break;
}
}
5 changes: 4 additions & 1 deletion drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2491,7 +2491,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,

req->request.actual = req->request.length - req->remaining;

if (!dwc3_gadget_ep_request_completed(req) &&
if (!dwc3_gadget_ep_request_completed(req) ||
req->num_pending_sgs) {
__dwc3_gadget_kick_transfer(dep);
goto out;
Expand Down Expand Up @@ -2719,6 +2719,9 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
WARN_ON_ONCE(ret);
dep->resource_index = 0;

if (!interrupt)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;

if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
udelay(100);
}
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/gadget/function/f_ecm.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,12 @@ static void ecm_disable(struct usb_function *f)

DBG(cdev, "ecm deactivated\n");

if (ecm->port.in_ep->enabled)
if (ecm->port.in_ep->enabled) {
gether_disconnect(&ecm->port);
} else {
ecm->port.in_ep->desc = NULL;
ecm->port.out_ep->desc = NULL;
}

usb_ep_disable(ecm->notify);
ecm->notify->desc = NULL;
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/gadget/function/f_rndis.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ static void rndis_disable(struct usb_function *f)
gether_disconnect(&rndis->port);

usb_ep_disable(rndis->notify);
rndis->notify->desc = NULL;
}

/*-------------------------------------------------------------------------*/
Expand Down
22 changes: 16 additions & 6 deletions drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,

static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
u32 *status, u32 portsc,
unsigned long flags)
unsigned long *flags)
{
struct xhci_bus_state *bus_state;
struct xhci_hcd *xhci;
Expand Down Expand Up @@ -860,11 +860,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
xhci_test_and_clear_bit(xhci, port, PORT_PLC);
xhci_set_link_state(xhci, port, XDEV_U0);

spin_unlock_irqrestore(&xhci->lock, flags);
spin_unlock_irqrestore(&xhci->lock, *flags);
time_left = wait_for_completion_timeout(
&bus_state->rexit_done[wIndex],
msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS));
spin_lock_irqsave(&xhci->lock, flags);
spin_lock_irqsave(&xhci->lock, *flags);

if (time_left) {
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
Expand Down Expand Up @@ -920,11 +920,13 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
{
struct xhci_bus_state *bus_state;
struct xhci_hcd *xhci;
struct usb_hcd *hcd;
u32 link_state;
u32 portnum;

bus_state = &port->rhub->bus_state;
xhci = hcd_to_xhci(port->rhub->hcd);
hcd = port->rhub->hcd;
link_state = portsc & PORT_PLS_MASK;
portnum = port->hcd_portnum;

Expand Down Expand Up @@ -952,12 +954,20 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
bus_state->suspended_ports &= ~(1 << portnum);
}

/* remote wake resume signaling complete */
if (bus_state->port_remote_wakeup & (1 << portnum) &&
link_state != XDEV_RESUME &&
link_state != XDEV_RECOVERY) {
bus_state->port_remote_wakeup &= ~(1 << portnum);
usb_hcd_end_port_resume(&hcd->self, portnum);
}

xhci_hub_report_usb3_link_state(xhci, status, portsc);
xhci_del_comp_mod_timer(xhci, portsc, portnum);
}

static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
u32 portsc, unsigned long flags)
u32 portsc, unsigned long *flags)
{
struct xhci_bus_state *bus_state;
u32 link_state;
Expand Down Expand Up @@ -1007,7 +1017,7 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
static u32 xhci_get_port_status(struct usb_hcd *hcd,
struct xhci_bus_state *bus_state,
u16 wIndex, u32 raw_port_status,
unsigned long flags)
unsigned long *flags)
__releases(&xhci->lock)
__acquires(&xhci->lock)
{
Expand Down Expand Up @@ -1130,7 +1140,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
}
trace_xhci_get_port_status(wIndex, temp);
status = xhci_get_port_status(hcd, bus_state, wIndex, temp,
flags);
&flags);
if (status == 0xffffffff)
goto error;

Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/host/xhci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1909,13 +1909,17 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->usb3_rhub.num_ports = 0;
xhci->num_active_eps = 0;
kfree(xhci->usb2_rhub.ports);
kfree(xhci->usb2_rhub.psi);
kfree(xhci->usb3_rhub.ports);
kfree(xhci->usb3_rhub.psi);
kfree(xhci->hw_ports);
kfree(xhci->rh_bw);
kfree(xhci->ext_caps);

xhci->usb2_rhub.ports = NULL;
xhci->usb2_rhub.psi = NULL;
xhci->usb3_rhub.ports = NULL;
xhci->usb3_rhub.psi = NULL;
xhci->hw_ports = NULL;
xhci->rh_bw = NULL;
xhci->ext_caps = NULL;
Expand Down
13 changes: 13 additions & 0 deletions drivers/usb/host/xhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,18 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
}
#endif /* CONFIG_PM */

static void xhci_pci_shutdown(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);

xhci_shutdown(hcd);

/* Yet another workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
pci_set_power_state(pdev, PCI_D3hot);
}

/*-------------------------------------------------------------------------*/

/* PCI driver selection metadata; PCI hotplugging uses this */
Expand Down Expand Up @@ -556,6 +568,7 @@ static int __init xhci_pci_init(void)
#ifdef CONFIG_PM
xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
#endif
return pci_register_driver(&xhci_pci_driver);
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -1628,7 +1628,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
if (slot_id && xhci->devs[slot_id])
xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
}

if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
Expand All @@ -1648,6 +1647,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
*/
bus_state->port_remote_wakeup |= 1 << hcd_portnum;
xhci_test_and_clear_bit(xhci, port, PORT_PLC);
usb_hcd_start_port_resume(&hcd->self, hcd_portnum);
xhci_set_link_state(xhci, port, XDEV_U0);
/* Need to wait until the next link state change
* indicates the device is actually in U0.
Expand Down Expand Up @@ -1688,7 +1688,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
if (slot_id && xhci->devs[slot_id])
xhci_ring_device(xhci, slot_id);
if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
xhci_test_and_clear_bit(xhci, port, PORT_PLC);
usb_wakeup_notification(hcd->self.root_hub,
hcd_portnum + 1);
Expand Down Expand Up @@ -2382,7 +2381,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
case COMP_SUCCESS:
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
break;
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
ep_ring->last_td_was_short)
trb_comp_code = COMP_SHORT_PACKET;
else
xhci_warn_ratelimited(xhci,
Expand Down
Loading

0 comments on commit a1b85b3

Please sign in to comment.