Commit 837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5
Committed by
Stefan Richter
1 parent
a1f805e5e7
Exists in
master
and in
4 other branches
firewire: ohci: avoid reallocation of AR buffers
Freeing an AR buffer page just to allocate a new page immediately afterwards is not only a pointless effort but also dangerous because the allocation can fail, which would result in an oops later. Split ar_context_add_page() into two functions so that we can reuse the old page directly. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Tested-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Showing 1 changed file with 16 additions and 12 deletions Side-by-side Diff
drivers/firewire/ohci.c
... | ... | @@ -577,17 +577,11 @@ |
577 | 577 | return ret; |
578 | 578 | } |
579 | 579 | |
580 | -static int ar_context_add_page(struct ar_context *ctx) | |
580 | +static void ar_context_link_page(struct ar_context *ctx, | |
581 | + struct ar_buffer *ab, dma_addr_t ab_bus) | |
581 | 582 | { |
582 | - struct device *dev = ctx->ohci->card.device; | |
583 | - struct ar_buffer *ab; | |
584 | - dma_addr_t uninitialized_var(ab_bus); | |
585 | 583 | size_t offset; |
586 | 584 | |
587 | - ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); | |
588 | - if (ab == NULL) | |
589 | - return -ENOMEM; | |
590 | - | |
591 | 585 | ab->next = NULL; |
592 | 586 | memset(&ab->descriptor, 0, sizeof(ab->descriptor)); |
593 | 587 | ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | |
594 | 588 | |
... | ... | @@ -606,7 +600,20 @@ |
606 | 600 | |
607 | 601 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
608 | 602 | flush_writes(ctx->ohci); |
603 | +} | |
609 | 604 | |
605 | +static int ar_context_add_page(struct ar_context *ctx) | |
606 | +{ | |
607 | + struct device *dev = ctx->ohci->card.device; | |
608 | + struct ar_buffer *ab; | |
609 | + dma_addr_t uninitialized_var(ab_bus); | |
610 | + | |
611 | + ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); | |
612 | + if (ab == NULL) | |
613 | + return -ENOMEM; | |
614 | + | |
615 | + ar_context_link_page(ctx, ab, ab_bus); | |
616 | + | |
610 | 617 | return 0; |
611 | 618 | } |
612 | 619 | |
... | ... | @@ -730,7 +737,6 @@ |
730 | 737 | static void ar_context_tasklet(unsigned long data) |
731 | 738 | { |
732 | 739 | struct ar_context *ctx = (struct ar_context *)data; |
733 | - struct fw_ohci *ohci = ctx->ohci; | |
734 | 740 | struct ar_buffer *ab; |
735 | 741 | struct descriptor *d; |
736 | 742 | void *buffer, *end; |
... | ... | @@ -799,9 +805,7 @@ |
799 | 805 | ctx->current_buffer = ab; |
800 | 806 | ctx->pointer = end; |
801 | 807 | |
802 | - dma_free_coherent(ohci->card.device, PAGE_SIZE, | |
803 | - start, start_bus); | |
804 | - ar_context_add_page(ctx); | |
808 | + ar_context_link_page(ctx, start, start_bus); | |
805 | 809 | } else { |
806 | 810 | ctx->pointer = start + PAGE_SIZE; |
807 | 811 | } |