Skip to content

Commit ef513be

Browse files
Jim Lingregkh
authored andcommitted
usb: xhci: Add Clear_TT_Buffer
USB 2.0 specification chapter 11.17.5 says "as part of endpoint halt processing for full-/low-speed endpoints connected via a TT, the host software must use the Clear_TT_Buffer request to the TT to ensure that the buffer is not in the busy state". In our case, a full-speed speaker (ConferenceCam) is behind a high- speed hub (ConferenceCam Connect), sometimes once we get STALL on a request we may continue to get STALL with the folllowing requests, like Set_Interface. Here we invoke usb_hub_clear_tt_buffer() to send Clear_TT_Buffer request to the hub of the device for the following Set_Interface requests to the device to get ACK successfully. Signed-off-by: Jim Lin <[email protected]> Acked-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4998f1e commit ef513be

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
399399
* stream once the endpoint is on the HW schedule.
400400
*/
401401
if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
402-
(ep_state & EP_HALTED))
402+
(ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
403403
return;
404404
writel(DB_VALUE(ep_index, stream_id), db_addr);
405405
/* The CPU has better things to do at this point than wait for a
@@ -433,6 +433,13 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
433433
}
434434
}
435435

436+
void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
437+
unsigned int slot_id,
438+
unsigned int ep_index)
439+
{
440+
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
441+
}
442+
436443
/* Get the right ring for the given slot_id, ep_index and stream_id.
437444
* If the endpoint supports streams, boundary check the URB's stream ID.
438445
* If the endpoint doesn't support streams, return the singular endpoint ring.
@@ -1794,6 +1801,23 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci,
17941801
return NULL;
17951802
}
17961803

1804+
static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td,
1805+
struct xhci_virt_ep *ep)
1806+
{
1807+
/*
1808+
* As part of low/full-speed endpoint-halt processing
1809+
* we must clear the TT buffer (USB 2.0 specification 11.17.5).
1810+
*/
1811+
if (td->urb->dev->tt && !usb_pipeint(td->urb->pipe) &&
1812+
(td->urb->dev->tt->hub != xhci_to_hcd(xhci)->self.root_hub) &&
1813+
!(ep->ep_state & EP_CLEARING_TT)) {
1814+
ep->ep_state |= EP_CLEARING_TT;
1815+
td->urb->ep->hcpriv = td->urb->dev;
1816+
if (usb_hub_clear_tt_buffer(td->urb))
1817+
ep->ep_state &= ~EP_CLEARING_TT;
1818+
}
1819+
}
1820+
17971821
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
17981822
unsigned int slot_id, unsigned int ep_index,
17991823
unsigned int stream_id, struct xhci_td *td,
@@ -1812,6 +1836,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
18121836
if (reset_type == EP_HARD_RESET) {
18131837
ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
18141838
xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
1839+
xhci_clear_hub_tt_buffer(xhci, td, ep);
18151840
}
18161841
xhci_ring_cmd_db(xhci);
18171842
}

drivers/usb/host/xhci.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5163,6 +5163,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
51635163
}
51645164
EXPORT_SYMBOL_GPL(xhci_gen_setup);
51655165

5166+
static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
5167+
struct usb_host_endpoint *ep)
5168+
{
5169+
struct xhci_hcd *xhci;
5170+
struct usb_device *udev;
5171+
unsigned int slot_id;
5172+
unsigned int ep_index;
5173+
unsigned long flags;
5174+
5175+
xhci = hcd_to_xhci(hcd);
5176+
udev = (struct usb_device *)ep->hcpriv;
5177+
slot_id = udev->slot_id;
5178+
ep_index = xhci_get_endpoint_index(&ep->desc);
5179+
5180+
spin_lock_irqsave(&xhci->lock, flags);
5181+
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT;
5182+
xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
5183+
spin_unlock_irqrestore(&xhci->lock, flags);
5184+
}
5185+
51665186
static const struct hc_driver xhci_hc_driver = {
51675187
.description = "xhci-hcd",
51685188
.product_desc = "xHCI Host Controller",
@@ -5224,6 +5244,7 @@ static const struct hc_driver xhci_hc_driver = {
52245244
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
52255245
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
52265246
.find_raw_port_number = xhci_find_raw_port_number,
5247+
.clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
52275248
};
52285249

52295250
void xhci_init_driver(struct hc_driver *drv,

drivers/usb/host/xhci.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,8 @@ struct xhci_virt_ep {
936936
#define EP_GETTING_NO_STREAMS (1 << 5)
937937
#define EP_HARD_CLEAR_TOGGLE (1 << 6)
938938
#define EP_SOFT_CLEAR_TOGGLE (1 << 7)
939+
/* usb_hub_clear_tt_buffer is in progress */
940+
#define EP_CLEARING_TT (1 << 8)
939941
/* ---- Related to URB cancellation ---- */
940942
struct list_head cancelled_td_list;
941943
/* Watchdog timer for stop endpoint command to cancel URBs */
@@ -2102,6 +2104,9 @@ void xhci_handle_command_timeout(struct work_struct *work);
21022104

21032105
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
21042106
unsigned int ep_index, unsigned int stream_id);
2107+
void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
2108+
unsigned int slot_id,
2109+
unsigned int ep_index);
21052110
void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
21062111
void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
21072112
unsigned int count_trbs(u64 addr, u64 len);

0 commit comments

Comments
 (0)