diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
| -rw-r--r-- | drivers/firewire/ohci.c | 35 |
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); |
