| Clemens Ladisch | 31ef913 | 2011-03-15 07:53:21 +0100 | [diff] [blame] | 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 | } | 
| Clemens Ladisch | 3a691b2 | 2011-05-11 10:44:51 +0200 | [diff] [blame] | 63 | EXPORT_SYMBOL(iso_packets_buffer_init); | 
| Clemens Ladisch | 31ef913 | 2011-03-15 07:53:21 +0100 | [diff] [blame] | 64 |  | 
|  | 65 | /** | 
|  | 66 | * iso_packets_buffer_destroy - frees packet buffer resources | 
|  | 67 | * @b: the buffer structure to free | 
|  | 68 | * @unit: the device at the other end of the stream | 
|  | 69 | */ | 
|  | 70 | void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | 
|  | 71 | struct fw_unit *unit) | 
|  | 72 | { | 
|  | 73 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); | 
|  | 74 | kfree(b->packets); | 
|  | 75 | } | 
| Clemens Ladisch | 3a691b2 | 2011-05-11 10:44:51 +0200 | [diff] [blame] | 76 | EXPORT_SYMBOL(iso_packets_buffer_destroy); |