1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-15 04:42:02 +00:00
openmptcprouter/root/target/linux/brcm2708/patches-4.19/0559-usb-xhci-hack-xhci_urb_enqueue-to-support-hid.mousep.patch
Ycarus (Yannick Chabanois) 5f08b288eb Add RPI4 beta support
2019-06-24 19:52:48 +02:00

127 lines
4.1 KiB
Diff

From 1e6abe096683e7520b9692cc490d02bf4d6e705c Mon Sep 17 00:00:00 2001
From: Jonathan Bell <jonathan@raspberrypi.org>
Date: Thu, 30 May 2019 10:38:40 +0100
Subject: [PATCH 559/678] usb: xhci: hack xhci_urb_enqueue to support
hid.mousepoll behaviour
xHCI creates endpoint contexts directly from the device's endpoint
data, so submitting URBs with urb->interval different from the hardware
interval has no effect.
Add an explicit reconfiguration of the endpoint context when requested,
which will happen only when the interval is different from the cached
value. In practice, the reconfiguration only happens on the first URB
submitted for the endpoint.
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
---
drivers/usb/host/xhci.c | 86 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e9edd823fe91..2d73827fe74e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1415,6 +1415,87 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
return ret;
}
+/*
+ * RPI: Fixup endpoint intervals when requested
+ * - Check interval versus the (cached) endpoint context
+ * - set the endpoint interval to the new value
+ * - force an endpoint configure command
+ */
+static void xhci_fixup_interval(struct xhci_hcd *xhci, struct urb *urb,
+ unsigned int slot_id, unsigned int ep_index)
+{
+ struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
+ struct xhci_command *command;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_virt_device *vdev;
+ int xhci_interval, ep_interval;
+ int ret;
+ unsigned long flags;
+ u32 ep_info_tmp;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ vdev = xhci->devs[slot_id];
+ /* Get context-derived endpoint interval */
+ ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
+ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
+ ep_interval = urb->interval * 8;
+
+ if (ep_interval == xhci_interval) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return;
+ }
+
+ xhci_dbg(xhci, "Fixup interval ep_interval=%d xhci_interval=%d\n",
+ ep_interval, xhci_interval);
+ command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
+ if (!command) {
+ /* Failure here is benign, poll at the original rate */
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return;
+ }
+
+ /* xHCI uses exponents for intervals... */
+ xhci_interval = fls(ep_interval) - 1;
+ xhci_interval = clamp_val(xhci_interval, 3, 10);
+ ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
+ ep_info_tmp &= ~EP_INTERVAL(255);
+ ep_info_tmp |= EP_INTERVAL(xhci_interval);
+
+ /* Keep the endpoint context up-to-date while issuing the command. */
+ xhci_endpoint_copy(xhci, vdev->in_ctx,
+ vdev->out_ctx, ep_index);
+ ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
+
+ /*
+ * We need to drop the lock, so take an explicit copy
+ * of the ep context.
+ */
+ xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
+
+ ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
+ if (!ctrl_ctx) {
+ xhci_warn(xhci,
+ "%s: Could not get input context, bad type.\n",
+ __func__);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_free_command(xhci, command);
+ return;
+ }
+ ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
+ ctrl_ctx->drop_flags = 0;
+
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ ret = xhci_configure_endpoint(xhci, urb->dev, command,
+ false, false);
+ if (ret)
+ xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
+ __func__, ret);
+ xhci_free_command(xhci, command);
+}
+
/*
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
@@ -1479,6 +1560,11 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
}
}
+ if (usb_endpoint_xfer_int(&urb->ep->desc) &&
+ (urb->dev->speed == USB_SPEED_FULL ||
+ urb->dev->speed == USB_SPEED_LOW))
+ xhci_fixup_interval(xhci, urb, slot_id, ep_index);
+
spin_lock_irqsave(&xhci->lock, flags);
if (xhci->xhc_state & XHCI_STATE_DYING) {
--
2.19.1