1 /***************************************************************************
2 * Copyright (C) 2006-2010 by Marin Mitov *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "dt3155-bufs.h"
24 * dt3155_init_chunks_buf - creates a chunk buffer and allocates memory for it
26 * returns: a pointer to the struct dt3155_buf or NULL if failed
28 * Creates a struct dt3155_buf, then allocates a chunk of memory of
29 * size DT3155_CHUNK_SIZE and sets all the pages in it as Reserved.
30 * This is done to be able to use remap_pfn_range() on these buffers
31 * (which do not work on normal memory if Reserved bit is not set)
34 dt3155_init_chunks_buf(void)
36 struct dt3155_buf
*buf
;
39 buf
= kzalloc(sizeof(*buf
), GFP_KERNEL
);
42 buf
->cpu
= (void *)__get_free_pages(DT3155_CHUNK_FLAGS
,
43 get_order(DT3155_CHUNK_SIZE
));
48 for (i
= 0; i
< DT3155_CHUNK_SIZE
; i
+= PAGE_SIZE
)
49 SetPageReserved(virt_to_page(buf
->cpu
+ i
));
50 return buf
; /* success */
54 * dt3155_free_chunks_buf - destroys the specified buffer
56 * @buf: the buffer to be freed
58 * Clears Reserved bit of all pages in the chunk, frees the chunk memory
59 * and destroys struct dt3155_buf.
62 dt3155_free_chunks_buf(struct dt3155_buf
*buf
)
66 for (i
= 0; i
< DT3155_CHUNK_SIZE
; i
+= PAGE_SIZE
)
67 ClearPageReserved(virt_to_page(buf
->cpu
+ i
));
68 free_pages((unsigned long)buf
->cpu
, get_order(DT3155_CHUNK_SIZE
));
73 * dt3155_init_fifo - creates and initializes a fifo
75 * returns: a pointer to the crated and initialized struct dt3155_fifo
79 dt3155_init_fifo(void)
81 struct dt3155_fifo
*fifo
= kzalloc(sizeof(*fifo
), GFP_KERNEL
);
83 spin_lock_init(&fifo
->lock
);
87 /* dt3155_free_fifo(x) defined as macro in dt3155.h */
90 * dt3155_get_buf - gets a buffer from the fifo
92 * @fifo: the fifo to get a buffer from
94 * returns: a pointer to the buffer or NULL if failed
96 * dt3155_get_buf gets the fifo's spin_lock and returns the
97 * buffer pointed by the head. Could be used in any context.
100 dt3155_get_buf(struct dt3155_fifo
*fifo
)
103 struct dt3155_buf
*tmp_buf
;
105 spin_lock_irqsave(&fifo
->lock
, flags
);
106 tmp_buf
= fifo
->head
;
108 fifo
->head
= fifo
->head
->next
;
111 spin_unlock_irqrestore(&fifo
->lock
, flags
);
116 * dt3155_put_buf - puts a buffer into a fifo
118 * @buf: the buffer to put
119 * @fifo: the fifo to put the buffer in
121 * dt3155_put_buf gets the fifo's spin_lock and puts the buf
122 * at the tail of the fifo. Could be used in any context.
125 dt3155_put_buf(struct dt3155_buf
*buf
, struct dt3155_fifo
*fifo
)
129 spin_lock_irqsave(&fifo
->lock
, flags
);
132 fifo
->tail
->next
= buf
;
136 spin_unlock_irqrestore(&fifo
->lock
, flags
);
140 * dt3155_init_chunks_fifo - creates and fills a chunks_fifo
142 * returns: a pointer to the fifo or NULL if failed
144 * dt3155_init_chunks_fifo creates and fills the fifo with
145 * a number of chunks <= DT3155_CHUNK_NUM. The returned fifo
146 * contains at least one chunk.
149 dt3155_init_chunks_fifo(void)
153 struct dt3155_fifo
*chunks
;
154 struct dt3155_buf
*tmp_buf
;
156 chunks
= dt3155_init_fifo();
159 tmp_buf
= dt3155_init_chunks_buf();
161 dt3155_free_fifo(chunks
);
164 dt3155_put_buf(tmp_buf
, chunks
);
165 for (i
= 1; i
< DT3155_CHUNK_NUM
; i
++) {
166 tmp_buf
= dt3155_init_chunks_buf();
169 dt3155_put_buf(tmp_buf
, chunks
);
175 * dt3155_free_chunks_fifo - empties and destroys the chunks_fifo
177 * @chunks: the chunks_fifo to be freed
179 * dt3155_free_chunks_fifo deallocates all chunks in the fifo and
183 dt3155_free_chunks_fifo(struct dt3155_fifo
*chunks
)
186 struct dt3155_buf
*buf
;
188 while ((buf
= dt3155_get_buf(chunks
))) {
189 dt3155_free_chunks_buf(buf
);
192 dt3155_free_fifo(chunks
);
193 printk(KERN_INFO
"dt3155: %i chunks freed\n", buf_count
);
197 * dt3155_init_ibufs_fifo - creates and fills an image buffer fifo
199 * @chunks: chunks_fifo to take memory from
200 * @buf_size: the size of image buffers
202 * returns: a pointer to the fifo filled with image buffers
204 * dt3155_init_ibufs_fifo takes chunks from chunks_fifo, chops them
205 * into pieces of size buf_size and fills image fifo with them.
208 dt3155_init_ibufs_fifo(struct dt3155_fifo
*chunks
, int buf_size
)
210 int i
, buf_count
= 0;
211 struct dt3155_buf
*tmp_ibuf
, *chunks_buf
, *last_chunk
;
212 struct dt3155_fifo
*tmp_fifo
;
214 tmp_fifo
= dt3155_init_fifo();
217 last_chunk
= chunks
->tail
;
219 chunks_buf
= dt3155_get_buf(chunks
);
220 dt3155_put_buf(chunks_buf
, chunks
);
221 for (i
= 0; i
< DT3155_CHUNK_SIZE
/ buf_size
; i
++) {
222 tmp_ibuf
= kzalloc(sizeof(*tmp_ibuf
), GFP_KERNEL
);
225 chunks_buf
->cpu
+ DT3155_BUF_SIZE
* i
;
226 dt3155_put_buf(tmp_ibuf
, tmp_fifo
);
232 dt3155_free_fifo(tmp_fifo
);
237 } while (chunks_buf
!= last_chunk
);
239 printk(KERN_INFO
"dt3155: %i image buffers available\n", buf_count
);
244 * dt3155_free_ibufs_fifo - empties and destroys an image fifo
246 * @fifo: the fifo to free
249 dt3155_free_ibufs_fifo(struct dt3155_fifo
*fifo
)
251 struct dt3155_buf
*tmp_ibuf
;
253 while ((tmp_ibuf
= dt3155_get_buf(fifo
)))