| 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> | 
| Paul Gortmaker | d81a6d7 | 2011-09-22 09:34:58 -0400 | [diff] [blame] | 9 | #include <linux/export.h> | 
| Clemens Ladisch | 31ef913 | 2011-03-15 07:53:21 +0100 | [diff] [blame] | 10 | #include <linux/slab.h> | 
|  | 11 | #include "packets-buffer.h" | 
|  | 12 |  | 
|  | 13 | /** | 
|  | 14 | * iso_packets_buffer_init - allocates the memory for packets | 
|  | 15 | * @b: the buffer structure to initialize | 
|  | 16 | * @unit: the device at the other end of the stream | 
|  | 17 | * @count: the number of packets | 
|  | 18 | * @packet_size: the (maximum) size of a packet, in bytes | 
|  | 19 | * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE | 
|  | 20 | */ | 
|  | 21 | int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, | 
|  | 22 | unsigned int count, unsigned int packet_size, | 
|  | 23 | enum dma_data_direction direction) | 
|  | 24 | { | 
|  | 25 | unsigned int packets_per_page, pages; | 
|  | 26 | unsigned int i, page_index, offset_in_page; | 
|  | 27 | void *p; | 
|  | 28 | int err; | 
|  | 29 |  | 
|  | 30 | b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL); | 
|  | 31 | if (!b->packets) { | 
|  | 32 | err = -ENOMEM; | 
|  | 33 | goto error; | 
|  | 34 | } | 
|  | 35 |  | 
|  | 36 | packet_size = L1_CACHE_ALIGN(packet_size); | 
|  | 37 | packets_per_page = PAGE_SIZE / packet_size; | 
|  | 38 | if (WARN_ON(!packets_per_page)) { | 
|  | 39 | err = -EINVAL; | 
|  | 40 | goto error; | 
|  | 41 | } | 
|  | 42 | pages = DIV_ROUND_UP(count, packets_per_page); | 
|  | 43 |  | 
|  | 44 | err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card, | 
|  | 45 | pages, direction); | 
|  | 46 | if (err < 0) | 
|  | 47 | goto err_packets; | 
|  | 48 |  | 
|  | 49 | for (i = 0; i < count; ++i) { | 
|  | 50 | page_index = i / packets_per_page; | 
|  | 51 | p = page_address(b->iso_buffer.pages[page_index]); | 
|  | 52 | offset_in_page = (i % packets_per_page) * packet_size; | 
|  | 53 | b->packets[i].buffer = p + offset_in_page; | 
|  | 54 | b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page; | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | return 0; | 
|  | 58 |  | 
|  | 59 | err_packets: | 
|  | 60 | kfree(b->packets); | 
|  | 61 | error: | 
|  | 62 | return err; | 
|  | 63 | } | 
| Clemens Ladisch | 3a691b2 | 2011-05-11 10:44:51 +0200 | [diff] [blame] | 64 | EXPORT_SYMBOL(iso_packets_buffer_init); | 
| Clemens Ladisch | 31ef913 | 2011-03-15 07:53:21 +0100 | [diff] [blame] | 65 |  | 
|  | 66 | /** | 
|  | 67 | * iso_packets_buffer_destroy - frees packet buffer resources | 
|  | 68 | * @b: the buffer structure to free | 
|  | 69 | * @unit: the device at the other end of the stream | 
|  | 70 | */ | 
|  | 71 | void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | 
|  | 72 | struct fw_unit *unit) | 
|  | 73 | { | 
|  | 74 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); | 
|  | 75 | kfree(b->packets); | 
|  | 76 | } | 
| Clemens Ladisch | 3a691b2 | 2011-05-11 10:44:51 +0200 | [diff] [blame] | 77 | EXPORT_SYMBOL(iso_packets_buffer_destroy); |