Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9f6b6b8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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 = kzalloc(tbuf_size, GFP_KERNEL);
	if (!tbuf)
		return -ENOMEM;
	if (!tbuf) {
		status = -ENOMEM;
		goto err_alloc;
	}

	bufp = tbuf;

@@ -734,6 +736,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
	}

	kfree(tbuf);
 err_alloc:

	/* any errors get returned through the urb completion */
	spin_lock_irq(&hcd_root_hub_lock);
+1 −0
Original line number Diff line number Diff line
@@ -344,6 +344,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
static struct platform_driver usb_xhci_driver = {
	.probe	= xhci_plat_probe,
	.remove	= xhci_plat_remove,
	.shutdown	= usb_hcd_platform_shutdown,
	.driver	= {
		.name = "xhci-hcd",
		.pm = DEV_PM_OPS,
+3 −0
Original line number Diff line number Diff line
@@ -1989,6 +1989,9 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
		case TRB_NORMAL:
			td->urb->actual_length = requested - remaining;
			goto finish_td;
		case TRB_STATUS:
			td->urb->actual_length = requested;
			goto finish_td;
		default:
			xhci_warn(xhci, "WARN: unexpected TRB Type %d\n",
				  trb_type);
+25 −18
Original line number Diff line number Diff line
@@ -1477,6 +1477,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
	struct xhci_ring *ep_ring;
	struct xhci_virt_ep *ep;
	struct xhci_command *command;
	struct xhci_virt_device *vdev;

	xhci = hcd_to_xhci(hcd);
	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 */
	ret = usb_hcd_check_unlink_urb(hcd, urb, status);
	if (ret || !urb->hcpriv)
	if (ret)
		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);
	if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
				"HW died, freeing TD.");
		urb_priv = urb->hcpriv;
		for (i = urb_priv->num_tds_done;
		     i < urb_priv->num_tds && xhci->devs[urb->dev->slot_id];
		     i < urb_priv->num_tds;
		     i++) {
			td = &urb_priv->td[i];
			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))
				list_del_init(&td->cancelled_td_list);
		}

		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;
		goto err_giveback;
	}

	urb_priv = urb->hcpriv;
	i = urb_priv->num_tds_done;
	if (i < urb_priv->num_tds)
		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:
	spin_unlock_irqrestore(&xhci->lock, flags);
	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.
+1 −1
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ static int isp1301_remove(struct i2c_client *client)
static struct i2c_driver isp1301_driver = {
	.driver = {
		.name = DRV_NAME,
		.of_match_table = of_match_ptr(isp1301_of_match),
		.of_match_table = isp1301_of_match,
	},
	.probe = isp1301_probe,
	.remove = isp1301_remove,