1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
/*
* Copyright (C) ST-Ericsson SA 2010
*
* ST-Ericsson B2R2 node generator
*
* Author: Robert Fekete <robert.fekete@stericsson.com>
* Author: Paul Wannback
* for ST-Ericsson.
*
* License terms: GNU General Public License (GPL), version 2.
*/
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/dma-mapping.h>
#include "b2r2_internal.h"
static void free_nodes(struct b2r2_control *cont,
struct b2r2_node *first_node)
{
struct b2r2_node *node = first_node;
int no_of_nodes = 0;
while (node) {
no_of_nodes++;
node = node->next;
}
dma_free_coherent(cont->dev,
no_of_nodes * sizeof(struct b2r2_node),
first_node,
first_node->physical_address -
offsetof(struct b2r2_node, node));
}
struct b2r2_node *b2r2_blt_alloc_nodes(struct b2r2_control *cont,
int no_of_nodes)
{
u32 physical_address;
struct b2r2_node *nodes;
struct b2r2_node *tmpnode;
if (no_of_nodes <= 0) {
dev_err(cont->dev, "%s: Wrong number of nodes (%d)",
__func__, no_of_nodes);
return NULL;
}
/* Allocate the memory */
nodes = (struct b2r2_node *) dma_alloc_coherent(cont->dev,
no_of_nodes * sizeof(struct b2r2_node),
&physical_address, GFP_DMA | GFP_KERNEL);
if (nodes == NULL) {
dev_err(cont->dev,
"%s: Failed to alloc memory for nodes",
__func__);
return NULL;
}
/* Build the linked list */
tmpnode = nodes;
physical_address += offsetof(struct b2r2_node, node);
while (no_of_nodes--) {
tmpnode->physical_address = physical_address;
if (no_of_nodes)
tmpnode->next = tmpnode + 1;
else
tmpnode->next = NULL;
tmpnode++;
physical_address += sizeof(struct b2r2_node);
}
return nodes;
}
void b2r2_blt_free_nodes(struct b2r2_control *cont,
struct b2r2_node *first_node)
{
free_nodes(cont, first_node);
}
|