aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/ohci.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 9dcb17d51aee..5826ae333b19 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -739,7 +739,7 @@ static void ar_context_tasklet(unsigned long data)
739 d = &ab->descriptor; 739 d = &ab->descriptor;
740 740
741 if (d->res_count == 0) { 741 if (d->res_count == 0) {
742 size_t size, rest, offset; 742 size_t size, size2, rest, pktsize, size3, offset;
743 dma_addr_t start_bus; 743 dma_addr_t start_bus;
744 void *start; 744 void *start;
745 745
@@ -756,12 +756,41 @@ static void ar_context_tasklet(unsigned long data)
756 ab = ab->next; 756 ab = ab->next;
757 d = &ab->descriptor; 757 d = &ab->descriptor;
758 size = buffer + PAGE_SIZE - ctx->pointer; 758 size = buffer + PAGE_SIZE - ctx->pointer;
759 /* valid buffer data in the next page */
759 rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); 760 rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
761 /* what actually fits in this page */
762 size2 = min(rest, (size_t)PAGE_SIZE - size);
760 memmove(buffer, ctx->pointer, size); 763 memmove(buffer, ctx->pointer, size);
761 memcpy(buffer + size, ab->data, rest); 764 memcpy(buffer + size, ab->data, size2);
762 ctx->current_buffer = ab; 765 ctx->current_buffer = ab;
763 ctx->pointer = (void *) ab->data + rest; 766 ctx->pointer = (void *) ab->data + rest;
764 end = buffer + size + rest; 767
768 while (size > 0) {
769 void *next = handle_ar_packet(ctx, buffer);
770 pktsize = next - buffer;
771 if (pktsize >= size) {
772 /*
773 * We have handled all the data that was
774 * originally in this page, so we can now
775 * continue in the next page.
776 */
777 buffer = next;
778 break;
779 }
780 /* move the next packet to the start of the buffer */
781 memmove(buffer, next, size + size2 - pktsize);
782 size -= pktsize;
783 /* fill up this page again */
784 size3 = min(rest - size2,
785 (size_t)PAGE_SIZE - size - size2);
786 memcpy(buffer + size + size2,
787 (void *) ab->data + size2, size3);
788 size2 += size3;
789 }
790
791 /* handle the packets that are fully in the next page */
792 buffer = (void *) ab->data + (buffer - (start + size));
793 end = (void *) ab->data + rest;
765 794
766 while (buffer < end) 795 while (buffer < end)
767 buffer = handle_ar_packet(ctx, buffer); 796 buffer = handle_ar_packet(ctx, buffer);