Commit | Line | Data |
---|---|---|
31ef9134 CL |
1 | /* |
2 | * helpers for managing a buffer for many packets | |
3 | * | |
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | |
5 | * Licensed under the terms of the GNU General Public License, version 2. | |
6 | */ | |
7 | ||
8 | #include <linux/firewire.h> | |
9 | #include <linux/slab.h> | |
10 | #include "packets-buffer.h" | |
11 | ||
12 | /** | |
13 | * iso_packets_buffer_init - allocates the memory for packets | |
14 | * @b: the buffer structure to initialize | |
15 | * @unit: the device at the other end of the stream | |
16 | * @count: the number of packets | |
17 | * @packet_size: the (maximum) size of a packet, in bytes | |
18 | * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE | |
19 | */ | |
20 | int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, | |
21 | unsigned int count, unsigned int packet_size, | |
22 | enum dma_data_direction direction) | |
23 | { | |
24 | unsigned int packets_per_page, pages; | |
25 | unsigned int i, page_index, offset_in_page; | |
26 | void *p; | |
27 | int err; | |
28 | ||
29 | b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL); | |
30 | if (!b->packets) { | |
31 | err = -ENOMEM; | |
32 | goto error; | |
33 | } | |
34 | ||
35 | packet_size = L1_CACHE_ALIGN(packet_size); | |
36 | packets_per_page = PAGE_SIZE / packet_size; | |
37 | if (WARN_ON(!packets_per_page)) { | |
38 | err = -EINVAL; | |
39 | goto error; | |
40 | } | |
41 | pages = DIV_ROUND_UP(count, packets_per_page); | |
42 | ||
43 | err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card, | |
44 | pages, direction); | |
45 | if (err < 0) | |
46 | goto err_packets; | |
47 | ||
48 | for (i = 0; i < count; ++i) { | |
49 | page_index = i / packets_per_page; | |
50 | p = page_address(b->iso_buffer.pages[page_index]); | |
51 | offset_in_page = (i % packets_per_page) * packet_size; | |
52 | b->packets[i].buffer = p + offset_in_page; | |
53 | b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page; | |
54 | } | |
55 | ||
56 | return 0; | |
57 | ||
58 | err_packets: | |
59 | kfree(b->packets); | |
60 | error: | |
61 | return err; | |
62 | } | |
63 | ||
64 | /** | |
65 | * iso_packets_buffer_destroy - frees packet buffer resources | |
66 | * @b: the buffer structure to free | |
67 | * @unit: the device at the other end of the stream | |
68 | */ | |
69 | void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | |
70 | struct fw_unit *unit) | |
71 | { | |
72 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); | |
73 | kfree(b->packets); | |
74 | } |