]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-linux/udma.git/blob - udma_mem.c
udma: migrate to new repo on git.ti.com
[keystone-linux/udma.git] / udma_mem.c
1 /*
2  * udma_mem.c
3  * This file provides udma memory functionality to user space applications
4  * to use the udma kernel driver.
5  *
6  * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
7  *
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *
13  *    Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  *    Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the
19  *    distribution.
20  *
21  *    Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37 */
39 #include <internal/udma_internal.h>
41 #define align(num, align)       (((num) + (align) - 1) & (~((align) - 1)))
43 static int udma_page_size       = -1;
44 static void *udma_mem_start     = NULL;
45 static void *udma_mem_end       = NULL;
46 static struct udma_atom udma_mem_avail;
48 int udma_mem_init(unsigned long mem_size)
49 {
50         void *udma_mem;
52         udma_page_size = getpagesize();
54         udma_mem = mmap(0, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED,
55                         udma_fd, 0);
56         if (udma_mem == MAP_FAILED)
57                 return -ENOMEM;
59         udma_mem_start = udma_mem;
60         udma_mem_end = udma_mem + mem_size;
61         udma_atom_set_ptr(&udma_mem_avail, udma_mem_start);
63         return 0;
64 }
66 void udma_mem_shutdown(void)
67 {
68         munmap(udma_mem_start, udma_mem_end - udma_mem_start);
69         udma_mem_start = udma_mem_end = NULL;
70         udma_atom_set_ptr(&udma_mem_avail, NULL);
71 }
73 void *udma_mem_alloc(unsigned long size)
74 {
75         void *memstart, *memend;
76         enum udma_atom_status status;
78         size = align(size, udma_page_size);
80         do {
81                 memstart = udma_atom_get_ptr(&udma_mem_avail);
82                 memend = memstart + size;
83                 if (memend > udma_mem_end)
84                         return NULL;
85                 status = udma_atom_cas_ptr(&udma_mem_avail, memstart, memend);
86         } while (status != UDMA_ATOM_CAS_SUCCESS);
88         return memstart;
89 }
91 int udma_mem_free(void *mem, unsigned long size)
92 {
93         void *memstart = mem, *memend, *avail;
94         enum udma_atom_status status;
96         size = align(size, udma_page_size);
97         memend = memstart + size;
99         do {
100                 avail = udma_atom_get_ptr(&udma_mem_avail);
101                 if (avail != memend)
102                         return -EINVAL;
103                 status = udma_atom_cas_ptr(&udma_mem_avail, memend, memstart);
104         } while (status != UDMA_ATOM_CAS_SUCCESS);
106         return 0;
109 struct udma_mem_part *udma_mem_part_create(unsigned nblocks, unsigned blocksize)
111         struct udma_mem_part *part;
112         unsigned total;
113         void *mem;
115         part = udma_malloc(sizeof(struct udma_mem_part));
116         if (!part)
117                 return NULL;
119         part->blocksize = align(blocksize, 4);
120         total = part->blocksize * nblocks;
121         nblocks = total / part->blocksize;
123         mem = udma_mem_alloc(total);
124         if (!mem) {
125                 udma_free(part);
126                 return NULL;
127         }
129         part->memstart = mem;
130         part->memend = mem + total;
132         udma_atom_set(&part->used, 0);
133         udma_lifo_init(&part->free);
135         for (; nblocks; nblocks--, mem += part->blocksize)
136                 udma_lifo_put(&part->free, mem);
138         return part;
141 void udma_mem_part_destroy(struct udma_mem_part *part)
143         udma_mem_free(part->memstart, part->memend - part->memstart);
144         udma_free(part);
147 void *udma_mem_block_alloc(struct udma_mem_part *part)
149         void *block;
151         block = udma_lifo_get(&part->free);
152         if (block)
153                 udma_atom_inc(&part->used);
154         return block;
157 void udma_mem_block_free(struct udma_mem_part *part, void* block)
159         if (block < part->memstart || block >= part->memend)
160                 return;
161         udma_lifo_put(&part->free, block);
162         udma_atom_dec(&part->used);