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 EXPORT_SYMBOL(iso_packets_buffer_init); 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 } 76 EXPORT_SYMBOL(iso_packets_buffer_destroy); 77