Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: ohci: fix race when reading count in AR descriptor
firewire: ohci: avoid reallocation of AR buffers
firewire: ohci: fix race in AR split packet handling
firewire: ohci: fix buffer overflow in AR split packet handling

+65 -23
+65 -23
drivers/firewire/ohci.c
··· 577 return ret; 578 } 579 580 - static int ar_context_add_page(struct ar_context *ctx) 581 { 582 - struct device *dev = ctx->ohci->card.device; 583 - struct ar_buffer *ab; 584 - dma_addr_t uninitialized_var(ab_bus); 585 size_t offset; 586 - 587 - ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); 588 - if (ab == NULL) 589 - return -ENOMEM; 590 591 ab->next = NULL; 592 memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ··· 600 601 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); 602 flush_writes(ctx->ohci); 603 604 return 0; 605 } ··· 737 static void ar_context_tasklet(unsigned long data) 738 { 739 struct ar_context *ctx = (struct ar_context *)data; 740 - struct fw_ohci *ohci = ctx->ohci; 741 struct ar_buffer *ab; 742 struct descriptor *d; 743 void *buffer, *end; 744 745 ab = ctx->current_buffer; 746 d = &ab->descriptor; 747 748 - if (d->res_count == 0) { 749 - size_t size, rest, offset; 750 dma_addr_t start_bus; 751 void *start; 752 ··· 758 */ 759 760 offset = offsetof(struct ar_buffer, data); 761 - start = buffer = ab; 762 start_bus = le32_to_cpu(ab->descriptor.data_address) - offset; 763 764 ab = ab->next; 765 d = &ab->descriptor; 766 - size = buffer + PAGE_SIZE - ctx->pointer; 767 rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); 768 memmove(buffer, ctx->pointer, size); 769 - memcpy(buffer + size, ab->data, rest); 770 - ctx->current_buffer = ab; 771 - ctx->pointer = (void *) ab->data + rest; 772 - end = buffer + size + rest; 773 774 - while (buffer < end) 775 - buffer = handle_ar_packet(ctx, buffer); 776 777 - dma_free_coherent(ohci->card.device, PAGE_SIZE, 778 - start, start_bus); 779 - ar_context_add_page(ctx); 780 } else { 781 buffer = ctx->pointer; 782 ctx->pointer = end = 783 - (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count); 784 785 while (buffer < end) 786 buffer = handle_ar_packet(ctx, buffer);
··· 577 return ret; 578 } 579 580 + static void ar_context_link_page(struct ar_context *ctx, 581 + struct ar_buffer *ab, dma_addr_t ab_bus) 582 { 583 size_t offset; 584 585 ab->next = NULL; 586 memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ··· 606 607 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); 608 flush_writes(ctx->ohci); 609 + } 610 + 611 + static int ar_context_add_page(struct ar_context *ctx) 612 + { 613 + struct device *dev = ctx->ohci->card.device; 614 + struct ar_buffer *ab; 615 + dma_addr_t uninitialized_var(ab_bus); 616 + 617 + ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); 618 + if (ab == NULL) 619 + return -ENOMEM; 620 + 621 + ar_context_link_page(ctx, ab, ab_bus); 622 623 return 0; 624 } ··· 730 static void ar_context_tasklet(unsigned long data) 731 { 732 struct ar_context *ctx = (struct ar_context *)data; 733 struct ar_buffer *ab; 734 struct descriptor *d; 735 void *buffer, *end; 736 + __le16 res_count; 737 738 ab = ctx->current_buffer; 739 d = &ab->descriptor; 740 741 + res_count = ACCESS_ONCE(d->res_count); 742 + if (res_count == 0) { 743 + size_t size, size2, rest, pktsize, size3, offset; 744 dma_addr_t start_bus; 745 void *start; 746 ··· 750 */ 751 752 offset = offsetof(struct ar_buffer, data); 753 + start = ab; 754 start_bus = le32_to_cpu(ab->descriptor.data_address) - offset; 755 + buffer = ab->data; 756 757 ab = ab->next; 758 d = &ab->descriptor; 759 + size = start + PAGE_SIZE - ctx->pointer; 760 + /* valid buffer data in the next page */ 761 rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); 762 + /* what actually fits in this page */ 763 + size2 = min(rest, (size_t)PAGE_SIZE - offset - size); 764 memmove(buffer, ctx->pointer, size); 765 + memcpy(buffer + size, ab->data, size2); 766 767 + while (size > 0) { 768 + void *next = handle_ar_packet(ctx, buffer); 769 + pktsize = next - buffer; 770 + if (pktsize >= size) { 771 + /* 772 + * We have handled all the data that was 773 + * originally in this page, so we can now 774 + * continue in the next page. 775 + */ 776 + buffer = next; 777 + break; 778 + } 779 + /* move the next packet to the start of the buffer */ 780 + memmove(buffer, next, size + size2 - pktsize); 781 + size -= pktsize; 782 + /* fill up this page again */ 783 + size3 = min(rest - size2, 784 + (size_t)PAGE_SIZE - offset - size - size2); 785 + memcpy(buffer + size + size2, 786 + (void *) ab->data + size2, size3); 787 + size2 += size3; 788 + } 789 790 + if (rest > 0) { 791 + /* handle the packets that are fully in the next page */ 792 + buffer = (void *) ab->data + 793 + (buffer - (start + offset + size)); 794 + end = (void *) ab->data + rest; 795 + 796 + while (buffer < end) 797 + buffer = handle_ar_packet(ctx, buffer); 798 + 799 + ctx->current_buffer = ab; 800 + ctx->pointer = end; 801 + 802 + ar_context_link_page(ctx, start, start_bus); 803 + } else { 804 + ctx->pointer = start + PAGE_SIZE; 805 + } 806 } else { 807 buffer = ctx->pointer; 808 ctx->pointer = end = 809 + (void *) ab + PAGE_SIZE - le16_to_cpu(res_count); 810 811 while (buffer < end) 812 buffer = handle_ar_packet(ctx, buffer);