mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-29 04:45:05 +00:00
staging: dwc2: always release host channel after dequeueing
Previously, when an active urb was dequeued, its host channel would not always be released. There is some special handling for this in dwc2_hc_chhltd_intr_dma, but when it was the last urb/qtd in its qh, a safeguard in dwc2_hc_n_intr would short-circuit and prevent the regular interrupt handlers from running, without releasing the channel. This is easily triggered when using a 3G modem using the option driver. Opening and closing any ttyUSBx device will eat up a host channel that is forever unusable from that point on. Signed-off-by: Matthijs Kooijman <matthijs@stdin.nl> [paulz@synopsys.com: fixed comment style and added a couple of NULL checks] Signed-off-by: Paul Zimmerman <paulz@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
257f658015
commit
8509f2f43a
@ -708,7 +708,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg,
|
||||
free_qtd = 1;
|
||||
break;
|
||||
case DWC2_HC_XFER_XACT_ERR:
|
||||
if (qtd->error_count >= 3) {
|
||||
if (qtd && qtd->error_count >= 3) {
|
||||
dev_vdbg(hsotg->dev,
|
||||
" Complete URB with transaction error\n");
|
||||
free_qtd = 1;
|
||||
@ -729,7 +729,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg,
|
||||
case DWC2_HC_XFER_PERIODIC_INCOMPLETE:
|
||||
dev_vdbg(hsotg->dev, " Complete URB with I/O error\n");
|
||||
free_qtd = 1;
|
||||
if (qtd->urb) {
|
||||
if (qtd && qtd->urb) {
|
||||
qtd->urb->status = -EIO;
|
||||
dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
|
||||
-EIO);
|
||||
@ -1708,8 +1708,9 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
|
||||
dev_dbg(hsotg->dev,
|
||||
"hcint 0x%08x, hcintmsk 0x%08x, hcsplt 0x%08x,\n",
|
||||
chan->hcint, hcintmsk, hcsplt);
|
||||
dev_dbg(hsotg->dev, "qtd->complete_split %d\n",
|
||||
qtd->complete_split);
|
||||
if (qtd)
|
||||
dev_dbg(hsotg->dev, "qtd->complete_split %d\n",
|
||||
qtd->complete_split);
|
||||
dev_warn(hsotg->dev,
|
||||
"%s: no halt status, channel %d, ignoring interrupt\n",
|
||||
__func__, chnum);
|
||||
@ -1937,7 +1938,31 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
|
||||
chan->hcint = hcint;
|
||||
hcint &= hcintmsk;
|
||||
|
||||
/*
|
||||
* If the channel was halted due to a dequeue, the qtd list might
|
||||
* be empty or at least the first entry will not be the active qtd.
|
||||
* In this case, take a shortcut and just release the channel.
|
||||
*/
|
||||
if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
|
||||
/*
|
||||
* If the channel was halted, this should be the only
|
||||
* interrupt unmasked
|
||||
*/
|
||||
WARN_ON(hcint != HCINTMSK_CHHLTD);
|
||||
if (hsotg->core_params->dma_desc_enable > 0)
|
||||
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
|
||||
chan->halt_status);
|
||||
else
|
||||
dwc2_release_channel(hsotg, chan, NULL,
|
||||
chan->halt_status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (list_empty(&chan->qh->qtd_list)) {
|
||||
/*
|
||||
* TODO: Will this ever happen with the
|
||||
* DWC2_HC_XFER_URB_DEQUEUE handling above?
|
||||
*/
|
||||
dev_dbg(hsotg->dev, "## no QTD queued for channel %d ##\n",
|
||||
chnum);
|
||||
dev_dbg(hsotg->dev,
|
||||
|
Loading…
Reference in New Issue
Block a user