aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-iso.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:38 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:02:57 -0500
commit9aad8125389a7a2990dee72d7892e22330a945eb (patch)
tree2566a8985837b000990db7e16b17547d3747141b /drivers/firewire/fw-iso.c
parent6e2e8424d310507fa044649435114217826ed78a (diff)
firewire: Split the iso buffer out from fw_iso_context and avoid vmalloc.
This patch splits out the iso buffer so we can initialize it at mmap time with the size provided in the mmap call. Furthermore, allocate the backing pages using alloc_page to avoid setting up kernel side virtual memory mappings for the pages. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-iso.c')
-rw-r--r--drivers/firewire/fw-iso.c118
1 files changed, 66 insertions, 52 deletions
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
index 6481e3df2c93..4e7ba8672929 100644
--- a/drivers/firewire/fw-iso.c
+++ b/drivers/firewire/fw-iso.c
@@ -28,68 +28,88 @@
28#include "fw-topology.h" 28#include "fw-topology.h"
29#include "fw-device.h" 29#include "fw-device.h"
30 30
31static int 31int
32setup_iso_buffer(struct fw_iso_context *ctx, size_t size, 32fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
33 enum dma_data_direction direction) 33 int page_count, enum dma_data_direction direction)
34{ 34{
35 struct page *page; 35 int i, j, retval = -ENOMEM;
36 int i, j; 36 dma_addr_t address;
37 void *p; 37
38 38 buffer->page_count = page_count;
39 ctx->buffer_size = PAGE_ALIGN(size); 39 buffer->direction = direction;
40 if (size == 0) 40
41 return 0; 41 buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]),
42 42 GFP_KERNEL);
43 ctx->buffer = vmalloc_32_user(ctx->buffer_size); 43 if (buffer->pages == NULL)
44 if (ctx->buffer == NULL) 44 goto out;
45 goto fail_buffer_alloc; 45
46 46 for (i = 0; i < buffer->page_count; i++) {
47 ctx->page_count = ctx->buffer_size >> PAGE_SHIFT; 47 buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32);
48 ctx->pages = 48 if (buffer->pages[i] == NULL)
49 kzalloc(ctx->page_count * sizeof(ctx->pages[0]), GFP_KERNEL); 49 goto out_pages;
50 if (ctx->pages == NULL) 50
51 goto fail_pages_alloc; 51 address = dma_map_page(card->device, buffer->pages[i],
52 52 0, PAGE_SIZE, direction);
53 p = ctx->buffer; 53 if (dma_mapping_error(address)) {
54 for (i = 0; i < ctx->page_count; i++, p += PAGE_SIZE) { 54 __free_page(buffer->pages[i]);
55 page = vmalloc_to_page(p); 55 goto out_pages;
56 ctx->pages[i] = dma_map_page(ctx->card->device, 56 }
57 page, 0, PAGE_SIZE, direction); 57 set_page_private(buffer->pages[i], address);
58 if (dma_mapping_error(ctx->pages[i]))
59 goto fail_mapping;
60 } 58 }
61 59
62 return 0; 60 return 0;
63 61
64 fail_mapping: 62 out_pages:
65 for (j = 0; j < i; j++) 63 for (j = 0; j < i; j++) {
66 dma_unmap_page(ctx->card->device, ctx->pages[j], 64 address = page_private(buffer->pages[j]);
65 dma_unmap_page(card->device, address,
67 PAGE_SIZE, DMA_TO_DEVICE); 66 PAGE_SIZE, DMA_TO_DEVICE);
68 fail_pages_alloc: 67 __free_page(buffer->pages[j]);
69 vfree(ctx->buffer); 68 }
70 fail_buffer_alloc: 69 kfree(buffer->pages);
71 return -ENOMEM; 70 out:
71 buffer->pages = NULL;
72 return retval;
73}
74
75int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma)
76{
77 unsigned long uaddr;
78 int i, retval;
79
80 uaddr = vma->vm_start;
81 for (i = 0; i < buffer->page_count; i++) {
82 retval = vm_insert_page(vma, uaddr, buffer->pages[i]);
83 if (retval)
84 return retval;
85 uaddr += PAGE_SIZE;
86 }
87
88 return 0;
72} 89}
73 90
74static void destroy_iso_buffer(struct fw_iso_context *ctx) 91void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
92 struct fw_card *card)
75{ 93{
76 int i; 94 int i;
95 dma_addr_t address;
77 96
78 for (i = 0; i < ctx->page_count; i++) 97 for (i = 0; i < buffer->page_count; i++) {
79 dma_unmap_page(ctx->card->device, ctx->pages[i], 98 address = page_private(buffer->pages[i]);
99 dma_unmap_page(card->device, address,
80 PAGE_SIZE, DMA_TO_DEVICE); 100 PAGE_SIZE, DMA_TO_DEVICE);
101 __free_page(buffer->pages[i]);
102 }
81 103
82 kfree(ctx->pages); 104 kfree(buffer->pages);
83 vfree(ctx->buffer); 105 buffer->pages = NULL;
84} 106}
85 107
86struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, 108struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type,
87 size_t buffer_size,
88 fw_iso_callback_t callback, 109 fw_iso_callback_t callback,
89 void *callback_data) 110 void *callback_data)
90{ 111{
91 struct fw_iso_context *ctx; 112 struct fw_iso_context *ctx;
92 int retval;
93 113
94 ctx = card->driver->allocate_iso_context(card, type); 114 ctx = card->driver->allocate_iso_context(card, type);
95 if (IS_ERR(ctx)) 115 if (IS_ERR(ctx))
@@ -100,12 +120,6 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type,
100 ctx->callback = callback; 120 ctx->callback = callback;
101 ctx->callback_data = callback_data; 121 ctx->callback_data = callback_data;
102 122
103 retval = setup_iso_buffer(ctx, buffer_size, DMA_TO_DEVICE);
104 if (retval < 0) {
105 card->driver->free_iso_context(ctx);
106 return ERR_PTR(retval);
107 }
108
109 return ctx; 123 return ctx;
110} 124}
111EXPORT_SYMBOL(fw_iso_context_create); 125EXPORT_SYMBOL(fw_iso_context_create);
@@ -114,8 +128,6 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
114{ 128{
115 struct fw_card *card = ctx->card; 129 struct fw_card *card = ctx->card;
116 130
117 destroy_iso_buffer(ctx);
118
119 card->driver->free_iso_context(ctx); 131 card->driver->free_iso_context(ctx);
120} 132}
121EXPORT_SYMBOL(fw_iso_context_destroy); 133EXPORT_SYMBOL(fw_iso_context_destroy);
@@ -133,10 +145,12 @@ EXPORT_SYMBOL(fw_iso_context_send);
133 145
134int 146int
135fw_iso_context_queue(struct fw_iso_context *ctx, 147fw_iso_context_queue(struct fw_iso_context *ctx,
136 struct fw_iso_packet *packet, void *payload) 148 struct fw_iso_packet *packet,
149 struct fw_iso_buffer *buffer,
150 unsigned long payload)
137{ 151{
138 struct fw_card *card = ctx->card; 152 struct fw_card *card = ctx->card;
139 153
140 return card->driver->queue_iso(ctx, packet, payload); 154 return card->driver->queue_iso(ctx, packet, buffer, payload);
141} 155}
142EXPORT_SYMBOL(fw_iso_context_queue); 156EXPORT_SYMBOL(fw_iso_context_queue);