Loading drivers/usb/musb/musb_host.c +140 −114 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 /* Loading Loading @@ -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, 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); 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; 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) { Loading Loading
drivers/usb/musb/musb_host.c +140 −114 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 /* Loading Loading @@ -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, 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); 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; 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) { Loading