* stream once the endpoint is on the HW schedule.
*/
if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
- (ep_state & EP_HALTED))
+ (ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
return;
writel(DB_VALUE(ep_index, stream_id), db_addr);
/* The CPU has better things to do at this point than wait for a
}
}
+void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
+ unsigned int slot_id,
+ unsigned int ep_index)
+{
+ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+}
+
/* Get the right ring for the given slot_id, ep_index and stream_id.
* If the endpoint supports streams, boundary check the URB's stream ID.
* If the endpoint doesn't support streams, return the singular endpoint ring.
return NULL;
}
+static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_virt_ep *ep)
+{
+ /*
+ * As part of low/full-speed endpoint-halt processing
+ * we must clear the TT buffer (USB 2.0 specification 11.17.5).
+ */
+ if (td->urb->dev->tt && !usb_pipeint(td->urb->pipe) &&
+ (td->urb->dev->tt->hub != xhci_to_hcd(xhci)->self.root_hub) &&
+ !(ep->ep_state & EP_CLEARING_TT)) {
+ ep->ep_state |= EP_CLEARING_TT;
+ td->urb->ep->hcpriv = td->urb->dev;
+ if (usb_hub_clear_tt_buffer(td->urb))
+ ep->ep_state &= ~EP_CLEARING_TT;
+ }
+}
+
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
unsigned int stream_id, struct xhci_td *td,
if (reset_type == EP_HARD_RESET) {
ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
+ xhci_clear_hub_tt_buffer(xhci, td, ep);
}
xhci_ring_cmd_db(xhci);
}
}
EXPORT_SYMBOL_GPL(xhci_gen_setup);
+static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
+{
+ struct xhci_hcd *xhci;
+ struct usb_device *udev;
+ unsigned int slot_id;
+ unsigned int ep_index;
+ unsigned long flags;
+
+ xhci = hcd_to_xhci(hcd);
+ udev = (struct usb_device *)ep->hcpriv;
+ slot_id = udev->slot_id;
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT;
+ xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+}
+
static const struct hc_driver xhci_hc_driver = {
.description = "xhci-hcd",
.product_desc = "xHCI Host Controller",
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
.find_raw_port_number = xhci_find_raw_port_number,
+ .clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
};
void xhci_init_driver(struct hc_driver *drv,
#define EP_GETTING_NO_STREAMS (1 << 5)
#define EP_HARD_CLEAR_TOGGLE (1 << 6)
#define EP_SOFT_CLEAR_TOGGLE (1 << 7)
+/* usb_hub_clear_tt_buffer is in progress */
+#define EP_CLEARING_TT (1 << 8)
/* ---- Related to URB cancellation ---- */
struct list_head cancelled_td_list;
/* Watchdog timer for stop endpoint command to cancel URBs */
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
unsigned int ep_index, unsigned int stream_id);
+void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
+ unsigned int slot_id,
+ unsigned int ep_index);
void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
unsigned int count_trbs(u64 addr, u64 len);