Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
core-iso.c
Go to the documentation of this file.
1 /*
2  * Isochronous I/O functionality:
3  * - Isochronous DMA context management
4  * - Isochronous bus resource management (channels, bandwidth), client side
5  *
6  * Copyright (C) 2006 Kristian Hoegsberg <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22 
23 #include <linux/dma-mapping.h>
24 #include <linux/errno.h>
25 #include <linux/firewire.h>
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/slab.h>
30 #include <linux/spinlock.h>
31 #include <linux/vmalloc.h>
32 #include <linux/export.h>
33 
34 #include <asm/byteorder.h>
35 
36 #include "core.h"
37 
38 /*
39  * Isochronous DMA context management
40  */
41 
42 int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count)
43 {
44  int i;
45 
46  buffer->page_count = 0;
47  buffer->page_count_mapped = 0;
48  buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]),
49  GFP_KERNEL);
50  if (buffer->pages == NULL)
51  return -ENOMEM;
52 
53  for (i = 0; i < page_count; i++) {
55  if (buffer->pages[i] == NULL)
56  break;
57  }
58  buffer->page_count = i;
59  if (i < page_count) {
60  fw_iso_buffer_destroy(buffer, NULL);
61  return -ENOMEM;
62  }
63 
64  return 0;
65 }
66 
69 {
71  int i;
72 
73  buffer->direction = direction;
74 
75  for (i = 0; i < buffer->page_count; i++) {
76  address = dma_map_page(card->device, buffer->pages[i],
77  0, PAGE_SIZE, direction);
78  if (dma_mapping_error(card->device, address))
79  break;
80 
81  set_page_private(buffer->pages[i], address);
82  }
83  buffer->page_count_mapped = i;
84  if (i < buffer->page_count)
85  return -ENOMEM;
86 
87  return 0;
88 }
89 
91  int page_count, enum dma_data_direction direction)
92 {
93  int ret;
94 
95  ret = fw_iso_buffer_alloc(buffer, page_count);
96  if (ret < 0)
97  return ret;
98 
99  ret = fw_iso_buffer_map_dma(buffer, card, direction);
100  if (ret < 0)
101  fw_iso_buffer_destroy(buffer, card);
102 
103  return ret;
104 }
106 
108  struct vm_area_struct *vma)
109 {
110  unsigned long uaddr;
111  int i, err;
112 
113  uaddr = vma->vm_start;
114  for (i = 0; i < buffer->page_count; i++) {
115  err = vm_insert_page(vma, uaddr, buffer->pages[i]);
116  if (err)
117  return err;
118 
119  uaddr += PAGE_SIZE;
120  }
121 
122  return 0;
123 }
124 
126  struct fw_card *card)
127 {
128  int i;
130 
131  for (i = 0; i < buffer->page_count_mapped; i++) {
132  address = page_private(buffer->pages[i]);
133  dma_unmap_page(card->device, address,
134  PAGE_SIZE, buffer->direction);
135  }
136  for (i = 0; i < buffer->page_count; i++)
137  __free_page(buffer->pages[i]);
138 
139  kfree(buffer->pages);
140  buffer->pages = NULL;
141  buffer->page_count = 0;
142  buffer->page_count_mapped = 0;
143 }
145 
146 /* Convert DMA address to offset into virtually contiguous buffer. */
148 {
149  size_t i;
151  ssize_t offset;
152 
153  for (i = 0; i < buffer->page_count; i++) {
154  address = page_private(buffer->pages[i]);
155  offset = (ssize_t)completed - (ssize_t)address;
156  if (offset > 0 && offset <= PAGE_SIZE)
157  return (i << PAGE_SHIFT) + offset;
158  }
159 
160  return 0;
161 }
162 
164  int type, int channel, int speed, size_t header_size,
166 {
167  struct fw_iso_context *ctx;
168 
169  ctx = card->driver->allocate_iso_context(card,
170  type, channel, header_size);
171  if (IS_ERR(ctx))
172  return ctx;
173 
174  ctx->card = card;
175  ctx->type = type;
176  ctx->channel = channel;
177  ctx->speed = speed;
178  ctx->header_size = header_size;
179  ctx->callback.sc = callback;
181 
182  return ctx;
183 }
185 
187 {
188  ctx->card->driver->free_iso_context(ctx);
189 }
191 
193  int cycle, int sync, int tags)
194 {
195  return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
196 }
198 
200 {
201  return ctx->card->driver->set_iso_channels(ctx, channels);
202 }
203 
205  struct fw_iso_packet *packet,
206  struct fw_iso_buffer *buffer,
207  unsigned long payload)
208 {
209  return ctx->card->driver->queue_iso(ctx, packet, buffer, payload);
210 }
212 
214 {
215  ctx->card->driver->flush_queue_iso(ctx);
216 }
218 
220 {
221  return ctx->card->driver->flush_iso_completions(ctx);
222 }
224 
226 {
227  return ctx->card->driver->stop_iso(ctx);
228 }
230 
231 /*
232  * Isochronous bus resource management (channels, bandwidth), client side
233  */
234 
235 static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
236  int bandwidth, bool allocate)
237 {
238  int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
239  __be32 data[2];
240 
241  /*
242  * On a 1394a IRM with low contention, try < 1 is enough.
243  * On a 1394-1995 IRM, we need at least try < 2.
244  * Let's just do try < 5.
245  */
246  for (try = 0; try < 5; try++) {
247  new = allocate ? old - bandwidth : old + bandwidth;
248  if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL)
249  return -EBUSY;
250 
251  data[0] = cpu_to_be32(old);
252  data[1] = cpu_to_be32(new);
254  irm_id, generation, SCODE_100,
256  data, 8)) {
257  case RCODE_GENERATION:
258  /* A generation change frees all bandwidth. */
259  return allocate ? -EAGAIN : bandwidth;
260 
261  case RCODE_COMPLETE:
262  if (be32_to_cpup(data) == old)
263  return bandwidth;
264 
265  old = be32_to_cpup(data);
266  /* Fall through. */
267  }
268  }
269 
270  return -EIO;
271 }
272 
273 static int manage_channel(struct fw_card *card, int irm_id, int generation,
274  u32 channels_mask, u64 offset, bool allocate)
275 {
276  __be32 bit, all, old;
277  __be32 data[2];
278  int channel, ret = -EIO, retry = 5;
279 
280  old = all = allocate ? cpu_to_be32(~0) : 0;
281 
282  for (channel = 0; channel < 32; channel++) {
283  if (!(channels_mask & 1 << channel))
284  continue;
285 
286  ret = -EBUSY;
287 
288  bit = cpu_to_be32(1 << (31 - channel));
289  if ((old & bit) != (all & bit))
290  continue;
291 
292  data[0] = old;
293  data[1] = old ^ bit;
295  irm_id, generation, SCODE_100,
296  offset, data, 8)) {
297  case RCODE_GENERATION:
298  /* A generation change frees all channels. */
299  return allocate ? -EAGAIN : channel;
300 
301  case RCODE_COMPLETE:
302  if (data[0] == old)
303  return channel;
304 
305  old = data[0];
306 
307  /* Is the IRM 1394a-2000 compliant? */
308  if ((data[0] & bit) == (data[1] & bit))
309  continue;
310 
311  /* 1394-1995 IRM, fall through to retry. */
312  default:
313  if (retry) {
314  retry--;
315  channel--;
316  } else {
317  ret = -EIO;
318  }
319  }
320  }
321 
322  return ret;
323 }
324 
325 static void deallocate_channel(struct fw_card *card, int irm_id,
326  int generation, int channel)
327 {
328  u32 mask;
329  u64 offset;
330 
331  mask = channel < 32 ? 1 << channel : 1 << (channel - 32);
332  offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
334 
335  manage_channel(card, irm_id, generation, mask, offset, false);
336 }
337 
362 void fw_iso_resource_manage(struct fw_card *card, int generation,
363  u64 channels_mask, int *channel, int *bandwidth,
364  bool allocate)
365 {
366  u32 channels_hi = channels_mask; /* channels 31...0 */
367  u32 channels_lo = channels_mask >> 32; /* channels 63...32 */
368  int irm_id, ret, c = -EINVAL;
369 
370  spin_lock_irq(&card->lock);
371  irm_id = card->irm_node->node_id;
372  spin_unlock_irq(&card->lock);
373 
374  if (channels_hi)
375  c = manage_channel(card, irm_id, generation, channels_hi,
377  allocate);
378  if (channels_lo && c < 0) {
379  c = manage_channel(card, irm_id, generation, channels_lo,
381  allocate);
382  if (c >= 0)
383  c += 32;
384  }
385  *channel = c;
386 
387  if (allocate && channels_mask != 0 && c < 0)
388  *bandwidth = 0;
389 
390  if (*bandwidth == 0)
391  return;
392 
393  ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
394  if (ret < 0)
395  *bandwidth = 0;
396 
397  if (allocate && ret < 0) {
398  if (c >= 0)
399  deallocate_channel(card, irm_id, generation, c);
400  *channel = ret;
401  }
402 }