static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
+ struct ebc_io *ebc = dep->ebc;
u32 reg;
+ if (ebc) {
+ dwc->is_ebc = 0;
+
+ if (ebc->is_ondemand && ebc->xfer_stop)
+ ebc->xfer_stop();
+ }
+
dwc3_remove_requests(dwc, dep);
+ /* make sure HW endpoint isn't stalled */
+ if (dep->flags & DWC3_EP_STALL)
+ __dwc3_gadget_ep_set_halt(dep, 0, false);
+
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
if (last_one)
break;
}
+
+ if (last_one)
+ break;
} else {
+ unsigned csp = false;
+
dma = req->request.dma;
length = req->request.length;
trbs_left--;
return retval;
}
-static int snd_compr_stop(struct snd_compr_stream *stream)
+int snd_compr_stop(struct snd_compr_stream *stream)
{
- int retval;
+ int retval = 0;
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP)
return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+ if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
if (!retval) {
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- wake_up(&stream->runtime->sleep);
snd_compr_drain_notify(stream);
stream->runtime->total_bytes_available = 0;
stream->runtime->total_bytes_transferred = 0;
}
return retval;
}
+EXPORT_SYMBOL(snd_compr_stop);
+
+static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
+{
+ /*
+ * We are called with lock held. So drop the lock while we wait for
+ * drain complete notfication from the driver
+ *
+ * It is expected that driver will notify the drain completion and then
+ * stream will be moved to SETUP state, even if draining resulted in an
+ * error. We can trigger next track after this.
+ */
+ stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+ mutex_unlock(&stream->device->lock);
+
+ wait_event(stream->runtime->wait, stream->runtime->drain_wake);
+
+ wake_up(&stream->runtime->sleep);
+ mutex_lock(&stream->device->lock);
+
+ return 0;
+}
+ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
+ {
+ int ret;
+
+ /*
+ * We are called with lock held. So drop the lock while we wait for
+ * drain complete notfication from the driver
+ *
+ * It is expected that driver will notify the drain completion and then
+ * stream will be moved to SETUP state, even if draining resulted in an
+ * error. We can trigger next track after this.
+ */
+ stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+ mutex_unlock(&stream->device->lock);
+
+ /* we wait for drain to complete here, drain can return when
+ * interruption occurred, wait returned error or success.
+ * For the first two cases we don't do anything different here and
+ * return after waking up
+ */
+
+ ret = wait_event_interruptible(stream->runtime->sleep,
+ (stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
+ if (ret == -ERESTARTSYS)
+ pr_debug("wait aborted by a signal");
+ else if (ret)
+ pr_debug("wait for drain failed with %d\n", ret);
+
+
+ wake_up(&stream->runtime->sleep);
+ mutex_lock(&stream->device->lock);
+
+ return ret;
+ }
+
static int snd_compr_drain(struct snd_compr_stream *stream)
{
- int retval;
+ int retval = 0;
- if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
- stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP)
return -EPERM;
- stream->runtime->drain_wake = 0;
-
- /* this is hackish for our tree but for now lets carry it while we fix
- * usermode behaviour
- */
- if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
- retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
- else
- return 0;
-
+ retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
if (retval) {
- pr_err("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
+ pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
wake_up(&stream->runtime->sleep);
return retval;
}