|  | /* | 
|  | * hcd_ddma.c - DesignWare HS OTG Controller descriptor DMA routines | 
|  | * | 
|  | * Copyright (C) 2004-2013 Synopsys, Inc. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions, and the following disclaimer, | 
|  | *    without modification. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * 3. The names of the above-listed copyright holders may not be used | 
|  | *    to endorse or promote products derived from this software without | 
|  | *    specific prior written permission. | 
|  | * | 
|  | * ALTERNATIVELY, this software may be distributed under the terms of the | 
|  | * GNU General Public License ("GPL") as published by the Free Software | 
|  | * Foundation; either version 2 of the License, or (at your option) any | 
|  | * later version. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | 
|  | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 
|  | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
|  | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | 
|  | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|  | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|  | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|  | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|  | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|  | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * This file contains the Descriptor DMA implementation for Host mode | 
|  | */ | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/spinlock.h> | 
|  | #include <linux/interrupt.h> | 
|  | #include <linux/dma-mapping.h> | 
|  | #include <linux/io.h> | 
|  | #include <linux/slab.h> | 
|  | #include <linux/usb.h> | 
|  |  | 
|  | #include <linux/usb/hcd.h> | 
|  | #include <linux/usb/ch11.h> | 
|  |  | 
|  | #include "core.h" | 
|  | #include "hcd.h" | 
|  |  | 
|  | static u16 dwc2_frame_list_idx(u16 frame) | 
|  | { | 
|  | return frame & (FRLISTEN_64_SIZE - 1); | 
|  | } | 
|  |  | 
|  | static u16 dwc2_desclist_idx_inc(u16 idx, u16 inc, u8 speed) | 
|  | { | 
|  | return (idx + inc) & | 
|  | ((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC : | 
|  | MAX_DMA_DESC_NUM_GENERIC) - 1); | 
|  | } | 
|  |  | 
|  | static u16 dwc2_desclist_idx_dec(u16 idx, u16 inc, u8 speed) | 
|  | { | 
|  | return (idx - inc) & | 
|  | ((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC : | 
|  | MAX_DMA_DESC_NUM_GENERIC) - 1); | 
|  | } | 
|  |  | 
|  | static u16 dwc2_max_desc_num(struct dwc2_qh *qh) | 
|  | { | 
|  | return (qh->ep_type == USB_ENDPOINT_XFER_ISOC && | 
|  | qh->dev_speed == USB_SPEED_HIGH) ? | 
|  | MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC; | 
|  | } | 
|  |  | 
|  | static u16 dwc2_frame_incr_val(struct dwc2_qh *qh) | 
|  | { | 
|  | return qh->dev_speed == USB_SPEED_HIGH ? | 
|  | (qh->host_interval + 8 - 1) / 8 : qh->host_interval; | 
|  | } | 
|  |  | 
|  | static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | 
|  | gfp_t flags) | 
|  | { | 
|  | struct kmem_cache *desc_cache; | 
|  |  | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_ISOC && | 
|  | qh->dev_speed == USB_SPEED_HIGH) | 
|  | desc_cache = hsotg->desc_hsisoc_cache; | 
|  | else | 
|  | desc_cache = hsotg->desc_gen_cache; | 
|  |  | 
|  | qh->desc_list_sz = sizeof(struct dwc2_dma_desc) * | 
|  | dwc2_max_desc_num(qh); | 
|  |  | 
|  | qh->desc_list = kmem_cache_zalloc(desc_cache, flags | GFP_DMA); | 
|  | if (!qh->desc_list) | 
|  | return -ENOMEM; | 
|  |  | 
|  | qh->desc_list_dma = dma_map_single(hsotg->dev, qh->desc_list, | 
|  | qh->desc_list_sz, | 
|  | DMA_TO_DEVICE); | 
|  |  | 
|  | qh->n_bytes = kcalloc(dwc2_max_desc_num(qh), sizeof(u32), flags); | 
|  | if (!qh->n_bytes) { | 
|  | dma_unmap_single(hsotg->dev, qh->desc_list_dma, | 
|  | qh->desc_list_sz, | 
|  | DMA_FROM_DEVICE); | 
|  | kmem_cache_free(desc_cache, qh->desc_list); | 
|  | qh->desc_list = NULL; | 
|  | return -ENOMEM; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | 
|  | { | 
|  | struct kmem_cache *desc_cache; | 
|  |  | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_ISOC && | 
|  | qh->dev_speed == USB_SPEED_HIGH) | 
|  | desc_cache = hsotg->desc_hsisoc_cache; | 
|  | else | 
|  | desc_cache = hsotg->desc_gen_cache; | 
|  |  | 
|  | if (qh->desc_list) { | 
|  | dma_unmap_single(hsotg->dev, qh->desc_list_dma, | 
|  | qh->desc_list_sz, DMA_FROM_DEVICE); | 
|  | kmem_cache_free(desc_cache, qh->desc_list); | 
|  | qh->desc_list = NULL; | 
|  | } | 
|  |  | 
|  | kfree(qh->n_bytes); | 
|  | qh->n_bytes = NULL; | 
|  | } | 
|  |  | 
|  | static int dwc2_frame_list_alloc(struct dwc2_hsotg *hsotg, gfp_t mem_flags) | 
|  | { | 
|  | if (hsotg->frame_list) | 
|  | return 0; | 
|  |  | 
|  | hsotg->frame_list_sz = 4 * FRLISTEN_64_SIZE; | 
|  | hsotg->frame_list = kzalloc(hsotg->frame_list_sz, GFP_ATOMIC | GFP_DMA); | 
|  | if (!hsotg->frame_list) | 
|  | return -ENOMEM; | 
|  |  | 
|  | hsotg->frame_list_dma = dma_map_single(hsotg->dev, hsotg->frame_list, | 
|  | hsotg->frame_list_sz, | 
|  | DMA_TO_DEVICE); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void dwc2_frame_list_free(struct dwc2_hsotg *hsotg) | 
|  | { | 
|  | unsigned long flags; | 
|  |  | 
|  | spin_lock_irqsave(&hsotg->lock, flags); | 
|  |  | 
|  | if (!hsotg->frame_list) { | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | return; | 
|  | } | 
|  |  | 
|  | dma_unmap_single(hsotg->dev, hsotg->frame_list_dma, | 
|  | hsotg->frame_list_sz, DMA_FROM_DEVICE); | 
|  |  | 
|  | kfree(hsotg->frame_list); | 
|  | hsotg->frame_list = NULL; | 
|  |  | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | } | 
|  |  | 
|  | static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en) | 
|  | { | 
|  | u32 hcfg; | 
|  | unsigned long flags; | 
|  |  | 
|  | spin_lock_irqsave(&hsotg->lock, flags); | 
|  |  | 
|  | hcfg = dwc2_readl(hsotg->regs + HCFG); | 
|  | if (hcfg & HCFG_PERSCHEDENA) { | 
|  | /* already enabled */ | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | return; | 
|  | } | 
|  |  | 
|  | dwc2_writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR); | 
|  |  | 
|  | hcfg &= ~HCFG_FRLISTEN_MASK; | 
|  | hcfg |= fr_list_en | HCFG_PERSCHEDENA; | 
|  | dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n"); | 
|  | dwc2_writel(hcfg, hsotg->regs + HCFG); | 
|  |  | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | } | 
|  |  | 
|  | static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg) | 
|  | { | 
|  | u32 hcfg; | 
|  | unsigned long flags; | 
|  |  | 
|  | spin_lock_irqsave(&hsotg->lock, flags); | 
|  |  | 
|  | hcfg = dwc2_readl(hsotg->regs + HCFG); | 
|  | if (!(hcfg & HCFG_PERSCHEDENA)) { | 
|  | /* already disabled */ | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | return; | 
|  | } | 
|  |  | 
|  | hcfg &= ~HCFG_PERSCHEDENA; | 
|  | dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n"); | 
|  | dwc2_writel(hcfg, hsotg->regs + HCFG); | 
|  |  | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Activates/Deactivates FrameList entries for the channel based on endpoint | 
|  | * servicing period | 
|  | */ | 
|  | static void dwc2_update_frame_list(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | 
|  | int enable) | 
|  | { | 
|  | struct dwc2_host_chan *chan; | 
|  | u16 i, j, inc; | 
|  |  | 
|  | if (!hsotg) { | 
|  | pr_err("hsotg = %p\n", hsotg); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!qh->channel) { | 
|  | dev_err(hsotg->dev, "qh->channel = %p\n", qh->channel); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!hsotg->frame_list) { | 
|  | dev_err(hsotg->dev, "hsotg->frame_list = %p\n", | 
|  | hsotg->frame_list); | 
|  | return; | 
|  | } | 
|  |  | 
|  | chan = qh->channel; | 
|  | inc = dwc2_frame_incr_val(qh); | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_ISOC) | 
|  | i = dwc2_frame_list_idx(qh->next_active_frame); | 
|  | else | 
|  | i = 0; | 
|  |  | 
|  | j = i; | 
|  | do { | 
|  | if (enable) | 
|  | hsotg->frame_list[j] |= 1 << chan->hc_num; | 
|  | else | 
|  | hsotg->frame_list[j] &= ~(1 << chan->hc_num); | 
|  | j = (j + inc) & (FRLISTEN_64_SIZE - 1); | 
|  | } while (j != i); | 
|  |  | 
|  | /* | 
|  | * Sync frame list since controller will access it if periodic | 
|  | * channel is currently enabled. | 
|  | */ | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | hsotg->frame_list_dma, | 
|  | hsotg->frame_list_sz, | 
|  | DMA_TO_DEVICE); | 
|  |  | 
|  | if (!enable) | 
|  | return; | 
|  |  | 
|  | chan->schinfo = 0; | 
|  | if (chan->speed == USB_SPEED_HIGH && qh->host_interval) { | 
|  | j = 1; | 
|  | /* TODO - check this */ | 
|  | inc = (8 + qh->host_interval - 1) / qh->host_interval; | 
|  | for (i = 0; i < inc; i++) { | 
|  | chan->schinfo |= j; | 
|  | j = j << qh->host_interval; | 
|  | } | 
|  | } else { | 
|  | chan->schinfo = 0xff; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qh *qh) | 
|  | { | 
|  | struct dwc2_host_chan *chan = qh->channel; | 
|  |  | 
|  | if (dwc2_qh_is_non_per(qh)) { | 
|  | if (hsotg->params.uframe_sched) | 
|  | hsotg->available_host_channels++; | 
|  | else | 
|  | hsotg->non_periodic_channels--; | 
|  | } else { | 
|  | dwc2_update_frame_list(hsotg, qh, 0); | 
|  | hsotg->available_host_channels++; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The condition is added to prevent double cleanup try in case of | 
|  | * device disconnect. See channel cleanup in dwc2_hcd_disconnect(). | 
|  | */ | 
|  | if (chan->qh) { | 
|  | if (!list_empty(&chan->hc_list_entry)) | 
|  | list_del(&chan->hc_list_entry); | 
|  | dwc2_hc_cleanup(hsotg, chan); | 
|  | list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list); | 
|  | chan->qh = NULL; | 
|  | } | 
|  |  | 
|  | qh->channel = NULL; | 
|  | qh->ntd = 0; | 
|  |  | 
|  | if (qh->desc_list) | 
|  | memset(qh->desc_list, 0, sizeof(struct dwc2_dma_desc) * | 
|  | dwc2_max_desc_num(qh)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * dwc2_hcd_qh_init_ddma() - Initializes a QH structure's Descriptor DMA | 
|  | * related members | 
|  | * | 
|  | * @hsotg: The HCD state structure for the DWC OTG controller | 
|  | * @qh:    The QH to init | 
|  | * | 
|  | * Return: 0 if successful, negative error code otherwise | 
|  | * | 
|  | * Allocates memory for the descriptor list. For the first periodic QH, | 
|  | * allocates memory for the FrameList and enables periodic scheduling. | 
|  | */ | 
|  | int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | 
|  | gfp_t mem_flags) | 
|  | { | 
|  | int retval; | 
|  |  | 
|  | if (qh->do_split) { | 
|  | dev_err(hsotg->dev, | 
|  | "SPLIT Transfers are not supported in Descriptor DMA mode.\n"); | 
|  | retval = -EINVAL; | 
|  | goto err0; | 
|  | } | 
|  |  | 
|  | retval = dwc2_desc_list_alloc(hsotg, qh, mem_flags); | 
|  | if (retval) | 
|  | goto err0; | 
|  |  | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_ISOC || | 
|  | qh->ep_type == USB_ENDPOINT_XFER_INT) { | 
|  | if (!hsotg->frame_list) { | 
|  | retval = dwc2_frame_list_alloc(hsotg, mem_flags); | 
|  | if (retval) | 
|  | goto err1; | 
|  | /* Enable periodic schedule on first periodic QH */ | 
|  | dwc2_per_sched_enable(hsotg, HCFG_FRLISTEN_64); | 
|  | } | 
|  | } | 
|  |  | 
|  | qh->ntd = 0; | 
|  | return 0; | 
|  |  | 
|  | err1: | 
|  | dwc2_desc_list_free(hsotg, qh); | 
|  | err0: | 
|  | return retval; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * dwc2_hcd_qh_free_ddma() - Frees a QH structure's Descriptor DMA related | 
|  | * members | 
|  | * | 
|  | * @hsotg: The HCD state structure for the DWC OTG controller | 
|  | * @qh:    The QH to free | 
|  | * | 
|  | * Frees descriptor list memory associated with the QH. If QH is periodic and | 
|  | * the last, frees FrameList memory and disables periodic scheduling. | 
|  | */ | 
|  | void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | 
|  | { | 
|  | unsigned long flags; | 
|  |  | 
|  | dwc2_desc_list_free(hsotg, qh); | 
|  |  | 
|  | /* | 
|  | * Channel still assigned due to some reasons. | 
|  | * Seen on Isoc URB dequeue. Channel halted but no subsequent | 
|  | * ChHalted interrupt to release the channel. Afterwards | 
|  | * when it comes here from endpoint disable routine | 
|  | * channel remains assigned. | 
|  | */ | 
|  | spin_lock_irqsave(&hsotg->lock, flags); | 
|  | if (qh->channel) | 
|  | dwc2_release_channel_ddma(hsotg, qh); | 
|  | spin_unlock_irqrestore(&hsotg->lock, flags); | 
|  |  | 
|  | if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC || | 
|  | qh->ep_type == USB_ENDPOINT_XFER_INT) && | 
|  | (hsotg->params.uframe_sched || | 
|  | !hsotg->periodic_channels) && hsotg->frame_list) { | 
|  | dwc2_per_sched_disable(hsotg); | 
|  | dwc2_frame_list_free(hsotg); | 
|  | } | 
|  | } | 
|  |  | 
|  | static u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u16 frame_idx) | 
|  | { | 
|  | if (qh->dev_speed == USB_SPEED_HIGH) | 
|  | /* Descriptor set (8 descriptors) index which is 8-aligned */ | 
|  | return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; | 
|  | else | 
|  | return frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Determine starting frame for Isochronous transfer. | 
|  | * Few frames skipped to prevent race condition with HC. | 
|  | */ | 
|  | static u16 dwc2_calc_starting_frame(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qh *qh, u16 *skip_frames) | 
|  | { | 
|  | u16 frame; | 
|  |  | 
|  | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); | 
|  |  | 
|  | /* | 
|  | * next_active_frame is always frame number (not uFrame) both in FS | 
|  | * and HS! | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * skip_frames is used to limit activated descriptors number | 
|  | * to avoid the situation when HC services the last activated | 
|  | * descriptor firstly. | 
|  | * Example for FS: | 
|  | * Current frame is 1, scheduled frame is 3. Since HC always fetches | 
|  | * the descriptor corresponding to curr_frame+1, the descriptor | 
|  | * corresponding to frame 2 will be fetched. If the number of | 
|  | * descriptors is max=64 (or greather) the list will be fully programmed | 
|  | * with Active descriptors and it is possible case (rare) that the | 
|  | * latest descriptor(considering rollback) corresponding to frame 2 will | 
|  | * be serviced first. HS case is more probable because, in fact, up to | 
|  | * 11 uframes (16 in the code) may be skipped. | 
|  | */ | 
|  | if (qh->dev_speed == USB_SPEED_HIGH) { | 
|  | /* | 
|  | * Consider uframe counter also, to start xfer asap. If half of | 
|  | * the frame elapsed skip 2 frames otherwise just 1 frame. | 
|  | * Starting descriptor index must be 8-aligned, so if the | 
|  | * current frame is near to complete the next one is skipped as | 
|  | * well. | 
|  | */ | 
|  | if (dwc2_micro_frame_num(hsotg->frame_number) >= 5) { | 
|  | *skip_frames = 2 * 8; | 
|  | frame = dwc2_frame_num_inc(hsotg->frame_number, | 
|  | *skip_frames); | 
|  | } else { | 
|  | *skip_frames = 1 * 8; | 
|  | frame = dwc2_frame_num_inc(hsotg->frame_number, | 
|  | *skip_frames); | 
|  | } | 
|  |  | 
|  | frame = dwc2_full_frame_num(frame); | 
|  | } else { | 
|  | /* | 
|  | * Two frames are skipped for FS - the current and the next. | 
|  | * But for descriptor programming, 1 frame (descriptor) is | 
|  | * enough, see example above. | 
|  | */ | 
|  | *skip_frames = 1; | 
|  | frame = dwc2_frame_num_inc(hsotg->frame_number, 2); | 
|  | } | 
|  |  | 
|  | return frame; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Calculate initial descriptor index for isochronous transfer based on | 
|  | * scheduled frame | 
|  | */ | 
|  | static u16 dwc2_recalc_initial_desc_idx(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qh *qh) | 
|  | { | 
|  | u16 frame, fr_idx, fr_idx_tmp, skip_frames; | 
|  |  | 
|  | /* | 
|  | * With current ISOC processing algorithm the channel is being released | 
|  | * when no more QTDs in the list (qh->ntd == 0). Thus this function is | 
|  | * called only when qh->ntd == 0 and qh->channel == 0. | 
|  | * | 
|  | * So qh->channel != NULL branch is not used and just not removed from | 
|  | * the source file. It is required for another possible approach which | 
|  | * is, do not disable and release the channel when ISOC session | 
|  | * completed, just move QH to inactive schedule until new QTD arrives. | 
|  | * On new QTD, the QH moved back to 'ready' schedule, starting frame and | 
|  | * therefore starting desc_index are recalculated. In this case channel | 
|  | * is released only on ep_disable. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Calculate starting descriptor index. For INTERRUPT endpoint it is | 
|  | * always 0. | 
|  | */ | 
|  | if (qh->channel) { | 
|  | frame = dwc2_calc_starting_frame(hsotg, qh, &skip_frames); | 
|  | /* | 
|  | * Calculate initial descriptor index based on FrameList current | 
|  | * bitmap and servicing period | 
|  | */ | 
|  | fr_idx_tmp = dwc2_frame_list_idx(frame); | 
|  | fr_idx = (FRLISTEN_64_SIZE + | 
|  | dwc2_frame_list_idx(qh->next_active_frame) - | 
|  | fr_idx_tmp) % dwc2_frame_incr_val(qh); | 
|  | fr_idx = (fr_idx + fr_idx_tmp) % FRLISTEN_64_SIZE; | 
|  | } else { | 
|  | qh->next_active_frame = dwc2_calc_starting_frame(hsotg, qh, | 
|  | &skip_frames); | 
|  | fr_idx = dwc2_frame_list_idx(qh->next_active_frame); | 
|  | } | 
|  |  | 
|  | qh->td_first = qh->td_last = dwc2_frame_to_desc_idx(qh, fr_idx); | 
|  |  | 
|  | return skip_frames; | 
|  | } | 
|  |  | 
|  | #define ISOC_URB_GIVEBACK_ASAP | 
|  |  | 
|  | #define MAX_ISOC_XFER_SIZE_FS	1023 | 
|  | #define MAX_ISOC_XFER_SIZE_HS	3072 | 
|  | #define DESCNUM_THRESHOLD	4 | 
|  |  | 
|  | static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qtd *qtd, | 
|  | struct dwc2_qh *qh, u32 max_xfer_size, | 
|  | u16 idx) | 
|  | { | 
|  | struct dwc2_dma_desc *dma_desc = &qh->desc_list[idx]; | 
|  | struct dwc2_hcd_iso_packet_desc *frame_desc; | 
|  |  | 
|  | memset(dma_desc, 0, sizeof(*dma_desc)); | 
|  | frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; | 
|  |  | 
|  | if (frame_desc->length > max_xfer_size) | 
|  | qh->n_bytes[idx] = max_xfer_size; | 
|  | else | 
|  | qh->n_bytes[idx] = frame_desc->length; | 
|  |  | 
|  | dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); | 
|  | dma_desc->status = qh->n_bytes[idx] << HOST_DMA_ISOC_NBYTES_SHIFT & | 
|  | HOST_DMA_ISOC_NBYTES_MASK; | 
|  |  | 
|  | /* Set active bit */ | 
|  | dma_desc->status |= HOST_DMA_A; | 
|  |  | 
|  | qh->ntd++; | 
|  | qtd->isoc_frame_index_last++; | 
|  |  | 
|  | #ifdef ISOC_URB_GIVEBACK_ASAP | 
|  | /* Set IOC for each descriptor corresponding to last frame of URB */ | 
|  | if (qtd->isoc_frame_index_last == qtd->urb->packet_count) | 
|  | dma_desc->status |= HOST_DMA_IOC; | 
|  | #endif | 
|  |  | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + | 
|  | (idx * sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | } | 
|  |  | 
|  | static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qh *qh, u16 skip_frames) | 
|  | { | 
|  | struct dwc2_qtd *qtd; | 
|  | u32 max_xfer_size; | 
|  | u16 idx, inc, n_desc = 0, ntd_max = 0; | 
|  | u16 cur_idx; | 
|  | u16 next_idx; | 
|  |  | 
|  | idx = qh->td_last; | 
|  | inc = qh->host_interval; | 
|  | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); | 
|  | cur_idx = dwc2_frame_list_idx(hsotg->frame_number); | 
|  | next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed); | 
|  |  | 
|  | /* | 
|  | * Ensure current frame number didn't overstep last scheduled | 
|  | * descriptor. If it happens, the only way to recover is to move | 
|  | * qh->td_last to current frame number + 1. | 
|  | * So that next isoc descriptor will be scheduled on frame number + 1 | 
|  | * and not on a past frame. | 
|  | */ | 
|  | if (dwc2_frame_idx_num_gt(cur_idx, next_idx) || (cur_idx == next_idx)) { | 
|  | if (inc < 32) { | 
|  | dev_vdbg(hsotg->dev, | 
|  | "current frame number overstep last descriptor\n"); | 
|  | qh->td_last = dwc2_desclist_idx_inc(cur_idx, inc, | 
|  | qh->dev_speed); | 
|  | idx = qh->td_last; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (qh->host_interval) { | 
|  | ntd_max = (dwc2_max_desc_num(qh) + qh->host_interval - 1) / | 
|  | qh->host_interval; | 
|  | if (skip_frames && !qh->channel) | 
|  | ntd_max -= skip_frames / qh->host_interval; | 
|  | } | 
|  |  | 
|  | max_xfer_size = qh->dev_speed == USB_SPEED_HIGH ? | 
|  | MAX_ISOC_XFER_SIZE_HS : MAX_ISOC_XFER_SIZE_FS; | 
|  |  | 
|  | list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) { | 
|  | if (qtd->in_process && | 
|  | qtd->isoc_frame_index_last == | 
|  | qtd->urb->packet_count) | 
|  | continue; | 
|  |  | 
|  | qtd->isoc_td_first = idx; | 
|  | while (qh->ntd < ntd_max && qtd->isoc_frame_index_last < | 
|  | qtd->urb->packet_count) { | 
|  | dwc2_fill_host_isoc_dma_desc(hsotg, qtd, qh, | 
|  | max_xfer_size, idx); | 
|  | idx = dwc2_desclist_idx_inc(idx, inc, qh->dev_speed); | 
|  | n_desc++; | 
|  | } | 
|  | qtd->isoc_td_last = idx; | 
|  | qtd->in_process = 1; | 
|  | } | 
|  |  | 
|  | qh->td_last = idx; | 
|  |  | 
|  | #ifdef ISOC_URB_GIVEBACK_ASAP | 
|  | /* Set IOC for last descriptor if descriptor list is full */ | 
|  | if (qh->ntd == ntd_max) { | 
|  | idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); | 
|  | qh->desc_list[idx].status |= HOST_DMA_IOC; | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + (idx * | 
|  | sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | } | 
|  | #else | 
|  | /* | 
|  | * Set IOC bit only for one descriptor. Always try to be ahead of HW | 
|  | * processing, i.e. on IOC generation driver activates next descriptor | 
|  | * but core continues to process descriptors following the one with IOC | 
|  | * set. | 
|  | */ | 
|  |  | 
|  | if (n_desc > DESCNUM_THRESHOLD) | 
|  | /* | 
|  | * Move IOC "up". Required even if there is only one QTD | 
|  | * in the list, because QTDs might continue to be queued, | 
|  | * but during the activation it was only one queued. | 
|  | * Actually more than one QTD might be in the list if this | 
|  | * function called from XferCompletion - QTDs was queued during | 
|  | * HW processing of the previous descriptor chunk. | 
|  | */ | 
|  | idx = dwc2_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), | 
|  | qh->dev_speed); | 
|  | else | 
|  | /* | 
|  | * Set the IOC for the latest descriptor if either number of | 
|  | * descriptors is not greater than threshold or no more new | 
|  | * descriptors activated | 
|  | */ | 
|  | idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); | 
|  |  | 
|  | qh->desc_list[idx].status |= HOST_DMA_IOC; | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + | 
|  | (idx * sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | struct dwc2_qtd *qtd, struct dwc2_qh *qh, | 
|  | int n_desc) | 
|  | { | 
|  | struct dwc2_dma_desc *dma_desc = &qh->desc_list[n_desc]; | 
|  | int len = chan->xfer_len; | 
|  |  | 
|  | if (len > HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1)) | 
|  | len = HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1); | 
|  |  | 
|  | if (chan->ep_is_in) { | 
|  | int num_packets; | 
|  |  | 
|  | if (len > 0 && chan->max_packet) | 
|  | num_packets = (len + chan->max_packet - 1) | 
|  | / chan->max_packet; | 
|  | else | 
|  | /* Need 1 packet for transfer length of 0 */ | 
|  | num_packets = 1; | 
|  |  | 
|  | /* Always program an integral # of packets for IN transfers */ | 
|  | len = num_packets * chan->max_packet; | 
|  | } | 
|  |  | 
|  | dma_desc->status = len << HOST_DMA_NBYTES_SHIFT & HOST_DMA_NBYTES_MASK; | 
|  | qh->n_bytes[n_desc] = len; | 
|  |  | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL && | 
|  | qtd->control_phase == DWC2_CONTROL_SETUP) | 
|  | dma_desc->status |= HOST_DMA_SUP; | 
|  |  | 
|  | dma_desc->buf = (u32)chan->xfer_dma; | 
|  |  | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + | 
|  | (n_desc * sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  |  | 
|  | /* | 
|  | * Last (or only) descriptor of IN transfer with actual size less | 
|  | * than MaxPacket | 
|  | */ | 
|  | if (len > chan->xfer_len) { | 
|  | chan->xfer_len = 0; | 
|  | } else { | 
|  | chan->xfer_dma += len; | 
|  | chan->xfer_len -= len; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_qh *qh) | 
|  | { | 
|  | struct dwc2_qtd *qtd; | 
|  | struct dwc2_host_chan *chan = qh->channel; | 
|  | int n_desc = 0; | 
|  |  | 
|  | dev_vdbg(hsotg->dev, "%s(): qh=%p dma=%08lx len=%d\n", __func__, qh, | 
|  | (unsigned long)chan->xfer_dma, chan->xfer_len); | 
|  |  | 
|  | /* | 
|  | * Start with chan->xfer_dma initialized in assign_and_init_hc(), then | 
|  | * if SG transfer consists of multiple URBs, this pointer is re-assigned | 
|  | * to the buffer of the currently processed QTD. For non-SG request | 
|  | * there is always one QTD active. | 
|  | */ | 
|  |  | 
|  | list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) { | 
|  | dev_vdbg(hsotg->dev, "qtd=%p\n", qtd); | 
|  |  | 
|  | if (n_desc) { | 
|  | /* SG request - more than 1 QTD */ | 
|  | chan->xfer_dma = qtd->urb->dma + | 
|  | qtd->urb->actual_length; | 
|  | chan->xfer_len = qtd->urb->length - | 
|  | qtd->urb->actual_length; | 
|  | dev_vdbg(hsotg->dev, "buf=%08lx len=%d\n", | 
|  | (unsigned long)chan->xfer_dma, chan->xfer_len); | 
|  | } | 
|  |  | 
|  | qtd->n_desc = 0; | 
|  | do { | 
|  | if (n_desc > 1) { | 
|  | qh->desc_list[n_desc - 1].status |= HOST_DMA_A; | 
|  | dev_vdbg(hsotg->dev, | 
|  | "set A bit in desc %d (%p)\n", | 
|  | n_desc - 1, | 
|  | &qh->desc_list[n_desc - 1]); | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + | 
|  | ((n_desc - 1) * | 
|  | sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | } | 
|  | dwc2_fill_host_dma_desc(hsotg, chan, qtd, qh, n_desc); | 
|  | dev_vdbg(hsotg->dev, | 
|  | "desc %d (%p) buf=%08x status=%08x\n", | 
|  | n_desc, &qh->desc_list[n_desc], | 
|  | qh->desc_list[n_desc].buf, | 
|  | qh->desc_list[n_desc].status); | 
|  | qtd->n_desc++; | 
|  | n_desc++; | 
|  | } while (chan->xfer_len > 0 && | 
|  | n_desc != MAX_DMA_DESC_NUM_GENERIC); | 
|  |  | 
|  | dev_vdbg(hsotg->dev, "n_desc=%d\n", n_desc); | 
|  | qtd->in_process = 1; | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL) | 
|  | break; | 
|  | if (n_desc == MAX_DMA_DESC_NUM_GENERIC) | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (n_desc) { | 
|  | qh->desc_list[n_desc - 1].status |= | 
|  | HOST_DMA_IOC | HOST_DMA_EOL | HOST_DMA_A; | 
|  | dev_vdbg(hsotg->dev, "set IOC/EOL/A bits in desc %d (%p)\n", | 
|  | n_desc - 1, &qh->desc_list[n_desc - 1]); | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma + (n_desc - 1) * | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | if (n_desc > 1) { | 
|  | qh->desc_list[0].status |= HOST_DMA_A; | 
|  | dev_vdbg(hsotg->dev, "set A bit in desc 0 (%p)\n", | 
|  | &qh->desc_list[0]); | 
|  | dma_sync_single_for_device(hsotg->dev, | 
|  | qh->desc_list_dma, | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_TO_DEVICE); | 
|  | } | 
|  | chan->ntd = n_desc; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * dwc2_hcd_start_xfer_ddma() - Starts a transfer in Descriptor DMA mode | 
|  | * | 
|  | * @hsotg: The HCD state structure for the DWC OTG controller | 
|  | * @qh:    The QH to init | 
|  | * | 
|  | * Return: 0 if successful, negative error code otherwise | 
|  | * | 
|  | * For Control and Bulk endpoints, initializes descriptor list and starts the | 
|  | * transfer. For Interrupt and Isochronous endpoints, initializes descriptor | 
|  | * list then updates FrameList, marking appropriate entries as active. | 
|  | * | 
|  | * For Isochronous endpoints the starting descriptor index is calculated based | 
|  | * on the scheduled frame, but only on the first transfer descriptor within a | 
|  | * session. Then the transfer is started via enabling the channel. | 
|  | * | 
|  | * For Isochronous endpoints the channel is not halted on XferComplete | 
|  | * interrupt so remains assigned to the endpoint(QH) until session is done. | 
|  | */ | 
|  | void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | 
|  | { | 
|  | /* Channel is already assigned */ | 
|  | struct dwc2_host_chan *chan = qh->channel; | 
|  | u16 skip_frames = 0; | 
|  |  | 
|  | switch (chan->ep_type) { | 
|  | case USB_ENDPOINT_XFER_CONTROL: | 
|  | case USB_ENDPOINT_XFER_BULK: | 
|  | dwc2_init_non_isoc_dma_desc(hsotg, qh); | 
|  | dwc2_hc_start_transfer_ddma(hsotg, chan); | 
|  | break; | 
|  | case USB_ENDPOINT_XFER_INT: | 
|  | dwc2_init_non_isoc_dma_desc(hsotg, qh); | 
|  | dwc2_update_frame_list(hsotg, qh, 1); | 
|  | dwc2_hc_start_transfer_ddma(hsotg, chan); | 
|  | break; | 
|  | case USB_ENDPOINT_XFER_ISOC: | 
|  | if (!qh->ntd) | 
|  | skip_frames = dwc2_recalc_initial_desc_idx(hsotg, qh); | 
|  | dwc2_init_isoc_dma_desc(hsotg, qh, skip_frames); | 
|  |  | 
|  | if (!chan->xfer_started) { | 
|  | dwc2_update_frame_list(hsotg, qh, 1); | 
|  |  | 
|  | /* | 
|  | * Always set to max, instead of actual size. Otherwise | 
|  | * ntd will be changed with channel being enabled. Not | 
|  | * recommended. | 
|  | */ | 
|  | chan->ntd = dwc2_max_desc_num(qh); | 
|  |  | 
|  | /* Enable channel only once for ISOC */ | 
|  | dwc2_hc_start_transfer_ddma(hsotg, chan); | 
|  | } | 
|  |  | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | #define DWC2_CMPL_DONE		1 | 
|  | #define DWC2_CMPL_STOP		2 | 
|  |  | 
|  | static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | struct dwc2_qtd *qtd, | 
|  | struct dwc2_qh *qh, u16 idx) | 
|  | { | 
|  | struct dwc2_dma_desc *dma_desc; | 
|  | struct dwc2_hcd_iso_packet_desc *frame_desc; | 
|  | u16 remain = 0; | 
|  | int rc = 0; | 
|  |  | 
|  | if (!qtd->urb) | 
|  | return -EINVAL; | 
|  |  | 
|  | dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx * | 
|  | sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_FROM_DEVICE); | 
|  |  | 
|  | dma_desc = &qh->desc_list[idx]; | 
|  |  | 
|  | frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; | 
|  | dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); | 
|  | if (chan->ep_is_in) | 
|  | remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >> | 
|  | HOST_DMA_ISOC_NBYTES_SHIFT; | 
|  |  | 
|  | if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) { | 
|  | /* | 
|  | * XactError, or unable to complete all the transactions | 
|  | * in the scheduled micro-frame/frame, both indicated by | 
|  | * HOST_DMA_STS_PKTERR | 
|  | */ | 
|  | qtd->urb->error_count++; | 
|  | frame_desc->actual_length = qh->n_bytes[idx] - remain; | 
|  | frame_desc->status = -EPROTO; | 
|  | } else { | 
|  | /* Success */ | 
|  | frame_desc->actual_length = qh->n_bytes[idx] - remain; | 
|  | frame_desc->status = 0; | 
|  | } | 
|  |  | 
|  | if (++qtd->isoc_frame_index == qtd->urb->packet_count) { | 
|  | /* | 
|  | * urb->status is not used for isoc transfers here. The | 
|  | * individual frame_desc status are used instead. | 
|  | */ | 
|  | dwc2_host_complete(hsotg, qtd, 0); | 
|  | dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); | 
|  |  | 
|  | /* | 
|  | * This check is necessary because urb_dequeue can be called | 
|  | * from urb complete callback (sound driver for example). All | 
|  | * pending URBs are dequeued there, so no need for further | 
|  | * processing. | 
|  | */ | 
|  | if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) | 
|  | return -1; | 
|  | rc = DWC2_CMPL_DONE; | 
|  | } | 
|  |  | 
|  | qh->ntd--; | 
|  |  | 
|  | /* Stop if IOC requested descriptor reached */ | 
|  | if (dma_desc->status & HOST_DMA_IOC) | 
|  | rc = DWC2_CMPL_STOP; | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | enum dwc2_halt_status halt_status) | 
|  | { | 
|  | struct dwc2_hcd_iso_packet_desc *frame_desc; | 
|  | struct dwc2_qtd *qtd, *qtd_tmp; | 
|  | struct dwc2_qh *qh; | 
|  | u16 idx; | 
|  | int rc; | 
|  |  | 
|  | qh = chan->qh; | 
|  | idx = qh->td_first; | 
|  |  | 
|  | if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) { | 
|  | list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) | 
|  | qtd->in_process = 0; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (halt_status == DWC2_HC_XFER_AHB_ERR || | 
|  | halt_status == DWC2_HC_XFER_BABBLE_ERR) { | 
|  | /* | 
|  | * Channel is halted in these error cases, considered as serious | 
|  | * issues. | 
|  | * Complete all URBs marking all frames as failed, irrespective | 
|  | * whether some of the descriptors (frames) succeeded or not. | 
|  | * Pass error code to completion routine as well, to update | 
|  | * urb->status, some of class drivers might use it to stop | 
|  | * queing transfer requests. | 
|  | */ | 
|  | int err = halt_status == DWC2_HC_XFER_AHB_ERR ? | 
|  | -EIO : -EOVERFLOW; | 
|  |  | 
|  | list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, | 
|  | qtd_list_entry) { | 
|  | if (qtd->urb) { | 
|  | for (idx = 0; idx < qtd->urb->packet_count; | 
|  | idx++) { | 
|  | frame_desc = &qtd->urb->iso_descs[idx]; | 
|  | frame_desc->status = err; | 
|  | } | 
|  |  | 
|  | dwc2_host_complete(hsotg, qtd, err); | 
|  | } | 
|  |  | 
|  | dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); | 
|  | } | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { | 
|  | if (!qtd->in_process) | 
|  | break; | 
|  |  | 
|  | /* | 
|  | * Ensure idx corresponds to descriptor where first urb of this | 
|  | * qtd was added. In fact, during isoc desc init, dwc2 may skip | 
|  | * an index if current frame number is already over this index. | 
|  | */ | 
|  | if (idx != qtd->isoc_td_first) { | 
|  | dev_vdbg(hsotg->dev, | 
|  | "try to complete %d instead of %d\n", | 
|  | idx, qtd->isoc_td_first); | 
|  | idx = qtd->isoc_td_first; | 
|  | } | 
|  |  | 
|  | do { | 
|  | struct dwc2_qtd *qtd_next; | 
|  | u16 cur_idx; | 
|  |  | 
|  | rc = dwc2_cmpl_host_isoc_dma_desc(hsotg, chan, qtd, qh, | 
|  | idx); | 
|  | if (rc < 0) | 
|  | return; | 
|  | idx = dwc2_desclist_idx_inc(idx, qh->host_interval, | 
|  | chan->speed); | 
|  | if (!rc) | 
|  | continue; | 
|  |  | 
|  | if (rc == DWC2_CMPL_DONE) | 
|  | break; | 
|  |  | 
|  | /* rc == DWC2_CMPL_STOP */ | 
|  |  | 
|  | if (qh->host_interval >= 32) | 
|  | goto stop_scan; | 
|  |  | 
|  | qh->td_first = idx; | 
|  | cur_idx = dwc2_frame_list_idx(hsotg->frame_number); | 
|  | qtd_next = list_first_entry(&qh->qtd_list, | 
|  | struct dwc2_qtd, | 
|  | qtd_list_entry); | 
|  | if (dwc2_frame_idx_num_gt(cur_idx, | 
|  | qtd_next->isoc_td_last)) | 
|  | break; | 
|  |  | 
|  | goto stop_scan; | 
|  |  | 
|  | } while (idx != qh->td_first); | 
|  | } | 
|  |  | 
|  | stop_scan: | 
|  | qh->td_first = idx; | 
|  | } | 
|  |  | 
|  | static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | struct dwc2_qtd *qtd, | 
|  | struct dwc2_dma_desc *dma_desc, | 
|  | enum dwc2_halt_status halt_status, | 
|  | u32 n_bytes, int *xfer_done) | 
|  | { | 
|  | struct dwc2_hcd_urb *urb = qtd->urb; | 
|  | u16 remain = 0; | 
|  |  | 
|  | if (chan->ep_is_in) | 
|  | remain = (dma_desc->status & HOST_DMA_NBYTES_MASK) >> | 
|  | HOST_DMA_NBYTES_SHIFT; | 
|  |  | 
|  | dev_vdbg(hsotg->dev, "remain=%d dwc2_urb=%p\n", remain, urb); | 
|  |  | 
|  | if (halt_status == DWC2_HC_XFER_AHB_ERR) { | 
|  | dev_err(hsotg->dev, "EIO\n"); | 
|  | urb->status = -EIO; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) { | 
|  | switch (halt_status) { | 
|  | case DWC2_HC_XFER_STALL: | 
|  | dev_vdbg(hsotg->dev, "Stall\n"); | 
|  | urb->status = -EPIPE; | 
|  | break; | 
|  | case DWC2_HC_XFER_BABBLE_ERR: | 
|  | dev_err(hsotg->dev, "Babble\n"); | 
|  | urb->status = -EOVERFLOW; | 
|  | break; | 
|  | case DWC2_HC_XFER_XACT_ERR: | 
|  | dev_err(hsotg->dev, "XactErr\n"); | 
|  | urb->status = -EPROTO; | 
|  | break; | 
|  | default: | 
|  | dev_err(hsotg->dev, | 
|  | "%s: Unhandled descriptor error status (%d)\n", | 
|  | __func__, halt_status); | 
|  | break; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if (dma_desc->status & HOST_DMA_A) { | 
|  | dev_vdbg(hsotg->dev, | 
|  | "Active descriptor encountered on channel %d\n", | 
|  | chan->hc_num); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL) { | 
|  | if (qtd->control_phase == DWC2_CONTROL_DATA) { | 
|  | urb->actual_length += n_bytes - remain; | 
|  | if (remain || urb->actual_length >= urb->length) { | 
|  | /* | 
|  | * For Control Data stage do not set urb->status | 
|  | * to 0, to prevent URB callback. Set it when | 
|  | * Status phase is done. See below. | 
|  | */ | 
|  | *xfer_done = 1; | 
|  | } | 
|  | } else if (qtd->control_phase == DWC2_CONTROL_STATUS) { | 
|  | urb->status = 0; | 
|  | *xfer_done = 1; | 
|  | } | 
|  | /* No handling for SETUP stage */ | 
|  | } else { | 
|  | /* BULK and INTR */ | 
|  | urb->actual_length += n_bytes - remain; | 
|  | dev_vdbg(hsotg->dev, "length=%d actual=%d\n", urb->length, | 
|  | urb->actual_length); | 
|  | if (remain || urb->actual_length >= urb->length) { | 
|  | urb->status = 0; | 
|  | *xfer_done = 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | int chnum, struct dwc2_qtd *qtd, | 
|  | int desc_num, | 
|  | enum dwc2_halt_status halt_status, | 
|  | int *xfer_done) | 
|  | { | 
|  | struct dwc2_qh *qh = chan->qh; | 
|  | struct dwc2_hcd_urb *urb = qtd->urb; | 
|  | struct dwc2_dma_desc *dma_desc; | 
|  | u32 n_bytes; | 
|  | int failed; | 
|  |  | 
|  | dev_vdbg(hsotg->dev, "%s()\n", __func__); | 
|  |  | 
|  | if (!urb) | 
|  | return -EINVAL; | 
|  |  | 
|  | dma_sync_single_for_cpu(hsotg->dev, | 
|  | qh->desc_list_dma + (desc_num * | 
|  | sizeof(struct dwc2_dma_desc)), | 
|  | sizeof(struct dwc2_dma_desc), | 
|  | DMA_FROM_DEVICE); | 
|  |  | 
|  | dma_desc = &qh->desc_list[desc_num]; | 
|  | n_bytes = qh->n_bytes[desc_num]; | 
|  | dev_vdbg(hsotg->dev, | 
|  | "qtd=%p dwc2_urb=%p desc_num=%d desc=%p n_bytes=%d\n", | 
|  | qtd, urb, desc_num, dma_desc, n_bytes); | 
|  | failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc, | 
|  | halt_status, n_bytes, | 
|  | xfer_done); | 
|  | if (failed || (*xfer_done && urb->status != -EINPROGRESS)) { | 
|  | dwc2_host_complete(hsotg, qtd, urb->status); | 
|  | dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); | 
|  | dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n", | 
|  | failed, *xfer_done); | 
|  | return failed; | 
|  | } | 
|  |  | 
|  | if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL) { | 
|  | switch (qtd->control_phase) { | 
|  | case DWC2_CONTROL_SETUP: | 
|  | if (urb->length > 0) | 
|  | qtd->control_phase = DWC2_CONTROL_DATA; | 
|  | else | 
|  | qtd->control_phase = DWC2_CONTROL_STATUS; | 
|  | dev_vdbg(hsotg->dev, | 
|  | "  Control setup transaction done\n"); | 
|  | break; | 
|  | case DWC2_CONTROL_DATA: | 
|  | if (*xfer_done) { | 
|  | qtd->control_phase = DWC2_CONTROL_STATUS; | 
|  | dev_vdbg(hsotg->dev, | 
|  | "  Control data transfer done\n"); | 
|  | } else if (desc_num + 1 == qtd->n_desc) { | 
|  | /* | 
|  | * Last descriptor for Control data stage which | 
|  | * is not completed yet | 
|  | */ | 
|  | dwc2_hcd_save_data_toggle(hsotg, chan, chnum, | 
|  | qtd); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, | 
|  | int chnum, | 
|  | enum dwc2_halt_status halt_status) | 
|  | { | 
|  | struct list_head *qtd_item, *qtd_tmp; | 
|  | struct dwc2_qh *qh = chan->qh; | 
|  | struct dwc2_qtd *qtd = NULL; | 
|  | int xfer_done; | 
|  | int desc_num = 0; | 
|  |  | 
|  | if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) { | 
|  | list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) | 
|  | qtd->in_process = 0; | 
|  | return; | 
|  | } | 
|  |  | 
|  | list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) { | 
|  | int i; | 
|  | int qtd_desc_count; | 
|  |  | 
|  | qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry); | 
|  | xfer_done = 0; | 
|  | qtd_desc_count = qtd->n_desc; | 
|  |  | 
|  | for (i = 0; i < qtd_desc_count; i++) { | 
|  | if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd, | 
|  | desc_num, halt_status, | 
|  | &xfer_done)) { | 
|  | qtd = NULL; | 
|  | goto stop_scan; | 
|  | } | 
|  |  | 
|  | desc_num++; | 
|  | } | 
|  | } | 
|  |  | 
|  | stop_scan: | 
|  | if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) { | 
|  | /* | 
|  | * Resetting the data toggle for bulk and interrupt endpoints | 
|  | * in case of stall. See handle_hc_stall_intr(). | 
|  | */ | 
|  | if (halt_status == DWC2_HC_XFER_STALL) | 
|  | qh->data_toggle = DWC2_HC_PID_DATA0; | 
|  | else | 
|  | dwc2_hcd_save_data_toggle(hsotg, chan, chnum, NULL); | 
|  | } | 
|  |  | 
|  | if (halt_status == DWC2_HC_XFER_COMPLETE) { | 
|  | if (chan->hcint & HCINTMSK_NYET) { | 
|  | /* | 
|  | * Got a NYET on the last transaction of the transfer. | 
|  | * It means that the endpoint should be in the PING | 
|  | * state at the beginning of the next transfer. | 
|  | */ | 
|  | qh->ping_state = 1; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * dwc2_hcd_complete_xfer_ddma() - Scans the descriptor list, updates URB's | 
|  | * status and calls completion routine for the URB if it's done. Called from | 
|  | * interrupt handlers. | 
|  | * | 
|  | * @hsotg:       The HCD state structure for the DWC OTG controller | 
|  | * @chan:        Host channel the transfer is completed on | 
|  | * @chnum:       Index of Host channel registers | 
|  | * @halt_status: Reason the channel is being halted or just XferComplete | 
|  | *               for isochronous transfers | 
|  | * | 
|  | * Releases the channel to be used by other transfers. | 
|  | * In case of Isochronous endpoint the channel is not halted until the end of | 
|  | * the session, i.e. QTD list is empty. | 
|  | * If periodic channel released the FrameList is updated accordingly. | 
|  | * Calls transaction selection routines to activate pending transfers. | 
|  | */ | 
|  | void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg, | 
|  | struct dwc2_host_chan *chan, int chnum, | 
|  | enum dwc2_halt_status halt_status) | 
|  | { | 
|  | struct dwc2_qh *qh = chan->qh; | 
|  | int continue_isoc_xfer = 0; | 
|  | enum dwc2_transaction_type tr_type; | 
|  |  | 
|  | if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) { | 
|  | dwc2_complete_isoc_xfer_ddma(hsotg, chan, halt_status); | 
|  |  | 
|  | /* Release the channel if halted or session completed */ | 
|  | if (halt_status != DWC2_HC_XFER_COMPLETE || | 
|  | list_empty(&qh->qtd_list)) { | 
|  | struct dwc2_qtd *qtd, *qtd_tmp; | 
|  |  | 
|  | /* | 
|  | * Kill all remainings QTDs since channel has been | 
|  | * halted. | 
|  | */ | 
|  | list_for_each_entry_safe(qtd, qtd_tmp, | 
|  | &qh->qtd_list, | 
|  | qtd_list_entry) { | 
|  | dwc2_host_complete(hsotg, qtd, | 
|  | -ECONNRESET); | 
|  | dwc2_hcd_qtd_unlink_and_free(hsotg, | 
|  | qtd, qh); | 
|  | } | 
|  |  | 
|  | /* Halt the channel if session completed */ | 
|  | if (halt_status == DWC2_HC_XFER_COMPLETE) | 
|  | dwc2_hc_halt(hsotg, chan, halt_status); | 
|  | dwc2_release_channel_ddma(hsotg, qh); | 
|  | dwc2_hcd_qh_unlink(hsotg, qh); | 
|  | } else { | 
|  | /* Keep in assigned schedule to continue transfer */ | 
|  | list_move_tail(&qh->qh_list_entry, | 
|  | &hsotg->periodic_sched_assigned); | 
|  | /* | 
|  | * If channel has been halted during giveback of urb | 
|  | * then prevent any new scheduling. | 
|  | */ | 
|  | if (!chan->halt_status) | 
|  | continue_isoc_xfer = 1; | 
|  | } | 
|  | /* | 
|  | * Todo: Consider the case when period exceeds FrameList size. | 
|  | * Frame Rollover interrupt should be used. | 
|  | */ | 
|  | } else { | 
|  | /* | 
|  | * Scan descriptor list to complete the URB(s), then release | 
|  | * the channel | 
|  | */ | 
|  | dwc2_complete_non_isoc_xfer_ddma(hsotg, chan, chnum, | 
|  | halt_status); | 
|  | dwc2_release_channel_ddma(hsotg, qh); | 
|  | dwc2_hcd_qh_unlink(hsotg, qh); | 
|  |  | 
|  | if (!list_empty(&qh->qtd_list)) { | 
|  | /* | 
|  | * Add back to inactive non-periodic schedule on normal | 
|  | * completion | 
|  | */ | 
|  | dwc2_hcd_qh_add(hsotg, qh); | 
|  | } | 
|  | } | 
|  |  | 
|  | tr_type = dwc2_hcd_select_transactions(hsotg); | 
|  | if (tr_type != DWC2_TRANSACTION_NONE || continue_isoc_xfer) { | 
|  | if (continue_isoc_xfer) { | 
|  | if (tr_type == DWC2_TRANSACTION_NONE) | 
|  | tr_type = DWC2_TRANSACTION_PERIODIC; | 
|  | else if (tr_type == DWC2_TRANSACTION_NON_PERIODIC) | 
|  | tr_type = DWC2_TRANSACTION_ALL; | 
|  | } | 
|  | dwc2_hcd_queue_transactions(hsotg, tr_type); | 
|  | } | 
|  | } |