18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * hcd_ddma.c - DesignWare HS OTG Controller descriptor DMA routines
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2004-2013 Synopsys, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
88c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
98c2ecf20Sopenharmony_ci * are met:
108c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
118c2ecf20Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
128c2ecf20Sopenharmony_ci *    without modification.
138c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
148c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
158c2ecf20Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
168c2ecf20Sopenharmony_ci * 3. The names of the above-listed copyright holders may not be used
178c2ecf20Sopenharmony_ci *    to endorse or promote products derived from this software without
188c2ecf20Sopenharmony_ci *    specific prior written permission.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the
218c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software
228c2ecf20Sopenharmony_ci * Foundation; either version 2 of the License, or (at your option) any
238c2ecf20Sopenharmony_ci * later version.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
268c2ecf20Sopenharmony_ci * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
278c2ecf20Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
288c2ecf20Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
298c2ecf20Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
308c2ecf20Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
318c2ecf20Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
328c2ecf20Sopenharmony_ci * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
338c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
348c2ecf20Sopenharmony_ci * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
358c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * This file contains the Descriptor DMA implementation for Host mode
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci#include <linux/kernel.h>
428c2ecf20Sopenharmony_ci#include <linux/module.h>
438c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
448c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
458c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
468c2ecf20Sopenharmony_ci#include <linux/io.h>
478c2ecf20Sopenharmony_ci#include <linux/slab.h>
488c2ecf20Sopenharmony_ci#include <linux/usb.h>
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include <linux/usb/hcd.h>
518c2ecf20Sopenharmony_ci#include <linux/usb/ch11.h>
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#include "core.h"
548c2ecf20Sopenharmony_ci#include "hcd.h"
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic u16 dwc2_frame_list_idx(u16 frame)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	return frame & (FRLISTEN_64_SIZE - 1);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic u16 dwc2_desclist_idx_inc(u16 idx, u16 inc, u8 speed)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	return (idx + inc) &
648c2ecf20Sopenharmony_ci		((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC :
658c2ecf20Sopenharmony_ci		  MAX_DMA_DESC_NUM_GENERIC) - 1);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic u16 dwc2_desclist_idx_dec(u16 idx, u16 inc, u8 speed)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	return (idx - inc) &
718c2ecf20Sopenharmony_ci		((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC :
728c2ecf20Sopenharmony_ci		  MAX_DMA_DESC_NUM_GENERIC) - 1);
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic u16 dwc2_max_desc_num(struct dwc2_qh *qh)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	return (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
788c2ecf20Sopenharmony_ci		qh->dev_speed == USB_SPEED_HIGH) ?
798c2ecf20Sopenharmony_ci		MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic u16 dwc2_frame_incr_val(struct dwc2_qh *qh)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	return qh->dev_speed == USB_SPEED_HIGH ?
858c2ecf20Sopenharmony_ci	       (qh->host_interval + 8 - 1) / 8 : qh->host_interval;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
898c2ecf20Sopenharmony_ci				gfp_t flags)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct kmem_cache *desc_cache;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
948c2ecf20Sopenharmony_ci	    qh->dev_speed == USB_SPEED_HIGH)
958c2ecf20Sopenharmony_ci		desc_cache = hsotg->desc_hsisoc_cache;
968c2ecf20Sopenharmony_ci	else
978c2ecf20Sopenharmony_ci		desc_cache = hsotg->desc_gen_cache;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	qh->desc_list_sz = sizeof(struct dwc2_dma_desc) *
1008c2ecf20Sopenharmony_ci						dwc2_max_desc_num(qh);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	qh->desc_list = kmem_cache_zalloc(desc_cache, flags | GFP_DMA);
1038c2ecf20Sopenharmony_ci	if (!qh->desc_list)
1048c2ecf20Sopenharmony_ci		return -ENOMEM;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	qh->desc_list_dma = dma_map_single(hsotg->dev, qh->desc_list,
1078c2ecf20Sopenharmony_ci					   qh->desc_list_sz,
1088c2ecf20Sopenharmony_ci					   DMA_TO_DEVICE);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	qh->n_bytes = kcalloc(dwc2_max_desc_num(qh), sizeof(u32), flags);
1118c2ecf20Sopenharmony_ci	if (!qh->n_bytes) {
1128c2ecf20Sopenharmony_ci		dma_unmap_single(hsotg->dev, qh->desc_list_dma,
1138c2ecf20Sopenharmony_ci				 qh->desc_list_sz,
1148c2ecf20Sopenharmony_ci				 DMA_FROM_DEVICE);
1158c2ecf20Sopenharmony_ci		kmem_cache_free(desc_cache, qh->desc_list);
1168c2ecf20Sopenharmony_ci		qh->desc_list = NULL;
1178c2ecf20Sopenharmony_ci		return -ENOMEM;
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	return 0;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	struct kmem_cache *desc_cache;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
1288c2ecf20Sopenharmony_ci	    qh->dev_speed == USB_SPEED_HIGH)
1298c2ecf20Sopenharmony_ci		desc_cache = hsotg->desc_hsisoc_cache;
1308c2ecf20Sopenharmony_ci	else
1318c2ecf20Sopenharmony_ci		desc_cache = hsotg->desc_gen_cache;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	if (qh->desc_list) {
1348c2ecf20Sopenharmony_ci		dma_unmap_single(hsotg->dev, qh->desc_list_dma,
1358c2ecf20Sopenharmony_ci				 qh->desc_list_sz, DMA_FROM_DEVICE);
1368c2ecf20Sopenharmony_ci		kmem_cache_free(desc_cache, qh->desc_list);
1378c2ecf20Sopenharmony_ci		qh->desc_list = NULL;
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	kfree(qh->n_bytes);
1418c2ecf20Sopenharmony_ci	qh->n_bytes = NULL;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic int dwc2_frame_list_alloc(struct dwc2_hsotg *hsotg, gfp_t mem_flags)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	if (hsotg->frame_list)
1478c2ecf20Sopenharmony_ci		return 0;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	hsotg->frame_list_sz = 4 * FRLISTEN_64_SIZE;
1508c2ecf20Sopenharmony_ci	hsotg->frame_list = kzalloc(hsotg->frame_list_sz, GFP_ATOMIC | GFP_DMA);
1518c2ecf20Sopenharmony_ci	if (!hsotg->frame_list)
1528c2ecf20Sopenharmony_ci		return -ENOMEM;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	hsotg->frame_list_dma = dma_map_single(hsotg->dev, hsotg->frame_list,
1558c2ecf20Sopenharmony_ci					       hsotg->frame_list_sz,
1568c2ecf20Sopenharmony_ci					       DMA_TO_DEVICE);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	return 0;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void dwc2_frame_list_free(struct dwc2_hsotg *hsotg)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	unsigned long flags;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hsotg->lock, flags);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (!hsotg->frame_list) {
1688c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hsotg->lock, flags);
1698c2ecf20Sopenharmony_ci		return;
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	dma_unmap_single(hsotg->dev, hsotg->frame_list_dma,
1738c2ecf20Sopenharmony_ci			 hsotg->frame_list_sz, DMA_FROM_DEVICE);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	kfree(hsotg->frame_list);
1768c2ecf20Sopenharmony_ci	hsotg->frame_list = NULL;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hsotg->lock, flags);
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	u32 hcfg;
1848c2ecf20Sopenharmony_ci	unsigned long flags;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hsotg->lock, flags);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	hcfg = dwc2_readl(hsotg, HCFG);
1898c2ecf20Sopenharmony_ci	if (hcfg & HCFG_PERSCHEDENA) {
1908c2ecf20Sopenharmony_ci		/* already enabled */
1918c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hsotg->lock, flags);
1928c2ecf20Sopenharmony_ci		return;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	dwc2_writel(hsotg, hsotg->frame_list_dma, HFLBADDR);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	hcfg &= ~HCFG_FRLISTEN_MASK;
1988c2ecf20Sopenharmony_ci	hcfg |= fr_list_en | HCFG_PERSCHEDENA;
1998c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n");
2008c2ecf20Sopenharmony_ci	dwc2_writel(hsotg, hcfg, HCFG);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hsotg->lock, flags);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	u32 hcfg;
2088c2ecf20Sopenharmony_ci	unsigned long flags;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hsotg->lock, flags);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	hcfg = dwc2_readl(hsotg, HCFG);
2138c2ecf20Sopenharmony_ci	if (!(hcfg & HCFG_PERSCHEDENA)) {
2148c2ecf20Sopenharmony_ci		/* already disabled */
2158c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hsotg->lock, flags);
2168c2ecf20Sopenharmony_ci		return;
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	hcfg &= ~HCFG_PERSCHEDENA;
2208c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n");
2218c2ecf20Sopenharmony_ci	dwc2_writel(hsotg, hcfg, HCFG);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hsotg->lock, flags);
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci/*
2278c2ecf20Sopenharmony_ci * Activates/Deactivates FrameList entries for the channel based on endpoint
2288c2ecf20Sopenharmony_ci * servicing period
2298c2ecf20Sopenharmony_ci */
2308c2ecf20Sopenharmony_cistatic void dwc2_update_frame_list(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
2318c2ecf20Sopenharmony_ci				   int enable)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	struct dwc2_host_chan *chan;
2348c2ecf20Sopenharmony_ci	u16 i, j, inc;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (!hsotg) {
2378c2ecf20Sopenharmony_ci		pr_err("hsotg = %p\n", hsotg);
2388c2ecf20Sopenharmony_ci		return;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	if (!qh->channel) {
2428c2ecf20Sopenharmony_ci		dev_err(hsotg->dev, "qh->channel = %p\n", qh->channel);
2438c2ecf20Sopenharmony_ci		return;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	if (!hsotg->frame_list) {
2478c2ecf20Sopenharmony_ci		dev_err(hsotg->dev, "hsotg->frame_list = %p\n",
2488c2ecf20Sopenharmony_ci			hsotg->frame_list);
2498c2ecf20Sopenharmony_ci		return;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	chan = qh->channel;
2538c2ecf20Sopenharmony_ci	inc = dwc2_frame_incr_val(qh);
2548c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC)
2558c2ecf20Sopenharmony_ci		i = dwc2_frame_list_idx(qh->next_active_frame);
2568c2ecf20Sopenharmony_ci	else
2578c2ecf20Sopenharmony_ci		i = 0;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	j = i;
2608c2ecf20Sopenharmony_ci	do {
2618c2ecf20Sopenharmony_ci		if (enable)
2628c2ecf20Sopenharmony_ci			hsotg->frame_list[j] |= 1 << chan->hc_num;
2638c2ecf20Sopenharmony_ci		else
2648c2ecf20Sopenharmony_ci			hsotg->frame_list[j] &= ~(1 << chan->hc_num);
2658c2ecf20Sopenharmony_ci		j = (j + inc) & (FRLISTEN_64_SIZE - 1);
2668c2ecf20Sopenharmony_ci	} while (j != i);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/*
2698c2ecf20Sopenharmony_ci	 * Sync frame list since controller will access it if periodic
2708c2ecf20Sopenharmony_ci	 * channel is currently enabled.
2718c2ecf20Sopenharmony_ci	 */
2728c2ecf20Sopenharmony_ci	dma_sync_single_for_device(hsotg->dev,
2738c2ecf20Sopenharmony_ci				   hsotg->frame_list_dma,
2748c2ecf20Sopenharmony_ci				   hsotg->frame_list_sz,
2758c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	if (!enable)
2788c2ecf20Sopenharmony_ci		return;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	chan->schinfo = 0;
2818c2ecf20Sopenharmony_ci	if (chan->speed == USB_SPEED_HIGH && qh->host_interval) {
2828c2ecf20Sopenharmony_ci		j = 1;
2838c2ecf20Sopenharmony_ci		/* TODO - check this */
2848c2ecf20Sopenharmony_ci		inc = (8 + qh->host_interval - 1) / qh->host_interval;
2858c2ecf20Sopenharmony_ci		for (i = 0; i < inc; i++) {
2868c2ecf20Sopenharmony_ci			chan->schinfo |= j;
2878c2ecf20Sopenharmony_ci			j = j << qh->host_interval;
2888c2ecf20Sopenharmony_ci		}
2898c2ecf20Sopenharmony_ci	} else {
2908c2ecf20Sopenharmony_ci		chan->schinfo = 0xff;
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
2958c2ecf20Sopenharmony_ci				      struct dwc2_qh *qh)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct dwc2_host_chan *chan = qh->channel;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (dwc2_qh_is_non_per(qh)) {
3008c2ecf20Sopenharmony_ci		if (hsotg->params.uframe_sched)
3018c2ecf20Sopenharmony_ci			hsotg->available_host_channels++;
3028c2ecf20Sopenharmony_ci		else
3038c2ecf20Sopenharmony_ci			hsotg->non_periodic_channels--;
3048c2ecf20Sopenharmony_ci	} else {
3058c2ecf20Sopenharmony_ci		dwc2_update_frame_list(hsotg, qh, 0);
3068c2ecf20Sopenharmony_ci		hsotg->available_host_channels++;
3078c2ecf20Sopenharmony_ci	}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	/*
3108c2ecf20Sopenharmony_ci	 * The condition is added to prevent double cleanup try in case of
3118c2ecf20Sopenharmony_ci	 * device disconnect. See channel cleanup in dwc2_hcd_disconnect().
3128c2ecf20Sopenharmony_ci	 */
3138c2ecf20Sopenharmony_ci	if (chan->qh) {
3148c2ecf20Sopenharmony_ci		if (!list_empty(&chan->hc_list_entry))
3158c2ecf20Sopenharmony_ci			list_del(&chan->hc_list_entry);
3168c2ecf20Sopenharmony_ci		dwc2_hc_cleanup(hsotg, chan);
3178c2ecf20Sopenharmony_ci		list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
3188c2ecf20Sopenharmony_ci		chan->qh = NULL;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	qh->channel = NULL;
3228c2ecf20Sopenharmony_ci	qh->ntd = 0;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if (qh->desc_list)
3258c2ecf20Sopenharmony_ci		memset(qh->desc_list, 0, sizeof(struct dwc2_dma_desc) *
3268c2ecf20Sopenharmony_ci		       dwc2_max_desc_num(qh));
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci/**
3308c2ecf20Sopenharmony_ci * dwc2_hcd_qh_init_ddma() - Initializes a QH structure's Descriptor DMA
3318c2ecf20Sopenharmony_ci * related members
3328c2ecf20Sopenharmony_ci *
3338c2ecf20Sopenharmony_ci * @hsotg: The HCD state structure for the DWC OTG controller
3348c2ecf20Sopenharmony_ci * @qh:    The QH to init
3358c2ecf20Sopenharmony_ci * @mem_flags: Indicates the type of memory allocation
3368c2ecf20Sopenharmony_ci *
3378c2ecf20Sopenharmony_ci * Return: 0 if successful, negative error code otherwise
3388c2ecf20Sopenharmony_ci *
3398c2ecf20Sopenharmony_ci * Allocates memory for the descriptor list. For the first periodic QH,
3408c2ecf20Sopenharmony_ci * allocates memory for the FrameList and enables periodic scheduling.
3418c2ecf20Sopenharmony_ci */
3428c2ecf20Sopenharmony_ciint dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
3438c2ecf20Sopenharmony_ci			  gfp_t mem_flags)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	int retval;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (qh->do_split) {
3488c2ecf20Sopenharmony_ci		dev_err(hsotg->dev,
3498c2ecf20Sopenharmony_ci			"SPLIT Transfers are not supported in Descriptor DMA mode.\n");
3508c2ecf20Sopenharmony_ci		retval = -EINVAL;
3518c2ecf20Sopenharmony_ci		goto err0;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	retval = dwc2_desc_list_alloc(hsotg, qh, mem_flags);
3558c2ecf20Sopenharmony_ci	if (retval)
3568c2ecf20Sopenharmony_ci		goto err0;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
3598c2ecf20Sopenharmony_ci	    qh->ep_type == USB_ENDPOINT_XFER_INT) {
3608c2ecf20Sopenharmony_ci		if (!hsotg->frame_list) {
3618c2ecf20Sopenharmony_ci			retval = dwc2_frame_list_alloc(hsotg, mem_flags);
3628c2ecf20Sopenharmony_ci			if (retval)
3638c2ecf20Sopenharmony_ci				goto err1;
3648c2ecf20Sopenharmony_ci			/* Enable periodic schedule on first periodic QH */
3658c2ecf20Sopenharmony_ci			dwc2_per_sched_enable(hsotg, HCFG_FRLISTEN_64);
3668c2ecf20Sopenharmony_ci		}
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	qh->ntd = 0;
3708c2ecf20Sopenharmony_ci	return 0;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cierr1:
3738c2ecf20Sopenharmony_ci	dwc2_desc_list_free(hsotg, qh);
3748c2ecf20Sopenharmony_cierr0:
3758c2ecf20Sopenharmony_ci	return retval;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci/**
3798c2ecf20Sopenharmony_ci * dwc2_hcd_qh_free_ddma() - Frees a QH structure's Descriptor DMA related
3808c2ecf20Sopenharmony_ci * members
3818c2ecf20Sopenharmony_ci *
3828c2ecf20Sopenharmony_ci * @hsotg: The HCD state structure for the DWC OTG controller
3838c2ecf20Sopenharmony_ci * @qh:    The QH to free
3848c2ecf20Sopenharmony_ci *
3858c2ecf20Sopenharmony_ci * Frees descriptor list memory associated with the QH. If QH is periodic and
3868c2ecf20Sopenharmony_ci * the last, frees FrameList memory and disables periodic scheduling.
3878c2ecf20Sopenharmony_ci */
3888c2ecf20Sopenharmony_civoid dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	unsigned long flags;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	dwc2_desc_list_free(hsotg, qh);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	/*
3958c2ecf20Sopenharmony_ci	 * Channel still assigned due to some reasons.
3968c2ecf20Sopenharmony_ci	 * Seen on Isoc URB dequeue. Channel halted but no subsequent
3978c2ecf20Sopenharmony_ci	 * ChHalted interrupt to release the channel. Afterwards
3988c2ecf20Sopenharmony_ci	 * when it comes here from endpoint disable routine
3998c2ecf20Sopenharmony_ci	 * channel remains assigned.
4008c2ecf20Sopenharmony_ci	 */
4018c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hsotg->lock, flags);
4028c2ecf20Sopenharmony_ci	if (qh->channel)
4038c2ecf20Sopenharmony_ci		dwc2_release_channel_ddma(hsotg, qh);
4048c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hsotg->lock, flags);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
4078c2ecf20Sopenharmony_ci	     qh->ep_type == USB_ENDPOINT_XFER_INT) &&
4088c2ecf20Sopenharmony_ci	    (hsotg->params.uframe_sched ||
4098c2ecf20Sopenharmony_ci	     !hsotg->periodic_channels) && hsotg->frame_list) {
4108c2ecf20Sopenharmony_ci		dwc2_per_sched_disable(hsotg);
4118c2ecf20Sopenharmony_ci		dwc2_frame_list_free(hsotg);
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u16 frame_idx)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	if (qh->dev_speed == USB_SPEED_HIGH)
4188c2ecf20Sopenharmony_ci		/* Descriptor set (8 descriptors) index which is 8-aligned */
4198c2ecf20Sopenharmony_ci		return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
4208c2ecf20Sopenharmony_ci	else
4218c2ecf20Sopenharmony_ci		return frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1);
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci/*
4258c2ecf20Sopenharmony_ci * Determine starting frame for Isochronous transfer.
4268c2ecf20Sopenharmony_ci * Few frames skipped to prevent race condition with HC.
4278c2ecf20Sopenharmony_ci */
4288c2ecf20Sopenharmony_cistatic u16 dwc2_calc_starting_frame(struct dwc2_hsotg *hsotg,
4298c2ecf20Sopenharmony_ci				    struct dwc2_qh *qh, u16 *skip_frames)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	u16 frame;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	/*
4368c2ecf20Sopenharmony_ci	 * next_active_frame is always frame number (not uFrame) both in FS
4378c2ecf20Sopenharmony_ci	 * and HS!
4388c2ecf20Sopenharmony_ci	 */
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	/*
4418c2ecf20Sopenharmony_ci	 * skip_frames is used to limit activated descriptors number
4428c2ecf20Sopenharmony_ci	 * to avoid the situation when HC services the last activated
4438c2ecf20Sopenharmony_ci	 * descriptor firstly.
4448c2ecf20Sopenharmony_ci	 * Example for FS:
4458c2ecf20Sopenharmony_ci	 * Current frame is 1, scheduled frame is 3. Since HC always fetches
4468c2ecf20Sopenharmony_ci	 * the descriptor corresponding to curr_frame+1, the descriptor
4478c2ecf20Sopenharmony_ci	 * corresponding to frame 2 will be fetched. If the number of
4488c2ecf20Sopenharmony_ci	 * descriptors is max=64 (or greather) the list will be fully programmed
4498c2ecf20Sopenharmony_ci	 * with Active descriptors and it is possible case (rare) that the
4508c2ecf20Sopenharmony_ci	 * latest descriptor(considering rollback) corresponding to frame 2 will
4518c2ecf20Sopenharmony_ci	 * be serviced first. HS case is more probable because, in fact, up to
4528c2ecf20Sopenharmony_ci	 * 11 uframes (16 in the code) may be skipped.
4538c2ecf20Sopenharmony_ci	 */
4548c2ecf20Sopenharmony_ci	if (qh->dev_speed == USB_SPEED_HIGH) {
4558c2ecf20Sopenharmony_ci		/*
4568c2ecf20Sopenharmony_ci		 * Consider uframe counter also, to start xfer asap. If half of
4578c2ecf20Sopenharmony_ci		 * the frame elapsed skip 2 frames otherwise just 1 frame.
4588c2ecf20Sopenharmony_ci		 * Starting descriptor index must be 8-aligned, so if the
4598c2ecf20Sopenharmony_ci		 * current frame is near to complete the next one is skipped as
4608c2ecf20Sopenharmony_ci		 * well.
4618c2ecf20Sopenharmony_ci		 */
4628c2ecf20Sopenharmony_ci		if (dwc2_micro_frame_num(hsotg->frame_number) >= 5) {
4638c2ecf20Sopenharmony_ci			*skip_frames = 2 * 8;
4648c2ecf20Sopenharmony_ci			frame = dwc2_frame_num_inc(hsotg->frame_number,
4658c2ecf20Sopenharmony_ci						   *skip_frames);
4668c2ecf20Sopenharmony_ci		} else {
4678c2ecf20Sopenharmony_ci			*skip_frames = 1 * 8;
4688c2ecf20Sopenharmony_ci			frame = dwc2_frame_num_inc(hsotg->frame_number,
4698c2ecf20Sopenharmony_ci						   *skip_frames);
4708c2ecf20Sopenharmony_ci		}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		frame = dwc2_full_frame_num(frame);
4738c2ecf20Sopenharmony_ci	} else {
4748c2ecf20Sopenharmony_ci		/*
4758c2ecf20Sopenharmony_ci		 * Two frames are skipped for FS - the current and the next.
4768c2ecf20Sopenharmony_ci		 * But for descriptor programming, 1 frame (descriptor) is
4778c2ecf20Sopenharmony_ci		 * enough, see example above.
4788c2ecf20Sopenharmony_ci		 */
4798c2ecf20Sopenharmony_ci		*skip_frames = 1;
4808c2ecf20Sopenharmony_ci		frame = dwc2_frame_num_inc(hsotg->frame_number, 2);
4818c2ecf20Sopenharmony_ci	}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	return frame;
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci/*
4878c2ecf20Sopenharmony_ci * Calculate initial descriptor index for isochronous transfer based on
4888c2ecf20Sopenharmony_ci * scheduled frame
4898c2ecf20Sopenharmony_ci */
4908c2ecf20Sopenharmony_cistatic u16 dwc2_recalc_initial_desc_idx(struct dwc2_hsotg *hsotg,
4918c2ecf20Sopenharmony_ci					struct dwc2_qh *qh)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	u16 frame, fr_idx, fr_idx_tmp, skip_frames;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/*
4968c2ecf20Sopenharmony_ci	 * With current ISOC processing algorithm the channel is being released
4978c2ecf20Sopenharmony_ci	 * when no more QTDs in the list (qh->ntd == 0). Thus this function is
4988c2ecf20Sopenharmony_ci	 * called only when qh->ntd == 0 and qh->channel == 0.
4998c2ecf20Sopenharmony_ci	 *
5008c2ecf20Sopenharmony_ci	 * So qh->channel != NULL branch is not used and just not removed from
5018c2ecf20Sopenharmony_ci	 * the source file. It is required for another possible approach which
5028c2ecf20Sopenharmony_ci	 * is, do not disable and release the channel when ISOC session
5038c2ecf20Sopenharmony_ci	 * completed, just move QH to inactive schedule until new QTD arrives.
5048c2ecf20Sopenharmony_ci	 * On new QTD, the QH moved back to 'ready' schedule, starting frame and
5058c2ecf20Sopenharmony_ci	 * therefore starting desc_index are recalculated. In this case channel
5068c2ecf20Sopenharmony_ci	 * is released only on ep_disable.
5078c2ecf20Sopenharmony_ci	 */
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	/*
5108c2ecf20Sopenharmony_ci	 * Calculate starting descriptor index. For INTERRUPT endpoint it is
5118c2ecf20Sopenharmony_ci	 * always 0.
5128c2ecf20Sopenharmony_ci	 */
5138c2ecf20Sopenharmony_ci	if (qh->channel) {
5148c2ecf20Sopenharmony_ci		frame = dwc2_calc_starting_frame(hsotg, qh, &skip_frames);
5158c2ecf20Sopenharmony_ci		/*
5168c2ecf20Sopenharmony_ci		 * Calculate initial descriptor index based on FrameList current
5178c2ecf20Sopenharmony_ci		 * bitmap and servicing period
5188c2ecf20Sopenharmony_ci		 */
5198c2ecf20Sopenharmony_ci		fr_idx_tmp = dwc2_frame_list_idx(frame);
5208c2ecf20Sopenharmony_ci		fr_idx = (FRLISTEN_64_SIZE +
5218c2ecf20Sopenharmony_ci			  dwc2_frame_list_idx(qh->next_active_frame) -
5228c2ecf20Sopenharmony_ci			  fr_idx_tmp) % dwc2_frame_incr_val(qh);
5238c2ecf20Sopenharmony_ci		fr_idx = (fr_idx + fr_idx_tmp) % FRLISTEN_64_SIZE;
5248c2ecf20Sopenharmony_ci	} else {
5258c2ecf20Sopenharmony_ci		qh->next_active_frame = dwc2_calc_starting_frame(hsotg, qh,
5268c2ecf20Sopenharmony_ci							   &skip_frames);
5278c2ecf20Sopenharmony_ci		fr_idx = dwc2_frame_list_idx(qh->next_active_frame);
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	qh->td_first = qh->td_last = dwc2_frame_to_desc_idx(qh, fr_idx);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	return skip_frames;
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci#define ISOC_URB_GIVEBACK_ASAP
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci#define MAX_ISOC_XFER_SIZE_FS	1023
5388c2ecf20Sopenharmony_ci#define MAX_ISOC_XFER_SIZE_HS	3072
5398c2ecf20Sopenharmony_ci#define DESCNUM_THRESHOLD	4
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_cistatic void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
5428c2ecf20Sopenharmony_ci					 struct dwc2_qtd *qtd,
5438c2ecf20Sopenharmony_ci					 struct dwc2_qh *qh, u32 max_xfer_size,
5448c2ecf20Sopenharmony_ci					 u16 idx)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	struct dwc2_dma_desc *dma_desc = &qh->desc_list[idx];
5478c2ecf20Sopenharmony_ci	struct dwc2_hcd_iso_packet_desc *frame_desc;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	memset(dma_desc, 0, sizeof(*dma_desc));
5508c2ecf20Sopenharmony_ci	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	if (frame_desc->length > max_xfer_size)
5538c2ecf20Sopenharmony_ci		qh->n_bytes[idx] = max_xfer_size;
5548c2ecf20Sopenharmony_ci	else
5558c2ecf20Sopenharmony_ci		qh->n_bytes[idx] = frame_desc->length;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
5588c2ecf20Sopenharmony_ci	dma_desc->status = qh->n_bytes[idx] << HOST_DMA_ISOC_NBYTES_SHIFT &
5598c2ecf20Sopenharmony_ci			   HOST_DMA_ISOC_NBYTES_MASK;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	/* Set active bit */
5628c2ecf20Sopenharmony_ci	dma_desc->status |= HOST_DMA_A;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	qh->ntd++;
5658c2ecf20Sopenharmony_ci	qtd->isoc_frame_index_last++;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci#ifdef ISOC_URB_GIVEBACK_ASAP
5688c2ecf20Sopenharmony_ci	/* Set IOC for each descriptor corresponding to last frame of URB */
5698c2ecf20Sopenharmony_ci	if (qtd->isoc_frame_index_last == qtd->urb->packet_count)
5708c2ecf20Sopenharmony_ci		dma_desc->status |= HOST_DMA_IOC;
5718c2ecf20Sopenharmony_ci#endif
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	dma_sync_single_for_device(hsotg->dev,
5748c2ecf20Sopenharmony_ci				   qh->desc_list_dma +
5758c2ecf20Sopenharmony_ci			(idx * sizeof(struct dwc2_dma_desc)),
5768c2ecf20Sopenharmony_ci			sizeof(struct dwc2_dma_desc),
5778c2ecf20Sopenharmony_ci			DMA_TO_DEVICE);
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cistatic void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
5818c2ecf20Sopenharmony_ci				    struct dwc2_qh *qh, u16 skip_frames)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct dwc2_qtd *qtd;
5848c2ecf20Sopenharmony_ci	u32 max_xfer_size;
5858c2ecf20Sopenharmony_ci	u16 idx, inc, n_desc = 0, ntd_max = 0;
5868c2ecf20Sopenharmony_ci	u16 cur_idx;
5878c2ecf20Sopenharmony_ci	u16 next_idx;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	idx = qh->td_last;
5908c2ecf20Sopenharmony_ci	inc = qh->host_interval;
5918c2ecf20Sopenharmony_ci	hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
5928c2ecf20Sopenharmony_ci	cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
5938c2ecf20Sopenharmony_ci	next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	/*
5968c2ecf20Sopenharmony_ci	 * Ensure current frame number didn't overstep last scheduled
5978c2ecf20Sopenharmony_ci	 * descriptor. If it happens, the only way to recover is to move
5988c2ecf20Sopenharmony_ci	 * qh->td_last to current frame number + 1.
5998c2ecf20Sopenharmony_ci	 * So that next isoc descriptor will be scheduled on frame number + 1
6008c2ecf20Sopenharmony_ci	 * and not on a past frame.
6018c2ecf20Sopenharmony_ci	 */
6028c2ecf20Sopenharmony_ci	if (dwc2_frame_idx_num_gt(cur_idx, next_idx) || (cur_idx == next_idx)) {
6038c2ecf20Sopenharmony_ci		if (inc < 32) {
6048c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev,
6058c2ecf20Sopenharmony_ci				 "current frame number overstep last descriptor\n");
6068c2ecf20Sopenharmony_ci			qh->td_last = dwc2_desclist_idx_inc(cur_idx, inc,
6078c2ecf20Sopenharmony_ci							    qh->dev_speed);
6088c2ecf20Sopenharmony_ci			idx = qh->td_last;
6098c2ecf20Sopenharmony_ci		}
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	if (qh->host_interval) {
6138c2ecf20Sopenharmony_ci		ntd_max = (dwc2_max_desc_num(qh) + qh->host_interval - 1) /
6148c2ecf20Sopenharmony_ci				qh->host_interval;
6158c2ecf20Sopenharmony_ci		if (skip_frames && !qh->channel)
6168c2ecf20Sopenharmony_ci			ntd_max -= skip_frames / qh->host_interval;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	max_xfer_size = qh->dev_speed == USB_SPEED_HIGH ?
6208c2ecf20Sopenharmony_ci			MAX_ISOC_XFER_SIZE_HS : MAX_ISOC_XFER_SIZE_FS;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) {
6238c2ecf20Sopenharmony_ci		if (qtd->in_process &&
6248c2ecf20Sopenharmony_ci		    qtd->isoc_frame_index_last ==
6258c2ecf20Sopenharmony_ci		    qtd->urb->packet_count)
6268c2ecf20Sopenharmony_ci			continue;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		qtd->isoc_td_first = idx;
6298c2ecf20Sopenharmony_ci		while (qh->ntd < ntd_max && qtd->isoc_frame_index_last <
6308c2ecf20Sopenharmony_ci						qtd->urb->packet_count) {
6318c2ecf20Sopenharmony_ci			dwc2_fill_host_isoc_dma_desc(hsotg, qtd, qh,
6328c2ecf20Sopenharmony_ci						     max_xfer_size, idx);
6338c2ecf20Sopenharmony_ci			idx = dwc2_desclist_idx_inc(idx, inc, qh->dev_speed);
6348c2ecf20Sopenharmony_ci			n_desc++;
6358c2ecf20Sopenharmony_ci		}
6368c2ecf20Sopenharmony_ci		qtd->isoc_td_last = idx;
6378c2ecf20Sopenharmony_ci		qtd->in_process = 1;
6388c2ecf20Sopenharmony_ci	}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	qh->td_last = idx;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci#ifdef ISOC_URB_GIVEBACK_ASAP
6438c2ecf20Sopenharmony_ci	/* Set IOC for last descriptor if descriptor list is full */
6448c2ecf20Sopenharmony_ci	if (qh->ntd == ntd_max) {
6458c2ecf20Sopenharmony_ci		idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
6468c2ecf20Sopenharmony_ci		qh->desc_list[idx].status |= HOST_DMA_IOC;
6478c2ecf20Sopenharmony_ci		dma_sync_single_for_device(hsotg->dev,
6488c2ecf20Sopenharmony_ci					   qh->desc_list_dma + (idx *
6498c2ecf20Sopenharmony_ci					   sizeof(struct dwc2_dma_desc)),
6508c2ecf20Sopenharmony_ci					   sizeof(struct dwc2_dma_desc),
6518c2ecf20Sopenharmony_ci					   DMA_TO_DEVICE);
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci#else
6548c2ecf20Sopenharmony_ci	/*
6558c2ecf20Sopenharmony_ci	 * Set IOC bit only for one descriptor. Always try to be ahead of HW
6568c2ecf20Sopenharmony_ci	 * processing, i.e. on IOC generation driver activates next descriptor
6578c2ecf20Sopenharmony_ci	 * but core continues to process descriptors following the one with IOC
6588c2ecf20Sopenharmony_ci	 * set.
6598c2ecf20Sopenharmony_ci	 */
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	if (n_desc > DESCNUM_THRESHOLD)
6628c2ecf20Sopenharmony_ci		/*
6638c2ecf20Sopenharmony_ci		 * Move IOC "up". Required even if there is only one QTD
6648c2ecf20Sopenharmony_ci		 * in the list, because QTDs might continue to be queued,
6658c2ecf20Sopenharmony_ci		 * but during the activation it was only one queued.
6668c2ecf20Sopenharmony_ci		 * Actually more than one QTD might be in the list if this
6678c2ecf20Sopenharmony_ci		 * function called from XferCompletion - QTDs was queued during
6688c2ecf20Sopenharmony_ci		 * HW processing of the previous descriptor chunk.
6698c2ecf20Sopenharmony_ci		 */
6708c2ecf20Sopenharmony_ci		idx = dwc2_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2),
6718c2ecf20Sopenharmony_ci					    qh->dev_speed);
6728c2ecf20Sopenharmony_ci	else
6738c2ecf20Sopenharmony_ci		/*
6748c2ecf20Sopenharmony_ci		 * Set the IOC for the latest descriptor if either number of
6758c2ecf20Sopenharmony_ci		 * descriptors is not greater than threshold or no more new
6768c2ecf20Sopenharmony_ci		 * descriptors activated
6778c2ecf20Sopenharmony_ci		 */
6788c2ecf20Sopenharmony_ci		idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	qh->desc_list[idx].status |= HOST_DMA_IOC;
6818c2ecf20Sopenharmony_ci	dma_sync_single_for_device(hsotg->dev,
6828c2ecf20Sopenharmony_ci				   qh->desc_list_dma +
6838c2ecf20Sopenharmony_ci				   (idx * sizeof(struct dwc2_dma_desc)),
6848c2ecf20Sopenharmony_ci				   sizeof(struct dwc2_dma_desc),
6858c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
6868c2ecf20Sopenharmony_ci#endif
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_cistatic void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg,
6908c2ecf20Sopenharmony_ci				    struct dwc2_host_chan *chan,
6918c2ecf20Sopenharmony_ci				    struct dwc2_qtd *qtd, struct dwc2_qh *qh,
6928c2ecf20Sopenharmony_ci				    int n_desc)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct dwc2_dma_desc *dma_desc = &qh->desc_list[n_desc];
6958c2ecf20Sopenharmony_ci	int len = chan->xfer_len;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	if (len > HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1))
6988c2ecf20Sopenharmony_ci		len = HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	if (chan->ep_is_in) {
7018c2ecf20Sopenharmony_ci		int num_packets;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci		if (len > 0 && chan->max_packet)
7048c2ecf20Sopenharmony_ci			num_packets = (len + chan->max_packet - 1)
7058c2ecf20Sopenharmony_ci					/ chan->max_packet;
7068c2ecf20Sopenharmony_ci		else
7078c2ecf20Sopenharmony_ci			/* Need 1 packet for transfer length of 0 */
7088c2ecf20Sopenharmony_ci			num_packets = 1;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci		/* Always program an integral # of packets for IN transfers */
7118c2ecf20Sopenharmony_ci		len = num_packets * chan->max_packet;
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	dma_desc->status = len << HOST_DMA_NBYTES_SHIFT & HOST_DMA_NBYTES_MASK;
7158c2ecf20Sopenharmony_ci	qh->n_bytes[n_desc] = len;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL &&
7188c2ecf20Sopenharmony_ci	    qtd->control_phase == DWC2_CONTROL_SETUP)
7198c2ecf20Sopenharmony_ci		dma_desc->status |= HOST_DMA_SUP;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	dma_desc->buf = (u32)chan->xfer_dma;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	dma_sync_single_for_device(hsotg->dev,
7248c2ecf20Sopenharmony_ci				   qh->desc_list_dma +
7258c2ecf20Sopenharmony_ci				   (n_desc * sizeof(struct dwc2_dma_desc)),
7268c2ecf20Sopenharmony_ci				   sizeof(struct dwc2_dma_desc),
7278c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	/*
7308c2ecf20Sopenharmony_ci	 * Last (or only) descriptor of IN transfer with actual size less
7318c2ecf20Sopenharmony_ci	 * than MaxPacket
7328c2ecf20Sopenharmony_ci	 */
7338c2ecf20Sopenharmony_ci	if (len > chan->xfer_len) {
7348c2ecf20Sopenharmony_ci		chan->xfer_len = 0;
7358c2ecf20Sopenharmony_ci	} else {
7368c2ecf20Sopenharmony_ci		chan->xfer_dma += len;
7378c2ecf20Sopenharmony_ci		chan->xfer_len -= len;
7388c2ecf20Sopenharmony_ci	}
7398c2ecf20Sopenharmony_ci}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_cistatic void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
7428c2ecf20Sopenharmony_ci					struct dwc2_qh *qh)
7438c2ecf20Sopenharmony_ci{
7448c2ecf20Sopenharmony_ci	struct dwc2_qtd *qtd;
7458c2ecf20Sopenharmony_ci	struct dwc2_host_chan *chan = qh->channel;
7468c2ecf20Sopenharmony_ci	int n_desc = 0;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev, "%s(): qh=%p dma=%08lx len=%d\n", __func__, qh,
7498c2ecf20Sopenharmony_ci		 (unsigned long)chan->xfer_dma, chan->xfer_len);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	/*
7528c2ecf20Sopenharmony_ci	 * Start with chan->xfer_dma initialized in assign_and_init_hc(), then
7538c2ecf20Sopenharmony_ci	 * if SG transfer consists of multiple URBs, this pointer is re-assigned
7548c2ecf20Sopenharmony_ci	 * to the buffer of the currently processed QTD. For non-SG request
7558c2ecf20Sopenharmony_ci	 * there is always one QTD active.
7568c2ecf20Sopenharmony_ci	 */
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) {
7598c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev, "qtd=%p\n", qtd);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci		if (n_desc) {
7628c2ecf20Sopenharmony_ci			/* SG request - more than 1 QTD */
7638c2ecf20Sopenharmony_ci			chan->xfer_dma = qtd->urb->dma +
7648c2ecf20Sopenharmony_ci					qtd->urb->actual_length;
7658c2ecf20Sopenharmony_ci			chan->xfer_len = qtd->urb->length -
7668c2ecf20Sopenharmony_ci					qtd->urb->actual_length;
7678c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev, "buf=%08lx len=%d\n",
7688c2ecf20Sopenharmony_ci				 (unsigned long)chan->xfer_dma, chan->xfer_len);
7698c2ecf20Sopenharmony_ci		}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci		qtd->n_desc = 0;
7728c2ecf20Sopenharmony_ci		do {
7738c2ecf20Sopenharmony_ci			if (n_desc > 1) {
7748c2ecf20Sopenharmony_ci				qh->desc_list[n_desc - 1].status |= HOST_DMA_A;
7758c2ecf20Sopenharmony_ci				dev_vdbg(hsotg->dev,
7768c2ecf20Sopenharmony_ci					 "set A bit in desc %d (%p)\n",
7778c2ecf20Sopenharmony_ci					 n_desc - 1,
7788c2ecf20Sopenharmony_ci					 &qh->desc_list[n_desc - 1]);
7798c2ecf20Sopenharmony_ci				dma_sync_single_for_device(hsotg->dev,
7808c2ecf20Sopenharmony_ci							   qh->desc_list_dma +
7818c2ecf20Sopenharmony_ci					((n_desc - 1) *
7828c2ecf20Sopenharmony_ci					sizeof(struct dwc2_dma_desc)),
7838c2ecf20Sopenharmony_ci					sizeof(struct dwc2_dma_desc),
7848c2ecf20Sopenharmony_ci					DMA_TO_DEVICE);
7858c2ecf20Sopenharmony_ci			}
7868c2ecf20Sopenharmony_ci			dwc2_fill_host_dma_desc(hsotg, chan, qtd, qh, n_desc);
7878c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev,
7888c2ecf20Sopenharmony_ci				 "desc %d (%p) buf=%08x status=%08x\n",
7898c2ecf20Sopenharmony_ci				 n_desc, &qh->desc_list[n_desc],
7908c2ecf20Sopenharmony_ci				 qh->desc_list[n_desc].buf,
7918c2ecf20Sopenharmony_ci				 qh->desc_list[n_desc].status);
7928c2ecf20Sopenharmony_ci			qtd->n_desc++;
7938c2ecf20Sopenharmony_ci			n_desc++;
7948c2ecf20Sopenharmony_ci		} while (chan->xfer_len > 0 &&
7958c2ecf20Sopenharmony_ci			 n_desc != MAX_DMA_DESC_NUM_GENERIC);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev, "n_desc=%d\n", n_desc);
7988c2ecf20Sopenharmony_ci		qtd->in_process = 1;
7998c2ecf20Sopenharmony_ci		if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL)
8008c2ecf20Sopenharmony_ci			break;
8018c2ecf20Sopenharmony_ci		if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
8028c2ecf20Sopenharmony_ci			break;
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	if (n_desc) {
8068c2ecf20Sopenharmony_ci		qh->desc_list[n_desc - 1].status |=
8078c2ecf20Sopenharmony_ci				HOST_DMA_IOC | HOST_DMA_EOL | HOST_DMA_A;
8088c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev, "set IOC/EOL/A bits in desc %d (%p)\n",
8098c2ecf20Sopenharmony_ci			 n_desc - 1, &qh->desc_list[n_desc - 1]);
8108c2ecf20Sopenharmony_ci		dma_sync_single_for_device(hsotg->dev,
8118c2ecf20Sopenharmony_ci					   qh->desc_list_dma + (n_desc - 1) *
8128c2ecf20Sopenharmony_ci					   sizeof(struct dwc2_dma_desc),
8138c2ecf20Sopenharmony_ci					   sizeof(struct dwc2_dma_desc),
8148c2ecf20Sopenharmony_ci					   DMA_TO_DEVICE);
8158c2ecf20Sopenharmony_ci		if (n_desc > 1) {
8168c2ecf20Sopenharmony_ci			qh->desc_list[0].status |= HOST_DMA_A;
8178c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev, "set A bit in desc 0 (%p)\n",
8188c2ecf20Sopenharmony_ci				 &qh->desc_list[0]);
8198c2ecf20Sopenharmony_ci			dma_sync_single_for_device(hsotg->dev,
8208c2ecf20Sopenharmony_ci						   qh->desc_list_dma,
8218c2ecf20Sopenharmony_ci					sizeof(struct dwc2_dma_desc),
8228c2ecf20Sopenharmony_ci					DMA_TO_DEVICE);
8238c2ecf20Sopenharmony_ci		}
8248c2ecf20Sopenharmony_ci		chan->ntd = n_desc;
8258c2ecf20Sopenharmony_ci	}
8268c2ecf20Sopenharmony_ci}
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci/**
8298c2ecf20Sopenharmony_ci * dwc2_hcd_start_xfer_ddma() - Starts a transfer in Descriptor DMA mode
8308c2ecf20Sopenharmony_ci *
8318c2ecf20Sopenharmony_ci * @hsotg: The HCD state structure for the DWC OTG controller
8328c2ecf20Sopenharmony_ci * @qh:    The QH to init
8338c2ecf20Sopenharmony_ci *
8348c2ecf20Sopenharmony_ci * Return: 0 if successful, negative error code otherwise
8358c2ecf20Sopenharmony_ci *
8368c2ecf20Sopenharmony_ci * For Control and Bulk endpoints, initializes descriptor list and starts the
8378c2ecf20Sopenharmony_ci * transfer. For Interrupt and Isochronous endpoints, initializes descriptor
8388c2ecf20Sopenharmony_ci * list then updates FrameList, marking appropriate entries as active.
8398c2ecf20Sopenharmony_ci *
8408c2ecf20Sopenharmony_ci * For Isochronous endpoints the starting descriptor index is calculated based
8418c2ecf20Sopenharmony_ci * on the scheduled frame, but only on the first transfer descriptor within a
8428c2ecf20Sopenharmony_ci * session. Then the transfer is started via enabling the channel.
8438c2ecf20Sopenharmony_ci *
8448c2ecf20Sopenharmony_ci * For Isochronous endpoints the channel is not halted on XferComplete
8458c2ecf20Sopenharmony_ci * interrupt so remains assigned to the endpoint(QH) until session is done.
8468c2ecf20Sopenharmony_ci */
8478c2ecf20Sopenharmony_civoid dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
8488c2ecf20Sopenharmony_ci{
8498c2ecf20Sopenharmony_ci	/* Channel is already assigned */
8508c2ecf20Sopenharmony_ci	struct dwc2_host_chan *chan = qh->channel;
8518c2ecf20Sopenharmony_ci	u16 skip_frames = 0;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	switch (chan->ep_type) {
8548c2ecf20Sopenharmony_ci	case USB_ENDPOINT_XFER_CONTROL:
8558c2ecf20Sopenharmony_ci	case USB_ENDPOINT_XFER_BULK:
8568c2ecf20Sopenharmony_ci		dwc2_init_non_isoc_dma_desc(hsotg, qh);
8578c2ecf20Sopenharmony_ci		dwc2_hc_start_transfer_ddma(hsotg, chan);
8588c2ecf20Sopenharmony_ci		break;
8598c2ecf20Sopenharmony_ci	case USB_ENDPOINT_XFER_INT:
8608c2ecf20Sopenharmony_ci		dwc2_init_non_isoc_dma_desc(hsotg, qh);
8618c2ecf20Sopenharmony_ci		dwc2_update_frame_list(hsotg, qh, 1);
8628c2ecf20Sopenharmony_ci		dwc2_hc_start_transfer_ddma(hsotg, chan);
8638c2ecf20Sopenharmony_ci		break;
8648c2ecf20Sopenharmony_ci	case USB_ENDPOINT_XFER_ISOC:
8658c2ecf20Sopenharmony_ci		if (!qh->ntd)
8668c2ecf20Sopenharmony_ci			skip_frames = dwc2_recalc_initial_desc_idx(hsotg, qh);
8678c2ecf20Sopenharmony_ci		dwc2_init_isoc_dma_desc(hsotg, qh, skip_frames);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci		if (!chan->xfer_started) {
8708c2ecf20Sopenharmony_ci			dwc2_update_frame_list(hsotg, qh, 1);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci			/*
8738c2ecf20Sopenharmony_ci			 * Always set to max, instead of actual size. Otherwise
8748c2ecf20Sopenharmony_ci			 * ntd will be changed with channel being enabled. Not
8758c2ecf20Sopenharmony_ci			 * recommended.
8768c2ecf20Sopenharmony_ci			 */
8778c2ecf20Sopenharmony_ci			chan->ntd = dwc2_max_desc_num(qh);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci			/* Enable channel only once for ISOC */
8808c2ecf20Sopenharmony_ci			dwc2_hc_start_transfer_ddma(hsotg, chan);
8818c2ecf20Sopenharmony_ci		}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci		break;
8848c2ecf20Sopenharmony_ci	default:
8858c2ecf20Sopenharmony_ci		break;
8868c2ecf20Sopenharmony_ci	}
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci#define DWC2_CMPL_DONE		1
8908c2ecf20Sopenharmony_ci#define DWC2_CMPL_STOP		2
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_cistatic int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
8938c2ecf20Sopenharmony_ci					struct dwc2_host_chan *chan,
8948c2ecf20Sopenharmony_ci					struct dwc2_qtd *qtd,
8958c2ecf20Sopenharmony_ci					struct dwc2_qh *qh, u16 idx)
8968c2ecf20Sopenharmony_ci{
8978c2ecf20Sopenharmony_ci	struct dwc2_dma_desc *dma_desc;
8988c2ecf20Sopenharmony_ci	struct dwc2_hcd_iso_packet_desc *frame_desc;
8998c2ecf20Sopenharmony_ci	u16 remain = 0;
9008c2ecf20Sopenharmony_ci	int rc = 0;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	if (!qtd->urb)
9038c2ecf20Sopenharmony_ci		return -EINVAL;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
9068c2ecf20Sopenharmony_ci				sizeof(struct dwc2_dma_desc)),
9078c2ecf20Sopenharmony_ci				sizeof(struct dwc2_dma_desc),
9088c2ecf20Sopenharmony_ci				DMA_FROM_DEVICE);
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	dma_desc = &qh->desc_list[idx];
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
9138c2ecf20Sopenharmony_ci	dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
9148c2ecf20Sopenharmony_ci	if (chan->ep_is_in)
9158c2ecf20Sopenharmony_ci		remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >>
9168c2ecf20Sopenharmony_ci			 HOST_DMA_ISOC_NBYTES_SHIFT;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) {
9198c2ecf20Sopenharmony_ci		/*
9208c2ecf20Sopenharmony_ci		 * XactError, or unable to complete all the transactions
9218c2ecf20Sopenharmony_ci		 * in the scheduled micro-frame/frame, both indicated by
9228c2ecf20Sopenharmony_ci		 * HOST_DMA_STS_PKTERR
9238c2ecf20Sopenharmony_ci		 */
9248c2ecf20Sopenharmony_ci		qtd->urb->error_count++;
9258c2ecf20Sopenharmony_ci		frame_desc->actual_length = qh->n_bytes[idx] - remain;
9268c2ecf20Sopenharmony_ci		frame_desc->status = -EPROTO;
9278c2ecf20Sopenharmony_ci	} else {
9288c2ecf20Sopenharmony_ci		/* Success */
9298c2ecf20Sopenharmony_ci		frame_desc->actual_length = qh->n_bytes[idx] - remain;
9308c2ecf20Sopenharmony_ci		frame_desc->status = 0;
9318c2ecf20Sopenharmony_ci	}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
9348c2ecf20Sopenharmony_ci		/*
9358c2ecf20Sopenharmony_ci		 * urb->status is not used for isoc transfers here. The
9368c2ecf20Sopenharmony_ci		 * individual frame_desc status are used instead.
9378c2ecf20Sopenharmony_ci		 */
9388c2ecf20Sopenharmony_ci		dwc2_host_complete(hsotg, qtd, 0);
9398c2ecf20Sopenharmony_ci		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci		/*
9428c2ecf20Sopenharmony_ci		 * This check is necessary because urb_dequeue can be called
9438c2ecf20Sopenharmony_ci		 * from urb complete callback (sound driver for example). All
9448c2ecf20Sopenharmony_ci		 * pending URBs are dequeued there, so no need for further
9458c2ecf20Sopenharmony_ci		 * processing.
9468c2ecf20Sopenharmony_ci		 */
9478c2ecf20Sopenharmony_ci		if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE)
9488c2ecf20Sopenharmony_ci			return -1;
9498c2ecf20Sopenharmony_ci		rc = DWC2_CMPL_DONE;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	qh->ntd--;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	/* Stop if IOC requested descriptor reached */
9558c2ecf20Sopenharmony_ci	if (dma_desc->status & HOST_DMA_IOC)
9568c2ecf20Sopenharmony_ci		rc = DWC2_CMPL_STOP;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	return rc;
9598c2ecf20Sopenharmony_ci}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
9628c2ecf20Sopenharmony_ci					 struct dwc2_host_chan *chan,
9638c2ecf20Sopenharmony_ci					 enum dwc2_halt_status halt_status)
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	struct dwc2_hcd_iso_packet_desc *frame_desc;
9668c2ecf20Sopenharmony_ci	struct dwc2_qtd *qtd, *qtd_tmp;
9678c2ecf20Sopenharmony_ci	struct dwc2_qh *qh;
9688c2ecf20Sopenharmony_ci	u16 idx;
9698c2ecf20Sopenharmony_ci	int rc;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	qh = chan->qh;
9728c2ecf20Sopenharmony_ci	idx = qh->td_first;
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
9758c2ecf20Sopenharmony_ci		list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry)
9768c2ecf20Sopenharmony_ci			qtd->in_process = 0;
9778c2ecf20Sopenharmony_ci		return;
9788c2ecf20Sopenharmony_ci	}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	if (halt_status == DWC2_HC_XFER_AHB_ERR ||
9818c2ecf20Sopenharmony_ci	    halt_status == DWC2_HC_XFER_BABBLE_ERR) {
9828c2ecf20Sopenharmony_ci		/*
9838c2ecf20Sopenharmony_ci		 * Channel is halted in these error cases, considered as serious
9848c2ecf20Sopenharmony_ci		 * issues.
9858c2ecf20Sopenharmony_ci		 * Complete all URBs marking all frames as failed, irrespective
9868c2ecf20Sopenharmony_ci		 * whether some of the descriptors (frames) succeeded or not.
9878c2ecf20Sopenharmony_ci		 * Pass error code to completion routine as well, to update
9888c2ecf20Sopenharmony_ci		 * urb->status, some of class drivers might use it to stop
9898c2ecf20Sopenharmony_ci		 * queing transfer requests.
9908c2ecf20Sopenharmony_ci		 */
9918c2ecf20Sopenharmony_ci		int err = halt_status == DWC2_HC_XFER_AHB_ERR ?
9928c2ecf20Sopenharmony_ci			  -EIO : -EOVERFLOW;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
9958c2ecf20Sopenharmony_ci					 qtd_list_entry) {
9968c2ecf20Sopenharmony_ci			if (qtd->urb) {
9978c2ecf20Sopenharmony_ci				for (idx = 0; idx < qtd->urb->packet_count;
9988c2ecf20Sopenharmony_ci				     idx++) {
9998c2ecf20Sopenharmony_ci					frame_desc = &qtd->urb->iso_descs[idx];
10008c2ecf20Sopenharmony_ci					frame_desc->status = err;
10018c2ecf20Sopenharmony_ci				}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci				dwc2_host_complete(hsotg, qtd, err);
10048c2ecf20Sopenharmony_ci			}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
10078c2ecf20Sopenharmony_ci		}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci		return;
10108c2ecf20Sopenharmony_ci	}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
10138c2ecf20Sopenharmony_ci		if (!qtd->in_process)
10148c2ecf20Sopenharmony_ci			break;
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci		/*
10178c2ecf20Sopenharmony_ci		 * Ensure idx corresponds to descriptor where first urb of this
10188c2ecf20Sopenharmony_ci		 * qtd was added. In fact, during isoc desc init, dwc2 may skip
10198c2ecf20Sopenharmony_ci		 * an index if current frame number is already over this index.
10208c2ecf20Sopenharmony_ci		 */
10218c2ecf20Sopenharmony_ci		if (idx != qtd->isoc_td_first) {
10228c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev,
10238c2ecf20Sopenharmony_ci				 "try to complete %d instead of %d\n",
10248c2ecf20Sopenharmony_ci				 idx, qtd->isoc_td_first);
10258c2ecf20Sopenharmony_ci			idx = qtd->isoc_td_first;
10268c2ecf20Sopenharmony_ci		}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci		do {
10298c2ecf20Sopenharmony_ci			struct dwc2_qtd *qtd_next;
10308c2ecf20Sopenharmony_ci			u16 cur_idx;
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci			rc = dwc2_cmpl_host_isoc_dma_desc(hsotg, chan, qtd, qh,
10338c2ecf20Sopenharmony_ci							  idx);
10348c2ecf20Sopenharmony_ci			if (rc < 0)
10358c2ecf20Sopenharmony_ci				return;
10368c2ecf20Sopenharmony_ci			idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
10378c2ecf20Sopenharmony_ci						    chan->speed);
10388c2ecf20Sopenharmony_ci			if (!rc)
10398c2ecf20Sopenharmony_ci				continue;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci			if (rc == DWC2_CMPL_DONE)
10428c2ecf20Sopenharmony_ci				break;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci			/* rc == DWC2_CMPL_STOP */
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci			if (qh->host_interval >= 32)
10478c2ecf20Sopenharmony_ci				goto stop_scan;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci			qh->td_first = idx;
10508c2ecf20Sopenharmony_ci			cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
10518c2ecf20Sopenharmony_ci			qtd_next = list_first_entry(&qh->qtd_list,
10528c2ecf20Sopenharmony_ci						    struct dwc2_qtd,
10538c2ecf20Sopenharmony_ci						    qtd_list_entry);
10548c2ecf20Sopenharmony_ci			if (dwc2_frame_idx_num_gt(cur_idx,
10558c2ecf20Sopenharmony_ci						  qtd_next->isoc_td_last))
10568c2ecf20Sopenharmony_ci				break;
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci			goto stop_scan;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci		} while (idx != qh->td_first);
10618c2ecf20Sopenharmony_ci	}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_cistop_scan:
10648c2ecf20Sopenharmony_ci	qh->td_first = idx;
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg,
10688c2ecf20Sopenharmony_ci					       struct dwc2_host_chan *chan,
10698c2ecf20Sopenharmony_ci					struct dwc2_qtd *qtd,
10708c2ecf20Sopenharmony_ci					struct dwc2_dma_desc *dma_desc,
10718c2ecf20Sopenharmony_ci					enum dwc2_halt_status halt_status,
10728c2ecf20Sopenharmony_ci					u32 n_bytes, int *xfer_done)
10738c2ecf20Sopenharmony_ci{
10748c2ecf20Sopenharmony_ci	struct dwc2_hcd_urb *urb = qtd->urb;
10758c2ecf20Sopenharmony_ci	u16 remain = 0;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	if (chan->ep_is_in)
10788c2ecf20Sopenharmony_ci		remain = (dma_desc->status & HOST_DMA_NBYTES_MASK) >>
10798c2ecf20Sopenharmony_ci			 HOST_DMA_NBYTES_SHIFT;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev, "remain=%d dwc2_urb=%p\n", remain, urb);
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	if (halt_status == DWC2_HC_XFER_AHB_ERR) {
10848c2ecf20Sopenharmony_ci		dev_err(hsotg->dev, "EIO\n");
10858c2ecf20Sopenharmony_ci		urb->status = -EIO;
10868c2ecf20Sopenharmony_ci		return 1;
10878c2ecf20Sopenharmony_ci	}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) {
10908c2ecf20Sopenharmony_ci		switch (halt_status) {
10918c2ecf20Sopenharmony_ci		case DWC2_HC_XFER_STALL:
10928c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev, "Stall\n");
10938c2ecf20Sopenharmony_ci			urb->status = -EPIPE;
10948c2ecf20Sopenharmony_ci			break;
10958c2ecf20Sopenharmony_ci		case DWC2_HC_XFER_BABBLE_ERR:
10968c2ecf20Sopenharmony_ci			dev_err(hsotg->dev, "Babble\n");
10978c2ecf20Sopenharmony_ci			urb->status = -EOVERFLOW;
10988c2ecf20Sopenharmony_ci			break;
10998c2ecf20Sopenharmony_ci		case DWC2_HC_XFER_XACT_ERR:
11008c2ecf20Sopenharmony_ci			dev_err(hsotg->dev, "XactErr\n");
11018c2ecf20Sopenharmony_ci			urb->status = -EPROTO;
11028c2ecf20Sopenharmony_ci			break;
11038c2ecf20Sopenharmony_ci		default:
11048c2ecf20Sopenharmony_ci			dev_err(hsotg->dev,
11058c2ecf20Sopenharmony_ci				"%s: Unhandled descriptor error status (%d)\n",
11068c2ecf20Sopenharmony_ci				__func__, halt_status);
11078c2ecf20Sopenharmony_ci			break;
11088c2ecf20Sopenharmony_ci		}
11098c2ecf20Sopenharmony_ci		return 1;
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	if (dma_desc->status & HOST_DMA_A) {
11138c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev,
11148c2ecf20Sopenharmony_ci			 "Active descriptor encountered on channel %d\n",
11158c2ecf20Sopenharmony_ci			 chan->hc_num);
11168c2ecf20Sopenharmony_ci		return 0;
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL) {
11208c2ecf20Sopenharmony_ci		if (qtd->control_phase == DWC2_CONTROL_DATA) {
11218c2ecf20Sopenharmony_ci			urb->actual_length += n_bytes - remain;
11228c2ecf20Sopenharmony_ci			if (remain || urb->actual_length >= urb->length) {
11238c2ecf20Sopenharmony_ci				/*
11248c2ecf20Sopenharmony_ci				 * For Control Data stage do not set urb->status
11258c2ecf20Sopenharmony_ci				 * to 0, to prevent URB callback. Set it when
11268c2ecf20Sopenharmony_ci				 * Status phase is done. See below.
11278c2ecf20Sopenharmony_ci				 */
11288c2ecf20Sopenharmony_ci				*xfer_done = 1;
11298c2ecf20Sopenharmony_ci			}
11308c2ecf20Sopenharmony_ci		} else if (qtd->control_phase == DWC2_CONTROL_STATUS) {
11318c2ecf20Sopenharmony_ci			urb->status = 0;
11328c2ecf20Sopenharmony_ci			*xfer_done = 1;
11338c2ecf20Sopenharmony_ci		}
11348c2ecf20Sopenharmony_ci		/* No handling for SETUP stage */
11358c2ecf20Sopenharmony_ci	} else {
11368c2ecf20Sopenharmony_ci		/* BULK and INTR */
11378c2ecf20Sopenharmony_ci		urb->actual_length += n_bytes - remain;
11388c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev, "length=%d actual=%d\n", urb->length,
11398c2ecf20Sopenharmony_ci			 urb->actual_length);
11408c2ecf20Sopenharmony_ci		if (remain || urb->actual_length >= urb->length) {
11418c2ecf20Sopenharmony_ci			urb->status = 0;
11428c2ecf20Sopenharmony_ci			*xfer_done = 1;
11438c2ecf20Sopenharmony_ci		}
11448c2ecf20Sopenharmony_ci	}
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	return 0;
11478c2ecf20Sopenharmony_ci}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_cistatic int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
11508c2ecf20Sopenharmony_ci				      struct dwc2_host_chan *chan,
11518c2ecf20Sopenharmony_ci				      int chnum, struct dwc2_qtd *qtd,
11528c2ecf20Sopenharmony_ci				      int desc_num,
11538c2ecf20Sopenharmony_ci				      enum dwc2_halt_status halt_status,
11548c2ecf20Sopenharmony_ci				      int *xfer_done)
11558c2ecf20Sopenharmony_ci{
11568c2ecf20Sopenharmony_ci	struct dwc2_qh *qh = chan->qh;
11578c2ecf20Sopenharmony_ci	struct dwc2_hcd_urb *urb = qtd->urb;
11588c2ecf20Sopenharmony_ci	struct dwc2_dma_desc *dma_desc;
11598c2ecf20Sopenharmony_ci	u32 n_bytes;
11608c2ecf20Sopenharmony_ci	int failed;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev, "%s()\n", __func__);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	if (!urb)
11658c2ecf20Sopenharmony_ci		return -EINVAL;
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	dma_sync_single_for_cpu(hsotg->dev,
11688c2ecf20Sopenharmony_ci				qh->desc_list_dma + (desc_num *
11698c2ecf20Sopenharmony_ci				sizeof(struct dwc2_dma_desc)),
11708c2ecf20Sopenharmony_ci				sizeof(struct dwc2_dma_desc),
11718c2ecf20Sopenharmony_ci				DMA_FROM_DEVICE);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	dma_desc = &qh->desc_list[desc_num];
11748c2ecf20Sopenharmony_ci	n_bytes = qh->n_bytes[desc_num];
11758c2ecf20Sopenharmony_ci	dev_vdbg(hsotg->dev,
11768c2ecf20Sopenharmony_ci		 "qtd=%p dwc2_urb=%p desc_num=%d desc=%p n_bytes=%d\n",
11778c2ecf20Sopenharmony_ci		 qtd, urb, desc_num, dma_desc, n_bytes);
11788c2ecf20Sopenharmony_ci	failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc,
11798c2ecf20Sopenharmony_ci						     halt_status, n_bytes,
11808c2ecf20Sopenharmony_ci						     xfer_done);
11818c2ecf20Sopenharmony_ci	if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
11828c2ecf20Sopenharmony_ci		dwc2_host_complete(hsotg, qtd, urb->status);
11838c2ecf20Sopenharmony_ci		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
11848c2ecf20Sopenharmony_ci		dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n",
11858c2ecf20Sopenharmony_ci			 failed, *xfer_done);
11868c2ecf20Sopenharmony_ci		return failed;
11878c2ecf20Sopenharmony_ci	}
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL) {
11908c2ecf20Sopenharmony_ci		switch (qtd->control_phase) {
11918c2ecf20Sopenharmony_ci		case DWC2_CONTROL_SETUP:
11928c2ecf20Sopenharmony_ci			if (urb->length > 0)
11938c2ecf20Sopenharmony_ci				qtd->control_phase = DWC2_CONTROL_DATA;
11948c2ecf20Sopenharmony_ci			else
11958c2ecf20Sopenharmony_ci				qtd->control_phase = DWC2_CONTROL_STATUS;
11968c2ecf20Sopenharmony_ci			dev_vdbg(hsotg->dev,
11978c2ecf20Sopenharmony_ci				 "  Control setup transaction done\n");
11988c2ecf20Sopenharmony_ci			break;
11998c2ecf20Sopenharmony_ci		case DWC2_CONTROL_DATA:
12008c2ecf20Sopenharmony_ci			if (*xfer_done) {
12018c2ecf20Sopenharmony_ci				qtd->control_phase = DWC2_CONTROL_STATUS;
12028c2ecf20Sopenharmony_ci				dev_vdbg(hsotg->dev,
12038c2ecf20Sopenharmony_ci					 "  Control data transfer done\n");
12048c2ecf20Sopenharmony_ci			} else if (desc_num + 1 == qtd->n_desc) {
12058c2ecf20Sopenharmony_ci				/*
12068c2ecf20Sopenharmony_ci				 * Last descriptor for Control data stage which
12078c2ecf20Sopenharmony_ci				 * is not completed yet
12088c2ecf20Sopenharmony_ci				 */
12098c2ecf20Sopenharmony_ci				dwc2_hcd_save_data_toggle(hsotg, chan, chnum,
12108c2ecf20Sopenharmony_ci							  qtd);
12118c2ecf20Sopenharmony_ci			}
12128c2ecf20Sopenharmony_ci			break;
12138c2ecf20Sopenharmony_ci		default:
12148c2ecf20Sopenharmony_ci			break;
12158c2ecf20Sopenharmony_ci		}
12168c2ecf20Sopenharmony_ci	}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	return 0;
12198c2ecf20Sopenharmony_ci}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_cistatic void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
12228c2ecf20Sopenharmony_ci					     struct dwc2_host_chan *chan,
12238c2ecf20Sopenharmony_ci					     int chnum,
12248c2ecf20Sopenharmony_ci					     enum dwc2_halt_status halt_status)
12258c2ecf20Sopenharmony_ci{
12268c2ecf20Sopenharmony_ci	struct list_head *qtd_item, *qtd_tmp;
12278c2ecf20Sopenharmony_ci	struct dwc2_qh *qh = chan->qh;
12288c2ecf20Sopenharmony_ci	struct dwc2_qtd *qtd = NULL;
12298c2ecf20Sopenharmony_ci	int xfer_done;
12308c2ecf20Sopenharmony_ci	int desc_num = 0;
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
12338c2ecf20Sopenharmony_ci		list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry)
12348c2ecf20Sopenharmony_ci			qtd->in_process = 0;
12358c2ecf20Sopenharmony_ci		return;
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) {
12398c2ecf20Sopenharmony_ci		int i;
12408c2ecf20Sopenharmony_ci		int qtd_desc_count;
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci		qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry);
12438c2ecf20Sopenharmony_ci		xfer_done = 0;
12448c2ecf20Sopenharmony_ci		qtd_desc_count = qtd->n_desc;
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci		for (i = 0; i < qtd_desc_count; i++) {
12478c2ecf20Sopenharmony_ci			if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd,
12488c2ecf20Sopenharmony_ci						       desc_num, halt_status,
12498c2ecf20Sopenharmony_ci						       &xfer_done)) {
12508c2ecf20Sopenharmony_ci				qtd = NULL;
12518c2ecf20Sopenharmony_ci				goto stop_scan;
12528c2ecf20Sopenharmony_ci			}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci			desc_num++;
12558c2ecf20Sopenharmony_ci		}
12568c2ecf20Sopenharmony_ci	}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_cistop_scan:
12598c2ecf20Sopenharmony_ci	if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) {
12608c2ecf20Sopenharmony_ci		/*
12618c2ecf20Sopenharmony_ci		 * Resetting the data toggle for bulk and interrupt endpoints
12628c2ecf20Sopenharmony_ci		 * in case of stall. See handle_hc_stall_intr().
12638c2ecf20Sopenharmony_ci		 */
12648c2ecf20Sopenharmony_ci		if (halt_status == DWC2_HC_XFER_STALL)
12658c2ecf20Sopenharmony_ci			qh->data_toggle = DWC2_HC_PID_DATA0;
12668c2ecf20Sopenharmony_ci		else
12678c2ecf20Sopenharmony_ci			dwc2_hcd_save_data_toggle(hsotg, chan, chnum, NULL);
12688c2ecf20Sopenharmony_ci	}
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	if (halt_status == DWC2_HC_XFER_COMPLETE) {
12718c2ecf20Sopenharmony_ci		if (chan->hcint & HCINTMSK_NYET) {
12728c2ecf20Sopenharmony_ci			/*
12738c2ecf20Sopenharmony_ci			 * Got a NYET on the last transaction of the transfer.
12748c2ecf20Sopenharmony_ci			 * It means that the endpoint should be in the PING
12758c2ecf20Sopenharmony_ci			 * state at the beginning of the next transfer.
12768c2ecf20Sopenharmony_ci			 */
12778c2ecf20Sopenharmony_ci			qh->ping_state = 1;
12788c2ecf20Sopenharmony_ci		}
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci/**
12838c2ecf20Sopenharmony_ci * dwc2_hcd_complete_xfer_ddma() - Scans the descriptor list, updates URB's
12848c2ecf20Sopenharmony_ci * status and calls completion routine for the URB if it's done. Called from
12858c2ecf20Sopenharmony_ci * interrupt handlers.
12868c2ecf20Sopenharmony_ci *
12878c2ecf20Sopenharmony_ci * @hsotg:       The HCD state structure for the DWC OTG controller
12888c2ecf20Sopenharmony_ci * @chan:        Host channel the transfer is completed on
12898c2ecf20Sopenharmony_ci * @chnum:       Index of Host channel registers
12908c2ecf20Sopenharmony_ci * @halt_status: Reason the channel is being halted or just XferComplete
12918c2ecf20Sopenharmony_ci *               for isochronous transfers
12928c2ecf20Sopenharmony_ci *
12938c2ecf20Sopenharmony_ci * Releases the channel to be used by other transfers.
12948c2ecf20Sopenharmony_ci * In case of Isochronous endpoint the channel is not halted until the end of
12958c2ecf20Sopenharmony_ci * the session, i.e. QTD list is empty.
12968c2ecf20Sopenharmony_ci * If periodic channel released the FrameList is updated accordingly.
12978c2ecf20Sopenharmony_ci * Calls transaction selection routines to activate pending transfers.
12988c2ecf20Sopenharmony_ci */
12998c2ecf20Sopenharmony_civoid dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
13008c2ecf20Sopenharmony_ci				 struct dwc2_host_chan *chan, int chnum,
13018c2ecf20Sopenharmony_ci				 enum dwc2_halt_status halt_status)
13028c2ecf20Sopenharmony_ci{
13038c2ecf20Sopenharmony_ci	struct dwc2_qh *qh = chan->qh;
13048c2ecf20Sopenharmony_ci	int continue_isoc_xfer = 0;
13058c2ecf20Sopenharmony_ci	enum dwc2_transaction_type tr_type;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
13088c2ecf20Sopenharmony_ci		dwc2_complete_isoc_xfer_ddma(hsotg, chan, halt_status);
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci		/* Release the channel if halted or session completed */
13118c2ecf20Sopenharmony_ci		if (halt_status != DWC2_HC_XFER_COMPLETE ||
13128c2ecf20Sopenharmony_ci		    list_empty(&qh->qtd_list)) {
13138c2ecf20Sopenharmony_ci			struct dwc2_qtd *qtd, *qtd_tmp;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci			/*
13168c2ecf20Sopenharmony_ci			 * Kill all remainings QTDs since channel has been
13178c2ecf20Sopenharmony_ci			 * halted.
13188c2ecf20Sopenharmony_ci			 */
13198c2ecf20Sopenharmony_ci			list_for_each_entry_safe(qtd, qtd_tmp,
13208c2ecf20Sopenharmony_ci						 &qh->qtd_list,
13218c2ecf20Sopenharmony_ci						 qtd_list_entry) {
13228c2ecf20Sopenharmony_ci				dwc2_host_complete(hsotg, qtd,
13238c2ecf20Sopenharmony_ci						   -ECONNRESET);
13248c2ecf20Sopenharmony_ci				dwc2_hcd_qtd_unlink_and_free(hsotg,
13258c2ecf20Sopenharmony_ci							     qtd, qh);
13268c2ecf20Sopenharmony_ci			}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci			/* Halt the channel if session completed */
13298c2ecf20Sopenharmony_ci			if (halt_status == DWC2_HC_XFER_COMPLETE)
13308c2ecf20Sopenharmony_ci				dwc2_hc_halt(hsotg, chan, halt_status);
13318c2ecf20Sopenharmony_ci			dwc2_release_channel_ddma(hsotg, qh);
13328c2ecf20Sopenharmony_ci			dwc2_hcd_qh_unlink(hsotg, qh);
13338c2ecf20Sopenharmony_ci		} else {
13348c2ecf20Sopenharmony_ci			/* Keep in assigned schedule to continue transfer */
13358c2ecf20Sopenharmony_ci			list_move_tail(&qh->qh_list_entry,
13368c2ecf20Sopenharmony_ci				       &hsotg->periodic_sched_assigned);
13378c2ecf20Sopenharmony_ci			/*
13388c2ecf20Sopenharmony_ci			 * If channel has been halted during giveback of urb
13398c2ecf20Sopenharmony_ci			 * then prevent any new scheduling.
13408c2ecf20Sopenharmony_ci			 */
13418c2ecf20Sopenharmony_ci			if (!chan->halt_status)
13428c2ecf20Sopenharmony_ci				continue_isoc_xfer = 1;
13438c2ecf20Sopenharmony_ci		}
13448c2ecf20Sopenharmony_ci		/*
13458c2ecf20Sopenharmony_ci		 * Todo: Consider the case when period exceeds FrameList size.
13468c2ecf20Sopenharmony_ci		 * Frame Rollover interrupt should be used.
13478c2ecf20Sopenharmony_ci		 */
13488c2ecf20Sopenharmony_ci	} else {
13498c2ecf20Sopenharmony_ci		/*
13508c2ecf20Sopenharmony_ci		 * Scan descriptor list to complete the URB(s), then release
13518c2ecf20Sopenharmony_ci		 * the channel
13528c2ecf20Sopenharmony_ci		 */
13538c2ecf20Sopenharmony_ci		dwc2_complete_non_isoc_xfer_ddma(hsotg, chan, chnum,
13548c2ecf20Sopenharmony_ci						 halt_status);
13558c2ecf20Sopenharmony_ci		dwc2_release_channel_ddma(hsotg, qh);
13568c2ecf20Sopenharmony_ci		dwc2_hcd_qh_unlink(hsotg, qh);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci		if (!list_empty(&qh->qtd_list)) {
13598c2ecf20Sopenharmony_ci			/*
13608c2ecf20Sopenharmony_ci			 * Add back to inactive non-periodic schedule on normal
13618c2ecf20Sopenharmony_ci			 * completion
13628c2ecf20Sopenharmony_ci			 */
13638c2ecf20Sopenharmony_ci			dwc2_hcd_qh_add(hsotg, qh);
13648c2ecf20Sopenharmony_ci		}
13658c2ecf20Sopenharmony_ci	}
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	tr_type = dwc2_hcd_select_transactions(hsotg);
13688c2ecf20Sopenharmony_ci	if (tr_type != DWC2_TRANSACTION_NONE || continue_isoc_xfer) {
13698c2ecf20Sopenharmony_ci		if (continue_isoc_xfer) {
13708c2ecf20Sopenharmony_ci			if (tr_type == DWC2_TRANSACTION_NONE)
13718c2ecf20Sopenharmony_ci				tr_type = DWC2_TRANSACTION_PERIODIC;
13728c2ecf20Sopenharmony_ci			else if (tr_type == DWC2_TRANSACTION_NON_PERIODIC)
13738c2ecf20Sopenharmony_ci				tr_type = DWC2_TRANSACTION_ALL;
13748c2ecf20Sopenharmony_ci		}
13758c2ecf20Sopenharmony_ci		dwc2_hcd_queue_transactions(hsotg, tr_type);
13768c2ecf20Sopenharmony_ci	}
13778c2ecf20Sopenharmony_ci}
1378