]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
usb: musb: Remove ifdefs for musb_host_rx in musb_host.c part5
authorTony Lindgren <tony@atomide.com>
Fri, 1 May 2015 19:29:37 +0000 (12:29 -0700)
committerFelipe Balbi <balbi@ti.com>
Thu, 7 May 2015 18:36:31 +0000 (13:36 -0500)
Remove ifdefs for musb_host_rx to get closer to building in
all the DMA drivers.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_host.c

index 79826eb47ba4467533e9ec0ac95bc451923a3fb2..249951564b33f326cb8ec009610fd73f23de5c2f 100644 (file)
@@ -1661,6 +1661,122 @@ static int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
 
        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,
@@ -1670,6 +1786,16 @@ static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
 {
        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;
+}
 #endif
 
 /*
@@ -1859,121 +1985,21 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                /* we are expecting IN packets */
                if ((musb_dma_inventra(musb) || musb_dma_ux500(musb) ||
                    musb_dma_cppi41(musb)) && dma) {
-                       struct dma_controller   *c;
-                       u16                     rx_count;
-                       int                     ret, length;
-                       dma_addr_t              buf;
-
-                       rx_count = musb_readw(epio, MUSB_RXCOUNT);
-
-                       dev_dbg(musb->controller, "RX%d count %d, buffer 0x%llx len %d/%d\n",
-                                       epnum, rx_count,
-                                       (unsigned long long) urb->transfer_dma
-                                       + urb->actual_length,
-                                       qh->offset,
-                                       urb->transfer_buffer_length);
-
-                       c = musb->dma_controller;
-
-                       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;
-                       }
-
-                       dma->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)
-                               dma->desired_mode = 1;
-                       if (rx_count < hw_ep->max_packet_sz_rx) {
-                               length = rx_count;
-                               dma->desired_mode = 0;
-                       } else {
-                               length = urb->transfer_buffer_length;
-                       }
-#endif
-
-/* 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!
- */
-
-                       val = musb_readw(epio, MUSB_RXCSR);
-                       val &= ~MUSB_RXCSR_H_REQPKT;
-
-                       if (dma->desired_mode == 0)
-                               val &= ~MUSB_RXCSR_H_AUTOREQ;
+                       dev_dbg(hw_ep->musb->controller,
+                               "RX%d count %d, buffer 0x%llx len %d/%d\n",
+                               epnum, musb_readw(epio, MUSB_RXCOUNT),
+                               (unsigned long long) urb->transfer_dma
+                               + urb->actual_length,
+                               qh->offset,
+                               urb->transfer_buffer_length);
+
+                       done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh,
+                                                             urb, xfer_len,
+                                                             iso_err);
+                       if (done)
+                               goto finish;
                        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...
-                        */
-                       ret = c->channel_program(
-                               dma, qh->maxpacket,
-                               dma->desired_mode, buf, length);
-
-                       if (!ret) {
-                               c->channel_release(dma);
-                               hw_ep->rx_channel = NULL;
-                               dma = NULL;
-                               val = musb_readw(epio, MUSB_RXCSR);
-                               val &= ~(MUSB_RXCSR_DMAENAB
-                                       | MUSB_RXCSR_H_AUTOREQ
-                                       | MUSB_RXCSR_AUTOCLEAR);
-                               musb_writew(epio, MUSB_RXCSR, val);
-                       }
+                               dev_err(musb->controller, "error: rx_dma failed\n");
                }
 
                if (!dma) {