summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-10-25 11:42:42 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-10-30 23:37:20 +0200
commit837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5 (patch)
treea9b2ba0d4382a1c0ad75182662570f61b5e03e57 /drivers/firewire
parenta1f805e5e73a8fe166b71c6592d3837df0cd5e2e (diff)
downloadop-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.c28
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;
}
OpenPOWER on IntegriCloud