mirror of https://gitee.com/openkylin/linux.git
usb: musb: Fix for isochronous IN transfer
Fixes blurred capture images in dma mode. Isochronous error field in urb and source data buffer pointer were not updated properly in dma mode. Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
352d026338
commit
f82a689fae
|
@ -1507,10 +1507,29 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
|
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
|
||||||
|
|
||||||
#ifdef CONFIG_USB_INVENTRA_DMA
|
#ifdef CONFIG_USB_INVENTRA_DMA
|
||||||
|
if (usb_pipeisoc(pipe)) {
|
||||||
|
struct usb_iso_packet_descriptor *d;
|
||||||
|
|
||||||
|
d = urb->iso_frame_desc + qh->iso_idx;
|
||||||
|
d->actual_length = xfer_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
|
||||||
|
done = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
/* done if urb buffer is full or short packet is recd */
|
/* done if urb buffer is full or short packet is recd */
|
||||||
done = (urb->actual_length + xfer_len >=
|
done = (urb->actual_length + xfer_len >=
|
||||||
urb->transfer_buffer_length
|
urb->transfer_buffer_length
|
||||||
|| dma->actual_len < qh->maxpacket);
|
|| dma->actual_len < qh->maxpacket);
|
||||||
|
}
|
||||||
|
|
||||||
/* send IN token for next packet, without AUTOREQ */
|
/* send IN token for next packet, without AUTOREQ */
|
||||||
if (!done) {
|
if (!done) {
|
||||||
|
@ -1547,7 +1566,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
if (dma) {
|
if (dma) {
|
||||||
struct dma_controller *c;
|
struct dma_controller *c;
|
||||||
u16 rx_count;
|
u16 rx_count;
|
||||||
int ret;
|
int ret, length;
|
||||||
|
dma_addr_t buf;
|
||||||
|
|
||||||
rx_count = musb_readw(epio, MUSB_RXCOUNT);
|
rx_count = musb_readw(epio, MUSB_RXCOUNT);
|
||||||
|
|
||||||
|
@ -1560,6 +1580,35 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
|
|
||||||
c = musb->dma_controller;
|
c = musb->dma_controller;
|
||||||
|
|
||||||
|
if (usb_pipeisoc(pipe)) {
|
||||||
|
int status = 0;
|
||||||
|
struct usb_iso_packet_descriptor *d;
|
||||||
|
|
||||||
|
d = urb->iso_frame_desc + qh->iso_idx;
|
||||||
|
|
||||||
|
if (iso_err) {
|
||||||
|
status = -EILSEQ;
|
||||||
|
urb->error_count++;
|
||||||
|
}
|
||||||
|
if (rx_count > d->length) {
|
||||||
|
if (status == 0) {
|
||||||
|
status = -EOVERFLOW;
|
||||||
|
urb->error_count++;
|
||||||
|
}
|
||||||
|
DBG(2, "** OVERFLOW %d into %d\n",\
|
||||||
|
rx_count, d->length);
|
||||||
|
|
||||||
|
length = d->length;
|
||||||
|
} else
|
||||||
|
length = rx_count;
|
||||||
|
d->status = status;
|
||||||
|
buf = urb->transfer_dma + d->offset;
|
||||||
|
} else {
|
||||||
|
length = rx_count;
|
||||||
|
buf = urb->transfer_dma +
|
||||||
|
urb->actual_length;
|
||||||
|
}
|
||||||
|
|
||||||
dma->desired_mode = 0;
|
dma->desired_mode = 0;
|
||||||
#ifdef USE_MODE1
|
#ifdef USE_MODE1
|
||||||
/* because of the issue below, mode 1 will
|
/* because of the issue below, mode 1 will
|
||||||
|
@ -1571,6 +1620,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
urb->actual_length)
|
urb->actual_length)
|
||||||
> qh->maxpacket)
|
> qh->maxpacket)
|
||||||
dma->desired_mode = 1;
|
dma->desired_mode = 1;
|
||||||
|
if (rx_count < hw_ep->max_packet_sz_rx) {
|
||||||
|
length = rx_count;
|
||||||
|
dma->bDesiredMode = 0;
|
||||||
|
} else {
|
||||||
|
length = urb->transfer_buffer_length;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Disadvantage of using mode 1:
|
/* Disadvantage of using mode 1:
|
||||||
|
@ -1608,12 +1663,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
*/
|
*/
|
||||||
ret = c->channel_program(
|
ret = c->channel_program(
|
||||||
dma, qh->maxpacket,
|
dma, qh->maxpacket,
|
||||||
dma->desired_mode,
|
dma->desired_mode, buf, length);
|
||||||
urb->transfer_dma
|
|
||||||
+ urb->actual_length,
|
|
||||||
(dma->desired_mode == 0)
|
|
||||||
? rx_count
|
|
||||||
: urb->transfer_buffer_length);
|
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
c->channel_release(dma);
|
c->channel_release(dma);
|
||||||
|
@ -1631,19 +1681,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma && usb_pipeisoc(pipe)) {
|
|
||||||
struct usb_iso_packet_descriptor *d;
|
|
||||||
int iso_stat = status;
|
|
||||||
|
|
||||||
d = urb->iso_frame_desc + qh->iso_idx;
|
|
||||||
d->actual_length += xfer_len;
|
|
||||||
if (iso_err) {
|
|
||||||
iso_stat = -EILSEQ;
|
|
||||||
urb->error_count++;
|
|
||||||
}
|
|
||||||
d->status = iso_stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
urb->actual_length += xfer_len;
|
urb->actual_length += xfer_len;
|
||||||
qh->offset += xfer_len;
|
qh->offset += xfer_len;
|
||||||
|
|
Loading…
Reference in New Issue