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 | |
| 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>
| -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 | } | 
