* pointer command pending because the device can choose to start any
* stream once the endpoint is on the HW schedule.
*/
+#ifdef CONFIG_AMLOGIC_USB
+ if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING)
+ || (ep_state & EP_HALTED))
+#else
if ((ep_state & EP_HALT_PENDING) || (ep_state & SET_DEQ_PENDING) ||
(ep_state & EP_HALTED))
+#endif
return;
writel(DB_VALUE(ep_index, stream_id), db_addr);
/* The CPU has better things to do at this point than wait for a
static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
struct xhci_virt_ep *ep)
{
+#ifdef CONFIG_AMLOGIC_USB
+ ep->ep_state &= ~EP_STOP_CMD_PENDING;
+ /* Can't del_timer_sync in interrupt */
+ del_timer(&ep->stop_cmd_timer);
+#else
ep->ep_state &= ~EP_HALT_PENDING;
- /* Can't del_timer_sync in interrupt, so we attempt to cancel. If the
+ /* Can't del_timer_sync in interrupt, so we attempt to cancel. If the
* timer is running on another CPU, we don't decrement stop_cmds_pending
* (since we didn't successfully stop the watchdog timer).
*/
if (del_timer(&ep->stop_cmd_timer))
ep->stop_cmds_pending--;
+#endif
}
/* Must be called with xhci->lock held in interrupt context */
* simple flag to say whether there is a pending stop endpoint command for a
* particular endpoint.
*
+#ifdef CONFIG_AMLOGIC_USB
+ * Instead we use a combination of that flag and checking if a new timer is
+ * pending.
+#else
* Instead we use a combination of that flag and a counter for the number of
* pending stop endpoint commands. If the timer is the tail end of the last
* stop endpoint command, and the endpoint's command is still pending, we assume
* the host is dying.
+#endif
*/
void xhci_stop_endpoint_command_watchdog(unsigned long arg)
{
spin_lock_irqsave(&xhci->lock, flags);
+#ifdef CONFIG_AMLOGIC_USB
+ /* bail out if cmd completed but raced with stop ep watchdog timer.*/
+ if (!(ep->ep_state & EP_STOP_CMD_PENDING) ||
+ timer_pending(&ep->stop_cmd_timer)) {
+#else
ep->stop_cmds_pending--;
if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Stop EP timer ran, but no command pending, "
"exiting.");
+#endif
spin_unlock_irqrestore(&xhci->lock, flags);
+#ifdef CONFIG_AMLOGIC_USB
+ xhci_dbg(xhci, "Stop EP timer raced with cmd completion, exit");
+#endif
return;
}
/* Oops, HC is dead or dying or at least not responding to the stop
* endpoint command.
*/
+
xhci->xhc_state |= XHCI_STATE_DYING;
+#ifdef CONFIG_AMLOGIC_USB
+ ep->ep_state &= ~EP_STOP_CMD_PENDING;
+#endif
+
/* Disable interrupts from the host controller and start halting it */
xhci_quiesce(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
/* Queue a stop endpoint command, but only if this is
* the first cancellation to be handled.
*/
+#ifdef CONFIG_AMLOGIC_USB
+ if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
+#else
if (!(ep->ep_state & EP_HALT_PENDING)) {
+#endif
command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
if (!command) {
ret = -ENOMEM;
goto done;
}
+#ifdef CONFIG_AMLOGIC_USB
+ ep->ep_state |= EP_STOP_CMD_PENDING;
+#else
ep->ep_state |= EP_HALT_PENDING;
ep->stop_cmds_pending++;
+#endif
ep->stop_cmd_timer.expires = jiffies +
XHCI_STOP_EP_CMD_TIMEOUT * HZ;
add_timer(&ep->stop_cmd_timer);
/* Stop any wayward timer functions (which may grab the lock) */
for (i = 0; i < 31; ++i) {
+#ifdef CONFIG_AMLOGIC_USB
+ virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
+#else
virt_dev->eps[i].ep_state &= ~EP_HALT_PENDING;
+#endif
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
unsigned int ep_state;
#define SET_DEQ_PENDING (1 << 0)
#define EP_HALTED (1 << 1) /* For stall handling */
-#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */
+#ifdef CONFIG_AMLOGIC_USB
+#define EP_STOP_CMD_PENDING (1 << 2) /* For URB cancellation */
+#else
+#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */
+#endif
/* Transitioning the endpoint to using streams, don't enqueue URBs */
#define EP_GETTING_STREAMS (1 << 3)
#define EP_HAS_STREAMS (1 << 4)
unsigned int stopped_stream;
/* Watchdog timer for stop endpoint command to cancel URBs */
struct timer_list stop_cmd_timer;
- int stop_cmds_pending;
+#ifndef CONFIG_AMLOGIC_USB
+ int stop_cmds_pending;
+#endif
struct xhci_hcd *xhci;
/* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue
* command. We'll need to update the ring's dequeue segment and dequeue