dma_alloc.c revision 1.6
1/*	$OpenBSD: dma_alloc.c,v 1.6 2011/04/05 01:28:05 art Exp $	 */
2/*
3 * Copyright (c) 2010 Theo de Raadt <deraadt@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/pool.h>
20#include <uvm/uvm.h>
21
22static __inline int	 dma_alloc_index(size_t size);
23
24/* Create dma pools from objects sized 2^4 to 2^16 */
25#define DMA_PAGE_SHIFT		16
26#define DMA_BUCKET_OFFSET	4
27static char dmanames[DMA_PAGE_SHIFT - DMA_BUCKET_OFFSET + 1][10];
28struct pool dmapools[DMA_PAGE_SHIFT - DMA_BUCKET_OFFSET + 1];
29
30void
31dma_alloc_init(void)
32{
33	int i;
34
35	for (i = 0; i < nitems(dmapools); i++) {
36		snprintf(dmanames[i], sizeof(dmanames[0]), "dma%d",
37		    1 << (i + DMA_BUCKET_OFFSET));
38		pool_init(&dmapools[i], 1 << (i + DMA_BUCKET_OFFSET), 0, 0, 0,
39		    dmanames[i], NULL);
40		pool_set_constraints(&dmapools[i], &kp_dma);
41		pool_setipl(&dmapools[i], IPL_VM);
42		/* XXX need pool_setlowat(&dmapools[i], dmalowat); */
43	}
44}
45
46static __inline int
47dma_alloc_index(size_t sz)
48{
49	int b;
50
51	for (b = 0; b < nitems(dmapools); b++)
52		if (sz <= (1 << (b + DMA_BUCKET_OFFSET)))
53			return (b);
54#ifdef DEBUG
55	printf("dma_alloc/free: object %d too large\n", sz);
56#endif
57	return (-1);
58}
59
60void *
61dma_alloc(size_t size, int prflags)
62{
63	int pi = dma_alloc_index(size);
64
65	if (pi == -1)
66		return (NULL);
67	return pool_get(&dmapools[pi], prflags);
68}
69
70
71void
72dma_free(void *m, size_t size)
73{
74	int pi = dma_alloc_index(size);
75
76	if (pi == -1)
77		return;
78	pool_put(&dmapools[pi], m);
79}
80