Commit ac33cdb1 authored by Tony Lindgren's avatar Tony Lindgren Committed by Felipe Balbi

usb: musb: Remove ifdefs for musb_host_rx in musb_host.c part5

Remove ifdefs for musb_host_rx to get closer to building in
all the DMA drivers.
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent e530bb8f
...@@ -1661,6 +1661,122 @@ static int musb_rx_dma_inventra_cppi41(struct dma_controller *dma, ...@@ -1661,6 +1661,122 @@ static int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
return done; 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 #else
static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma, static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
struct musb_hw_ep *hw_ep, struct musb_hw_ep *hw_ep,
...@@ -1670,6 +1786,16 @@ static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma, ...@@ -1670,6 +1786,16 @@ static inline int musb_rx_dma_inventra_cppi41(struct dma_controller *dma,
{ {
return false; 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 #endif
/* /*
...@@ -1859,121 +1985,21 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1859,121 +1985,21 @@ void musb_host_rx(struct musb *musb, u8 epnum)
/* we are expecting IN packets */ /* we are expecting IN packets */
if ((musb_dma_inventra(musb) || musb_dma_ux500(musb) || if ((musb_dma_inventra(musb) || musb_dma_ux500(musb) ||
musb_dma_cppi41(musb)) && dma) { musb_dma_cppi41(musb)) && dma) {
struct dma_controller *c; dev_dbg(hw_ep->musb->controller,
u16 rx_count; "RX%d count %d, buffer 0x%llx len %d/%d\n",
int ret, length; epnum, musb_readw(epio, MUSB_RXCOUNT),
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 (unsigned long long) urb->transfer_dma
+ urb->actual_length, + urb->actual_length,
qh->offset, qh->offset,
urb->transfer_buffer_length); urb->transfer_buffer_length);
c = musb->dma_controller; done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh,
urb, xfer_len,
if (usb_pipeisoc(pipe)) { iso_err);
int d_status = 0; if (done)
struct usb_iso_packet_descriptor *d; goto finish;
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;
else else
val |= MUSB_RXCSR_H_AUTOREQ; dev_err(musb->controller, "error: rx_dma failed\n");
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);
}
} }
if (!dma) { if (!dma) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment