+ pipe = urb->pipe;
+
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = len;
+
+ /* even if there was an error, we did the dma
+ * for iso_frame_desc->length
+ */
+ if (d->status != -EILSEQ && d->status != -EOVERFLOW)
+ d->status = 0;
+
+ if (++qh->iso_idx >= urb->number_of_packets) {
+ done = true;
+ } else {
+ /* REVISIT: Why ignore return value here? */
+ if (musb_dma_cppi41(hw_ep->musb))
+ done = musb_rx_dma_iso_cppi41(dma, hw_ep, qh,
+ urb, len);
+ done = false;
+ }
+
+ } else {
+ /* done if urb buffer is full or short packet is recd */
+ done = (urb->actual_length + len >=
+ urb->transfer_buffer_length
+ || channel->actual_len < qh->maxpacket
+ || channel->rx_packet_done);
+ }
+
+ /* send IN token for next packet, without AUTOREQ */
+ if (!done) {
+ val = musb_readw(epio, MUSB_RXCSR);
+ val |= MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, MUSB_RXCSR_H_WZC_BITS | val);
+ }
+
+ return done;
+}
+
+/* Disadvantage of using mode 1:
+ * It's basically usable only for mass storage class; essentially all
+ * other protocols also terminate transfers on short packets.
+ *
+ * Details:
+ * An extra IN token is sent at the end of the transfer (due to AUTOREQ)
+ * If you try to use mode 1 for (transfer_buffer_length - 512), and try
+ * to use the extra IN token to grab the last packet using mode 0, then
+ * the problem is that you cannot be sure when the device will send the
+ * last packet and RxPktRdy set. Sometimes the packet is recd too soon
+ * such that it gets lost when RxCSR is re-set at the end of the mode 1
+ * transfer, while sometimes it is recd just a little late so that if you
+ * try to configure for mode 0 soon after the mode 1 transfer is
+ * completed, you will find rxcount 0. Okay, so you might think why not
+ * wait for an interrupt when the pkt is recd. Well, you won't get any!
+ */
+static int musb_rx_dma_in_inventra_cppi41(struct dma_controller *dma,
+ struct musb_hw_ep *hw_ep,
+ struct musb_qh *qh,
+ struct urb *urb,
+ size_t len,
+ u8 iso_err)
+{
+ struct musb *musb = hw_ep->musb;
+ void __iomem *epio = hw_ep->regs;
+ struct dma_channel *channel = hw_ep->rx_channel;
+ u16 rx_count, val;
+ int length, pipe, done;
+ dma_addr_t buf;
+
+ rx_count = musb_readw(epio, MUSB_RXCOUNT);
+ pipe = urb->pipe;
+
+ if (usb_pipeisoc(pipe)) {
+ int d_status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+
+ if (iso_err) {
+ d_status = -EILSEQ;
+ urb->error_count++;
+ }
+ if (rx_count > d->length) {
+ if (d_status == 0) {
+ d_status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ dev_dbg(musb->controller, "** OVERFLOW %d into %d\n",
+ rx_count, d->length);
+
+ length = d->length;
+ } else
+ length = rx_count;
+ d->status = d_status;
+ buf = urb->transfer_dma + d->offset;
+ } else {
+ length = rx_count;
+ buf = urb->transfer_dma + urb->actual_length;
+ }
+
+ channel->desired_mode = 0;
+#ifdef USE_MODE1
+ /* because of the issue below, mode 1 will
+ * only rarely behave with correct semantics.
+ */
+ if ((urb->transfer_flags & URB_SHORT_NOT_OK)
+ && (urb->transfer_buffer_length - urb->actual_length)
+ > qh->maxpacket)
+ channel->desired_mode = 1;
+ if (rx_count < hw_ep->max_packet_sz_rx) {
+ length = rx_count;
+ channel->desired_mode = 0;
+ } else {
+ length = urb->transfer_buffer_length;
+ }
+#endif
+
+ /* See comments above on disadvantages of using mode 1 */
+ val = musb_readw(epio, MUSB_RXCSR);
+ val &= ~MUSB_RXCSR_H_REQPKT;
+
+ if (channel->desired_mode == 0)
+ val &= ~MUSB_RXCSR_H_AUTOREQ;
+ else
+ val |= MUSB_RXCSR_H_AUTOREQ;
+ val |= MUSB_RXCSR_DMAENAB;
+
+ /* autoclear shouldn't be set in high bandwidth */
+ if (qh->hb_mult == 1)
+ val |= MUSB_RXCSR_AUTOCLEAR;
+
+ musb_writew(epio, MUSB_RXCSR, MUSB_RXCSR_H_WZC_BITS | val);
+
+ /* REVISIT if when actual_length != 0,
+ * transfer_buffer_length needs to be
+ * adjusted first...
+ */
+ done = dma->channel_program(channel, qh->maxpacket,
+ channel->desired_mode,
+ buf, length);
+
+ if (!done) {
+ dma->channel_release(channel);
+ hw_ep->rx_channel = NULL;
+ channel = NULL;
+ val = musb_readw(epio, MUSB_RXCSR);
+ val &= ~(MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_H_AUTOREQ
+ | MUSB_RXCSR_AUTOCLEAR);
+ musb_writew(epio, MUSB_RXCSR, val);
+ }
+
+ return done;
+}
+#else
+static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
+ struct musb_hw_ep *hw_ep,
+ struct musb_qh *qh,
+ struct urb *urb,
+ size_t len)
+{
+ return false;
+}
+
+static inline int musb_rx_dma_in_inventra_cppi41(struct dma_controller *dma,
+ struct musb_hw_ep *hw_ep,
+ struct musb_qh *qh,
+ struct urb *urb,
+ size_t len,
+ u8 iso_err)
+{
+ return false;
+}