diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-10-25 11:42:42 +0200 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-10-30 23:37:20 +0200 |
commit | 837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5 (patch) | |
tree | a9b2ba0d4382a1c0ad75182662570f61b5e03e57 /drivers/firewire | |
parent | a1f805e5e73a8fe166b71c6592d3837df0cd5e2e (diff) | |
download | op-kernel-dev-837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5.zip op-kernel-dev-837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5.tar.gz |
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/firewire')
-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 7570b71..b5ba666 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, return ret; } -static int ar_context_add_page(struct ar_context *ctx) +static void ar_context_link_page(struct ar_context *ctx, + struct ar_buffer *ab, dma_addr_t ab_bus) { - struct device *dev = ctx->ohci->card.device; - struct ar_buffer *ab; - dma_addr_t uninitialized_var(ab_bus); size_t offset; - ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); - if (ab == NULL) - return -ENOMEM; - ab->next = NULL; memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | @@ -606,6 +600,19 @@ static int ar_context_add_page(struct ar_context *ctx) reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); flush_writes(ctx->ohci); +} + +static int ar_context_add_page(struct ar_context *ctx) +{ + struct device *dev = ctx->ohci->card.device; + struct ar_buffer *ab; + dma_addr_t uninitialized_var(ab_bus); + + ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); + if (ab == NULL) + return -ENOMEM; + + ar_context_link_page(ctx, ab, ab_bus); return 0; } @@ -730,7 +737,6 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) static void ar_context_tasklet(unsigned long data) { struct ar_context *ctx = (struct ar_context *)data; - struct fw_ohci *ohci = ctx->ohci; struct ar_buffer *ab; struct descriptor *d; void *buffer, *end; @@ -799,9 +805,7 @@ static void ar_context_tasklet(unsigned long data) ctx->current_buffer = ab; ctx->pointer = end; - dma_free_coherent(ohci->card.device, PAGE_SIZE, - start, start_bus); - ar_context_add_page(ctx); + ar_context_link_page(ctx, start, start_bus); } else { ctx->pointer = start + PAGE_SIZE; } |