Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/packets-buffer.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* helpers for managing a buffer for many packets
4
*
5
* Copyright (c) Clemens Ladisch <[email protected]>
6
*/
7
8
#include <linux/firewire.h>
9
#include <linux/export.h>
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_array(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 err_packets;
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
}
64
EXPORT_SYMBOL(iso_packets_buffer_init);
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
}
77
EXPORT_SYMBOL(iso_packets_buffer_destroy);
78
79