USB fixes for 4.11-rc5
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWN/NGw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymNQQCeNiONvY70Y99hWFDX+PL896fV1rYAoNchYIZY V4NYSVr43W4uk7jrUQD5 =NUT1 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
a9f6b6b8cd
@ -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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
||||||
|
Loading…
Reference in New Issue
Block a user