Commit a9f6b6b8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-4.11-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 4.11-rc5.

  The usual xhci fixes are here, as well as a fix for yet-another-bug-
  found-by-KASAN, those developers are doing great stuff here.

  And there's a phy build warning fix that showed up in 4.11-rc1.

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

* tag 'usb-4.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
  xhci: Manually give back cancelled URB if we can't queue it for cancel
  xhci: Set URB actual length for stopped control transfers
  xhci: plat: Register shutdown for xhci_plat
  USB: fix linked-list corruption in rh_call_control()
parents b3ff4fac a7f12a21
...@@ -520,8 +520,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) ...@@ -520,8 +520,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
*/ */
tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength); tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
tbuf = kzalloc(tbuf_size, GFP_KERNEL); tbuf = kzalloc(tbuf_size, GFP_KERNEL);
if (!tbuf) if (!tbuf) {
return -ENOMEM; status = -ENOMEM;
goto err_alloc;
}
bufp = tbuf; bufp = tbuf;
...@@ -734,6 +736,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) ...@@ -734,6 +736,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
} }
kfree(tbuf); kfree(tbuf);
err_alloc:
/* any errors get returned through the urb completion */ /* any errors get returned through the urb completion */
spin_lock_irq(&hcd_root_hub_lock); spin_lock_irq(&hcd_root_hub_lock);
......
...@@ -344,6 +344,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); ...@@ -344,6 +344,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
static struct platform_driver usb_xhci_driver = { static struct platform_driver usb_xhci_driver = {
.probe = xhci_plat_probe, .probe = xhci_plat_probe,
.remove = xhci_plat_remove, .remove = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = { .driver = {
.name = "xhci-hcd", .name = "xhci-hcd",
.pm = DEV_PM_OPS, .pm = DEV_PM_OPS,
......
...@@ -1989,6 +1989,9 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -1989,6 +1989,9 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
case TRB_NORMAL: case TRB_NORMAL:
td->urb->actual_length = requested - remaining; td->urb->actual_length = requested - remaining;
goto finish_td; goto finish_td;
case TRB_STATUS:
td->urb->actual_length = requested;
goto finish_td;
default: default:
xhci_warn(xhci, "WARN: unexpected TRB Type %d\n", xhci_warn(xhci, "WARN: unexpected TRB Type %d\n",
trb_type); trb_type);
......
...@@ -1477,6 +1477,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1477,6 +1477,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
struct xhci_ring *ep_ring; struct xhci_ring *ep_ring;
struct xhci_virt_ep *ep; struct xhci_virt_ep *ep;
struct xhci_command *command; struct xhci_command *command;
struct xhci_virt_device *vdev;
xhci = hcd_to_xhci(hcd); xhci = hcd_to_xhci(hcd);
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
...@@ -1485,15 +1486,27 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1485,15 +1486,27 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
/* Make sure the URB hasn't completed or been unlinked already */ /* Make sure the URB hasn't completed or been unlinked already */
ret = usb_hcd_check_unlink_urb(hcd, urb, status); ret = usb_hcd_check_unlink_urb(hcd, urb, status);
if (ret || !urb->hcpriv) if (ret)
goto done; goto done;
/* give back URB now if we can't queue it for cancel */
vdev = xhci->devs[urb->dev->slot_id];
urb_priv = urb->hcpriv;
if (!vdev || !urb_priv)
goto err_giveback;
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
ep = &vdev->eps[ep_index];
ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
if (!ep || !ep_ring)
goto err_giveback;
temp = readl(&xhci->op_regs->status); temp = readl(&xhci->op_regs->status);
if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"HW died, freeing TD."); "HW died, freeing TD.");
urb_priv = urb->hcpriv;
for (i = urb_priv->num_tds_done; for (i = urb_priv->num_tds_done;
i < urb_priv->num_tds && xhci->devs[urb->dev->slot_id]; i < urb_priv->num_tds;
i++) { i++) {
td = &urb_priv->td[i]; td = &urb_priv->td[i];
if (!list_empty(&td->td_list)) if (!list_empty(&td->td_list))
...@@ -1501,23 +1514,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1501,23 +1514,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
if (!list_empty(&td->cancelled_td_list)) if (!list_empty(&td->cancelled_td_list))
list_del_init(&td->cancelled_td_list); list_del_init(&td->cancelled_td_list);
} }
goto err_giveback;
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&xhci->lock, flags);
usb_hcd_giveback_urb(hcd, urb, -ESHUTDOWN);
xhci_urb_free_priv(urb_priv);
return ret;
}
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
if (!ep_ring) {
ret = -EINVAL;
goto done;
} }
urb_priv = urb->hcpriv;
i = urb_priv->num_tds_done; i = urb_priv->num_tds_done;
if (i < urb_priv->num_tds) if (i < urb_priv->num_tds)
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
...@@ -1554,6 +1553,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1554,6 +1553,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
done: done:
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
return ret; return ret;
err_giveback:
if (urb_priv)
xhci_urb_free_priv(urb_priv);
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&xhci->lock, flags);
usb_hcd_giveback_urb(hcd, urb, -ESHUTDOWN);
return ret;
} }
/* Drop an endpoint from a new bandwidth configuration for this device. /* Drop an endpoint from a new bandwidth configuration for this device.
......
...@@ -136,7 +136,7 @@ static int isp1301_remove(struct i2c_client *client) ...@@ -136,7 +136,7 @@ static int isp1301_remove(struct i2c_client *client)
static struct i2c_driver isp1301_driver = { static struct i2c_driver isp1301_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = of_match_ptr(isp1301_of_match), .of_match_table = isp1301_of_match,
}, },
.probe = isp1301_probe, .probe = isp1301_probe,
.remove = isp1301_remove, .remove = isp1301_remove,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment