diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-10-25 05:42:42 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-10-30 17:37:20 -0400 |
commit | 837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5 (patch) | |
tree | a9b2ba0d4382a1c0ad75182662570f61b5e03e57 /drivers | |
parent | a1f805e5e73a8fe166b71c6592d3837df0cd5e2e (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/ohci.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7570b71a2453..b5ba66656c6c 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -577,17 +577,11 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr, | |||
577 | return ret; | 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 | size_t offset; | 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 | ab->next = NULL; | 585 | ab->next = NULL; |
592 | memset(&ab->descriptor, 0, sizeof(ab->descriptor)); | 586 | memset(&ab->descriptor, 0, sizeof(ab->descriptor)); |
593 | ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | | 587 | ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | |
@@ -606,6 +600,19 @@ static int ar_context_add_page(struct ar_context *ctx) | |||
606 | 600 | ||
607 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | 601 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
608 | flush_writes(ctx->ohci); | 602 | flush_writes(ctx->ohci); |
603 | } | ||
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); | ||
609 | 616 | ||
610 | return 0; | 617 | return 0; |
611 | } | 618 | } |
@@ -730,7 +737,6 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | |||
730 | static void ar_context_tasklet(unsigned long data) | 737 | static void ar_context_tasklet(unsigned long data) |
731 | { | 738 | { |
732 | struct ar_context *ctx = (struct ar_context *)data; | 739 | struct ar_context *ctx = (struct ar_context *)data; |
733 | struct fw_ohci *ohci = ctx->ohci; | ||
734 | struct ar_buffer *ab; | 740 | struct ar_buffer *ab; |
735 | struct descriptor *d; | 741 | struct descriptor *d; |
736 | void *buffer, *end; | 742 | void *buffer, *end; |
@@ -799,9 +805,7 @@ static void ar_context_tasklet(unsigned long data) | |||
799 | ctx->current_buffer = ab; | 805 | ctx->current_buffer = ab; |
800 | ctx->pointer = end; | 806 | ctx->pointer = end; |
801 | 807 | ||
802 | dma_free_coherent(ohci->card.device, PAGE_SIZE, | 808 | ar_context_link_page(ctx, start, start_bus); |
803 | start, start_bus); | ||
804 | ar_context_add_page(ctx); | ||
805 | } else { | 809 | } else { |
806 | ctx->pointer = start + PAGE_SIZE; | 810 | ctx->pointer = start + PAGE_SIZE; |
807 | } | 811 | } |