]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blobdiff - drivers/usb/musb/cppi41_dma.c
musb: adding support for am335x
[sitara-epos/sitara-epos-kernel.git] / drivers / usb / musb / cppi41_dma.c
index 157f15e109adc801641274fb7d79d33415bc0354..b553d49931b1a8a03e946db1cbb1db054ed6332b 100644 (file)
@@ -32,8 +32,8 @@
 /* Configuration */
 #define USB_CPPI41_DESC_SIZE_SHIFT 6
 #define USB_CPPI41_DESC_ALIGN  (1 << USB_CPPI41_DESC_SIZE_SHIFT)
-#define USB_CPPI41_CH_NUM_PD   64      /* 4K bulk data at full speed */
-#define USB_CPPI41_MAX_PD      (USB_CPPI41_CH_NUM_PD * USB_CPPI41_NUM_CH)
+#define USB_CPPI41_CH_NUM_PD   128     /* 4K bulk data at full speed */
+#define USB_CPPI41_MAX_PD      (USB_CPPI41_CH_NUM_PD * (USB_CPPI41_NUM_CH+1))
 
 #undef DEBUG_CPPI_TD
 #undef USBDRV_DEBUG
@@ -55,13 +55,15 @@ struct usb_pkt_desc;
 
 struct usb_pkt_desc {
        /* Hardware descriptor fields from this point */
-       struct cppi41_host_pkt_desc hw_desc;
+       struct cppi41_host_pkt_desc hw_desc;    /* 40 bytes */
        /* Protocol specific data */
-       dma_addr_t dma_addr;
-       struct usb_pkt_desc *next_pd_ptr;
+       dma_addr_t dma_addr;                    /* offs:44 byte */
+       struct usb_pkt_desc *next_pd_ptr;       /* offs:48 byte*/
        u8 ch_num;
        u8 ep_num;
        u8 eop;
+       u8 res1;                                /* offs:52 */
+       u8 res2[12];                            /* offs:64 */
 };
 
 /**
@@ -96,6 +98,8 @@ struct cppi41_channel {
        u16 pkt_size;
        u8  transfer_mode;
        u8  zlp_queued;
+       u8  inf_mode;
+       u8  tx_complete;
 };
 
 /**
@@ -110,6 +114,7 @@ struct cppi41 {
 
        struct cppi41_channel tx_cppi_ch[USB_CPPI41_NUM_CH];
        struct cppi41_channel rx_cppi_ch[USB_CPPI41_NUM_CH];
+       struct work_struct      txdma_work;
 
        struct usb_pkt_desc *pd_pool_head; /* Free PD pool head */
        dma_addr_t pd_mem_phys;         /* PD memory physical address */
@@ -124,6 +129,8 @@ struct cppi41 {
        u8 en_bd_intr;                  /* enable bd interrupt */
        u32 automode_reg_offs;          /* USB_AUTOREQ_REG offset */
        u32 teardown_reg_offs;          /* USB_TEARDOWN_REG offset */
+       u32 bd_size;
+       u8  inf_mode;
 };
 
 struct usb_cppi41_info usb_cppi41_info[2];
@@ -184,7 +191,7 @@ static int __devinit cppi41_controller_start(struct dma_controller *controller)
        cppi_info = cppi->cppi_info;
        musb = cppi->musb;
 
-       if (cpu_is_ti81xx()) {
+       if (cpu_is_ti816x() || cpu_is_am33xx()) {
                cppi->automode_reg_offs = TI81XX_USB_AUTOREQ_REG;
                cppi->teardown_reg_offs = TI81XX_USB_TEARDOWN_REG;
        } else {
@@ -203,15 +210,16 @@ static int __devinit cppi41_controller_start(struct dma_controller *controller)
         * dma_alloc_coherent()  will return a page aligned address, so our
         * alignment requirement will be honored.
         */
+       cppi->bd_size = USB_CPPI41_MAX_PD * sizeof(struct usb_pkt_desc);
        cppi->pd_mem = dma_alloc_coherent(cppi->musb->controller,
-                                         USB_CPPI41_MAX_PD *
-                                         USB_CPPI41_DESC_ALIGN,
+                                         cppi->bd_size,
                                          &cppi->pd_mem_phys,
                                          GFP_KERNEL | GFP_DMA);
        if (cppi->pd_mem == NULL) {
                dev_dbg(musb->controller, "ERROR: packet descriptor memory allocation failed\n");
                return 0;
        }
+
        if (cppi41_mem_rgn_alloc(cppi_info->q_mgr, cppi->pd_mem_phys,
                                 USB_CPPI41_DESC_SIZE_SHIFT,
                                 get_count_order(USB_CPPI41_MAX_PD),
@@ -310,7 +318,7 @@ static int __devinit cppi41_controller_start(struct dma_controller *controller)
 
  free_pds:
        dma_free_coherent(cppi->musb->controller,
-                         USB_CPPI41_MAX_PD * USB_CPPI41_DESC_ALIGN,
+                         cppi->bd_size,
                          cppi->pd_mem, cppi->pd_mem_phys);
 
        return 0;
@@ -333,11 +341,6 @@ static int cppi41_controller_stop(struct dma_controller *controller)
        cppi_info = cppi->cppi_info;
        musb = cppi->musb;
 
-       /*
-        * pop all the teardwon descriptor queued to tdQueue
-        */
-       cppi41_free_teardown_queue(0);
-
        /* Free the teardown completion queue */
        if (cppi41_queue_free(cppi_info->q_mgr, cppi->teardownQNum))
                dev_dbg(musb->controller, "ERROR: failed to free teardown completion queue\n");
@@ -349,10 +352,14 @@ static int cppi41_controller_stop(struct dma_controller *controller)
        if (cppi41_mem_rgn_free(cppi_info->q_mgr, cppi->pd_mem_rgn))
                dev_dbg(musb->controller, "ERROR: failed to free queue manager memory region\n");
 
-       dma_free_coherent(cppi->musb->controller,
-                         USB_CPPI41_MAX_PD * USB_CPPI41_DESC_ALIGN,
+       dma_free_coherent(cppi->musb->controller, cppi->bd_size,
                          cppi->pd_mem, cppi->pd_mem_phys);
 
+       cppi->pd_mem = 0;
+       cppi->pd_mem_phys = 0;
+       cppi->pd_pool_head = 0;
+       cppi->bd_size = 0;
+
        reg_base = cppi->musb->ctrl_base;
 
        /* Disable auto request mode */
@@ -442,6 +449,7 @@ static struct dma_channel *cppi41_channel_alloc(struct dma_controller
                rx_cfg.default_desc_type = cppi41_rx_host_desc;
                rx_cfg.sop_offset = 0;
                rx_cfg.retry_starved = 1;
+               rx_cfg.rx_max_buf_cnt = 0;
                rx_cfg.rx_queue.q_mgr = cppi_ch->src_queue.q_mgr = q_mgr;
                rx_cfg.rx_queue.q_num = cppi_info->rx_comp_q[ch_num];
                for (i = 0; i < 4; i++)
@@ -570,15 +578,15 @@ static unsigned cppi41_next_tx_segment(struct cppi41_channel *tx_ch)
         * transfer in one PD and one IRQ.  The only time we would NOT want
         * to use it is when the hardware constraints prevent it...
         */
-       if ((pkt_size & 0x3f) == 0 && length > pkt_size) {
-               num_pds  = 1;
-               pkt_size = length;
+       if ((pkt_size & 0x3f) == 0) {
+               num_pds  = length ? 1 : 0;
                cppi41_mode_update(tx_ch, USB_GENERIC_RNDIS_MODE);
        } else {
                num_pds  = (length + pkt_size - 1) / pkt_size;
                cppi41_mode_update(tx_ch, USB_TRANSPARENT_MODE);
        }
 
+       pkt_size = length;
        /*
         * If length of transmit buffer is 0 or a multiple of the endpoint size,
         * then send the zero length packet.
@@ -661,6 +669,10 @@ static void cppi41_set_ep_size(struct cppi41_channel *rx_ch, u32 pkt_size)
        struct cppi41 *cppi = rx_ch->channel.private_data;
        void *__iomem reg_base = cppi->musb->ctrl_base;
        u8 ep_num = rx_ch->ch_num + 1;
+       u32 res = pkt_size % 64;
+
+       /* epsize register must be multiple of 64 */
+       pkt_size += res ? (64 - res) : res;
 
        musb_writel(reg_base, USB_GENERIC_RNDIS_EP_SIZE_REG(ep_num), pkt_size);
 }
@@ -741,44 +753,51 @@ static unsigned cppi41_next_rx_segment(struct cppi41_channel *rx_ch)
        u32 max_rx_transfer_size = 64 * 1024;
        u32 i, n_bd , pkt_len;
        struct usb_gadget_driver *gadget_driver;
-       u8 en_bd_intr = cppi->en_bd_intr;
+       u8 en_bd_intr = cppi->en_bd_intr, mode;
 
        if (is_peripheral_active(cppi->musb)) {
                /* TODO: temporary fix for CDC/RNDIS which needs to be in
                 * GENERIC_RNDIS mode. Without this RNDIS gadget taking
                 * more then 2K ms for a 64 byte pings.
                 */
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
                gadget_driver = cppi->musb->gadget_driver;
-#endif
-               if (!strcmp(gadget_driver->driver.name, "g_ether")) {
-                       cppi41_mode_update(rx_ch, USB_GENERIC_RNDIS_MODE);
-               } else {
-                       max_rx_transfer_size = 512;
-                       cppi41_mode_update(rx_ch, USB_TRANSPARENT_MODE);
-               }
-               pkt_len = 0;
-               if (rx_ch->length < max_rx_transfer_size)
-                       pkt_len = rx_ch->length;
-               cppi41_set_ep_size(rx_ch, pkt_len);
+
+               pkt_len = rx_ch->pkt_size;
+               mode = USB_GENERIC_RNDIS_MODE;
+               if (!strcmp(gadget_driver->driver.name, "g_file_storage")) {
+                       if (cppi->inf_mode && length > pkt_len) {
+                               pkt_len = 0;
+                               length = length - rx_ch->pkt_size;
+                               cppi41_rx_ch_set_maxbufcnt(&rx_ch->dma_ch_obj,
+                                       DMA_CH_RX_MAX_BUF_CNT_1);
+                               rx_ch->inf_mode = 1;
+                       } else {
+                               max_rx_transfer_size = rx_ch->pkt_size;
+                               mode = USB_TRANSPARENT_MODE;
+                       }
+               } else
+                       if (rx_ch->length < max_rx_transfer_size)
+                               pkt_len = rx_ch->length;
+
+               if (mode != USB_TRANSPARENT_MODE)
+                       cppi41_set_ep_size(rx_ch, pkt_len);
+               cppi41_mode_update(rx_ch, mode);
        } else {
                /*
                 * Rx can use the generic RNDIS mode where we can
                 * probably fit this transfer in one PD and one IRQ
                 * (or two with a short packet).
                 */
-               if ((pkt_size & 0x3f) == 0 && length >= 2 * pkt_size) {
+               if ((pkt_size & 0x3f) == 0) {
                        cppi41_mode_update(rx_ch, USB_GENERIC_RNDIS_MODE);
                        cppi41_autoreq_update(rx_ch, USB_AUTOREQ_ALL_BUT_EOP);
 
-                       if (likely(length < 0x10000))
-                               pkt_size = length - length % pkt_size;
-                       else
-                               pkt_size = 0x10000;
+                       pkt_size = (length > 0x10000) ? 0x10000 : length;
                        cppi41_set_ep_size(rx_ch, pkt_size);
                } else {
                        cppi41_mode_update(rx_ch, USB_TRANSPARENT_MODE);
                        cppi41_autoreq_update(rx_ch, USB_NO_AUTOREQ);
+                       max_rx_transfer_size = rx_ch->pkt_size;
                }
        }
 
@@ -803,9 +822,16 @@ static unsigned cppi41_next_rx_segment(struct cppi41_channel *rx_ch)
                (length > max_rx_transfer_size) ? max_rx_transfer_size : length;
 
                hw_desc = &curr_pd->hw_desc;
+               hw_desc->desc_info = (CPPI41_DESC_TYPE_HOST <<
+                                     CPPI41_DESC_TYPE_SHIFT);
                hw_desc->orig_buf_ptr = rx_ch->start_addr + rx_ch->curr_offset;
                hw_desc->orig_buf_len = pkt_len;
 
+               /* buf_len field of buffer descriptor updated by dma
+                * after reception of data is completed
+                */
+               hw_desc->buf_len = 0;
+
                curr_pd->ch_num = rx_ch->ch_num;
                curr_pd->ep_num = rx_ch->end_pt->epnum;
 
@@ -951,6 +977,8 @@ static void usb_tx_ch_teardown(struct cppi41_channel *tx_ch)
        u32 td_reg, timeout = 0xfffff;
        u8 ep_num = tx_ch->ch_num + 1;
        unsigned long pd_addr;
+       struct cppi41_queue_obj tx_queue_obj;
+       struct usb_cppi41_info *cppi_info;
 
        /* Initiate teardown for Tx DMA channel */
        cppi41_dma_ch_teardown(&tx_ch->dma_ch_obj);
@@ -966,11 +994,11 @@ static void usb_tx_ch_teardown(struct cppi41_channel *tx_ch)
 
        if (pd_addr) {
 
-               dprintk("Descriptor (%08lx) popped from teardown completion "
+               dev_dbg(musb->controller, "Descriptor (%08lx) popped from teardown completion "
                        "queue\n", pd_addr);
 
                if (usb_check_teardown(tx_ch, pd_addr)) {
-                       dprintk("Teardown Desc (%p) rcvd\n", pd_addr);
+                       dev_dbg(musb->controller, "Teardown Desc (%lx) rcvd\n", pd_addr);
                } else
                        ERR("Invalid PD(%08lx)popped from TearDn completion"
                                "queue\n", pd_addr);
@@ -978,6 +1006,33 @@ static void usb_tx_ch_teardown(struct cppi41_channel *tx_ch)
                if (timeout <= 0)
                        ERR("Teardown Desc not rcvd\n");
        }
+
+       /* read the tx completion queue and remove
+        * completion bd if any
+        */
+       cppi_info = cppi->cppi_info;
+       if (cppi41_queue_init(&tx_queue_obj, cppi_info->q_mgr,
+                             cppi_info->tx_comp_q[tx_ch->ch_num])) {
+               ERR("ERROR: cppi41_queue_init failed for "
+                   "Tx completion queue");
+               return;
+       }
+
+       while ((pd_addr = cppi41_queue_pop(&tx_queue_obj)) != 0) {
+               struct usb_pkt_desc *curr_pd;
+
+               curr_pd = usb_get_pd_ptr(cppi, pd_addr);
+               if (curr_pd == NULL) {
+                       ERR("Invalid PD popped from Tx completion queue\n");
+                       continue;
+               }
+
+               dev_dbg(musb->controller, "Tx-PD(%p) popped from completion queue\n", curr_pd);
+               dev_dbg(musb->controller, "ch(%d)epnum(%d)len(%d)\n", curr_pd->ch_num,
+                       curr_pd->ep_num, curr_pd->hw_desc.buf_len);
+
+               usb_put_free_pd(cppi, curr_pd);
+       }
 }
 
 /*
@@ -989,8 +1044,10 @@ static void usb_tx_ch_teardown(struct cppi41_channel *tx_ch)
 static void usb_rx_ch_teardown(struct cppi41_channel *rx_ch)
 {
        struct cppi41 *cppi = rx_ch->channel.private_data;
+       struct musb *musb = cppi->musb;
        struct usb_cppi41_info *cppi_info = cppi->cppi_info;
-       u32 timeout = 0xfffff;
+       u32 timeout = 0xfffff, pd_addr;
+       struct cppi41_queue_obj rx_queue_obj;
 
        cppi41_dma_ch_default_queue(&rx_ch->dma_ch_obj, 0, cppi->teardownQNum);
 
@@ -1011,7 +1068,7 @@ static void usb_rx_ch_teardown(struct cppi41_channel *rx_ch)
                        break;
                }
 
-               dprintk("Descriptor (%08lx) popped from teardown completion "
+               dev_dbg(musb->controller, "Descriptor (%08lx) popped from teardown completion "
                        "queue\n", pd_addr);
 
                /*
@@ -1043,6 +1100,32 @@ static void usb_rx_ch_teardown(struct cppi41_channel *rx_ch)
                usb_put_free_pd(cppi, curr_pd);
        } while (0);
 
+       /* read the rx completion queue and remove
+        * completion bd if any
+        */
+       if (cppi41_queue_init(&rx_queue_obj, cppi_info->q_mgr,
+                             cppi_info->rx_comp_q[rx_ch->ch_num])) {
+               ERR("ERROR: cppi41_queue_init failed for "
+                   "Rx completion queue");
+               return;
+       }
+
+       while ((pd_addr = cppi41_queue_pop(&rx_queue_obj)) != 0) {
+               struct usb_pkt_desc *curr_pd;
+
+               curr_pd = usb_get_pd_ptr(cppi, pd_addr);
+               if (curr_pd == NULL) {
+                       ERR("Invalid PD popped from Rx completion queue\n");
+                       continue;
+               }
+
+               dev_dbg(musb->controller, "Rx-PD(%p) popped from completion queue\n", curr_pd);
+               dev_dbg(musb->controller, "ch(%d)epnum(%d)len(%d)\n", curr_pd->ch_num,
+                       curr_pd->ep_num, curr_pd->hw_desc.buf_len);
+
+               usb_put_free_pd(cppi, curr_pd);
+       }
+
        /* Now restore the default Rx completion queue... */
        cppi41_dma_ch_default_queue(&rx_ch->dma_ch_obj, cppi_info->q_mgr,
                                    cppi_info->rx_comp_q[rx_ch->ch_num]);
@@ -1110,6 +1193,7 @@ static int cppi41_channel_abort(struct dma_channel *channel)
                csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_H_WZC_BITS;
                musb_writew(epio, MUSB_TXCSR, csr);
                musb_writew(epio, MUSB_TXCSR, csr);
+               cppi_ch->tx_complete = 0;
        } else { /* Rx */
                dprintk("Rx channel teardown, cppi_ch = %p\n", cppi_ch);
 
@@ -1188,6 +1272,63 @@ static int cppi41_channel_abort(struct dma_channel *channel)
        return 0;
 }
 
+void txdma_completion_work(struct work_struct *data)
+{
+       struct cppi41 *cppi = container_of(data, struct cppi41, txdma_work);
+       struct cppi41_channel *tx_ch;
+       struct musb *musb = cppi->musb;
+       unsigned index;
+       u8 resched = 0;
+       unsigned long flags;
+
+       while (1) {
+               for (index = 0; index < USB_CPPI41_NUM_CH; index++) {
+                       void __iomem *epio;
+                       u16 csr;
+
+                       tx_ch = &cppi->tx_cppi_ch[index];
+                       spin_lock_irqsave(&musb->lock, flags);
+                       if (tx_ch->tx_complete) {
+                               /* Sometimes a EP can unregister from a DMA
+                                * channel while the data is still in the FIFO.
+                                * Probable reason a proper abort was not
+                                * called before taking such a step.
+                                * Protect against such cases.
+                                */
+                               if (!tx_ch->end_pt) {
+                                       tx_ch->tx_complete = 0;
+                                       continue;
+                               }
+
+                               epio = tx_ch->end_pt->regs;
+                               csr = musb_readw(epio, MUSB_TXCSR);
+
+                               if (csr & (MUSB_TXCSR_TXPKTRDY |
+                                       MUSB_TXCSR_FIFONOTEMPTY)) {
+                                       resched = 1;
+                               } else {
+                                       tx_ch->channel.status =
+                                               MUSB_DMA_STATUS_FREE;
+                                       tx_ch->tx_complete = 0;
+                                       musb_dma_completion(musb, index+1, 1);
+                               }
+                       }
+                       spin_unlock_irqrestore(&musb->lock, flags);
+
+                       if (!resched)
+                               cond_resched();
+               }
+
+               if (resched) {
+                       resched = 0;
+                       cond_resched();
+               } else {
+                       return ;
+               }
+       }
+
+}
+
 /**
  * cppi41_dma_controller_create -
  * instantiate an object representing DMA controller.
@@ -1211,6 +1352,13 @@ cppi41_dma_controller_create(struct musb  *musb, void __iomem *mregs)
        cppi->controller.channel_abort = cppi41_channel_abort;
        cppi->cppi_info = (struct usb_cppi41_info *)&usb_cppi41_info[musb->id];;
        cppi->en_bd_intr = cppi->cppi_info->bd_intr_ctrl;
+       INIT_WORK(&cppi->txdma_work, txdma_completion_work);
+
+       /* enable infinite mode only for ti81xx silicon rev2 */
+       if (cpu_is_am33xx() || cpu_is_ti816x()) {
+               dev_dbg(musb->controller, "cppi41dma supports infinite mode\n");
+               cppi->inf_mode = 1;
+       }
 
        return &cppi->controller;
 }
@@ -1276,8 +1424,6 @@ static void usb_process_tx_queue(struct cppi41 *cppi, unsigned index)
                    (tx_ch->transfer_mode && !tx_ch->zlp_queued))
                        cppi41_next_tx_segment(tx_ch);
                else if (tx_ch->channel.actual_len >= tx_ch->length) {
-                       tx_ch->channel.status = MUSB_DMA_STATUS_FREE;
-
                        /*
                         * We get Tx DMA completion interrupt even when
                         * data is still in FIFO and not moved out to
@@ -1286,9 +1432,8 @@ static void usb_process_tx_queue(struct cppi41 *cppi, unsigned index)
                         * USB functionality. So far, we have obsered
                         * failure with iperf.
                         */
-                       udelay(20);
-                       /* Tx completion routine callback */
-                       musb_dma_completion(cppi->musb, ep_num, 1);
+                       tx_ch->tx_complete = 1;
+                       schedule_work(&cppi->txdma_work);
                }
        }
 }
@@ -1311,7 +1456,7 @@ static void usb_process_rx_queue(struct cppi41 *cppi, unsigned index)
                struct usb_pkt_desc *curr_pd;
                struct cppi41_channel *rx_ch;
                u8 ch_num, ep_num;
-               u32 length, orig_buf_len;
+               u32 length = 0, orig_buf_len, timeout = 50;
 
                curr_pd = usb_get_pd_ptr(cppi, pd_addr);
                if (curr_pd == NULL) {
@@ -1319,10 +1464,28 @@ static void usb_process_rx_queue(struct cppi41 *cppi, unsigned index)
                        continue;
                }
 
+               /* This delay is required to overcome the dma race condition
+                * where software reads buffer descriptor before being updated
+                * by dma as buffer descriptor's writes by dma still pending in
+                * interconnect bridge.
+                */
+               while (timeout--) {
+                       length = curr_pd->hw_desc.desc_info &
+                                       CPPI41_PKT_LEN_MASK;
+                       if (length != 0)
+                               break;
+                       udelay(1);
+               }
+
+               if (length == 0)
+                       ERR("!Race condtion: rxBD read before updated by dma");
+
                /* Extract the data from received packet descriptor */
                ch_num = curr_pd->ch_num;
                ep_num = curr_pd->ep_num;
-               length = curr_pd->hw_desc.buf_len;
+
+               dev_dbg(musb->controller, "Rx complete: dma channel(%d) ep%d len %d timeout %d\n",
+                       ch_num, ep_num, length, (50-timeout));
 
                rx_ch = &cppi->rx_cppi_ch[ch_num];
                rx_ch->channel.actual_len += length;
@@ -1330,7 +1493,7 @@ static void usb_process_rx_queue(struct cppi41 *cppi, unsigned index)
                if (curr_pd->eop) {
                        curr_pd->eop = 0;
                        /* disable the rx dma schedular */
-                       if (is_peripheral_active(cppi->musb))
+                       if (is_peripheral_active(cppi->musb) && !cppi->inf_mode)
                                cppi41_schedtbl_remove_dma_ch(0, 0, ch_num, 0);
                }
 
@@ -1346,10 +1509,42 @@ static void usb_process_rx_queue(struct cppi41 *cppi, unsigned index)
 
                if (unlikely(rx_ch->channel.actual_len >= rx_ch->length ||
                             length < orig_buf_len)) {
-                       rx_ch->channel.status = MUSB_DMA_STATUS_FREE;
 
-                       /* Rx completion routine callback */
-                       musb_dma_completion(cppi->musb, ep_num, 0);
+#if defined(CONFIG_SOC_OMAPTI81XX) || defined(CONFIG_SOC_OMAPAM33XX)
+                       struct musb_hw_ep *ep;
+                       u8 isoc, next_seg = 0;
+
+                       /* Workaround for early rx completion of
+                        * cppi41 dma in Generic RNDIS mode for ti81xx
+                        */
+                       if (is_host_enabled(cppi->musb)) {
+                               u32 pkt_size = rx_ch->pkt_size;
+                               ep = cppi->musb->endpoints + ep_num;
+                               isoc = musb_readb(ep->regs, MUSB_RXTYPE);
+                               isoc = (isoc >> 4) & 0x1;
+
+                               if (!isoc
+                               && (rx_ch->dma_mode == USB_GENERIC_RNDIS_MODE)
+                               && (rx_ch->channel.actual_len < rx_ch->length)
+                               && !(rx_ch->channel.actual_len % pkt_size))
+                                       next_seg = 1;
+                       }
+                       if (next_seg) {
+                               rx_ch->curr_offset = rx_ch->channel.actual_len;
+                               cppi41_next_rx_segment(rx_ch);
+                       } else
+#endif
+                       {
+                               rx_ch->channel.status = MUSB_DMA_STATUS_FREE;
+
+                               if (rx_ch->inf_mode) {
+                                       cppi41_rx_ch_set_maxbufcnt(
+                                       &rx_ch->dma_ch_obj, 0);
+                                       rx_ch->inf_mode = 0;
+                               }
+                               /* Rx completion routine callback */
+                               musb_dma_completion(cppi->musb, ep_num, 0);
+                       }
                } else {
                        if (is_peripheral_active(cppi->musb) &&
                                ((rx_ch->length - rx_ch->curr_offset) > 0))