| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2012 Ian Lepore |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | /* |
| 30 | */ |
| 31 | |
| 32 | /* |
| 33 | * A buffer pool manager, for use by a platform's busdma implementation. |
| 34 | */ |
| 35 | |
| 36 | #ifndef _MACHINE_BUSDMA_BUFALLOC_H_ |
| 37 | #define _MACHINE_BUSDMA_BUFALLOC_H_ |
| 38 | |
| 39 | #include <machine/bus.h> |
| 40 | #include <vm/uma.h> |
| 41 | |
| 42 | /* |
| 43 | * Information about a buffer zone, returned by busdma_bufalloc_findzone(). |
| 44 | */ |
| 45 | struct busdma_bufzone { |
| 46 | 	bus_size_t	size; |
| 47 | 	uma_zone_t	umazone; |
| 48 | 	char		name[24]; |
| 49 | }; |
| 50 | |
| 51 | /* |
| 52 | * Opaque handle type returned by busdma_bufalloc_create(). |
| 53 | */ |
| 54 | struct busdma_bufalloc; |
| 55 | typedef struct busdma_bufalloc *busdma_bufalloc_t; |
| 56 | |
| 57 | /* |
| 58 | * Create an allocator that manages a pool of DMA buffers. |
| 59 | * |
| 60 | * The allocator manages a collection of uma(9) zones of buffers in power-of-two |
| 61 | * sized increments ranging from minimum_alignment to the platform's PAGE_SIZE. |
| 62 | * The buffers within each zone are aligned on boundaries corresponding to the |
| 63 | * buffer size, and thus by implication each buffer is contiguous within a page |
| 64 | * and does not cross a power of two boundary larger than the buffer size. |
| 65 | * These rules are intended to make it easy for a busdma implementation to |
| 66 | * check whether a tag's constraints allow use of a buffer from the allocator. |
| 67 | * |
| 68 | * minimum_alignment is also the minimum buffer allocation size. For platforms |
| 69 | * with software-assisted cache coherency, this is typically the data cache line |
| 70 | * size (and MUST not be smaller than the cache line size). |
| 71 | * |
| 72 | * name appears in zone stats as 'dma name nnnnn' where 'dma' is fixed and |
| 73 | * 'nnnnn' is the size of buffers in that zone. |
| 74 | * |
| 75 | * If the alloc/free function pointers are NULL, the regular uma internal |
| 76 | * allocators are used (I.E., you get "plain old kernel memory"). On a platform |
| 77 | * with an exclusion zone that applies to all DMA operations, a custom allocator |
| 78 | * could be used to ensure no buffer memory is ever allocated from that zone, |
| 79 | * allowing the bus_dmamem_alloc() implementation to make the assumption that |
| 80 | * buffers provided by the allocation could never lead to the need for a bounce. |
| 81 | */ |
| 82 | busdma_bufalloc_t busdma_bufalloc_create(const char *name, |
| 83 | bus_size_t minimum_alignment, |
| 84 | uma_alloc uma_alloc_func, uma_free uma_free_func, |
| 85 | u_int32_t uma_zcreate_flags); |
| 86 | |
| 87 | /* |
| 88 | * Destroy an allocator created by busdma_bufalloc_create(). |
| 89 | * Safe to call with a NULL pointer. |
| 90 | */ |
| 91 | void busdma_bufalloc_destroy(busdma_bufalloc_t ba); |
| 92 | |
| 93 | /* |
| 94 | * Return a pointer to the busdma_bufzone that should be used to allocate or |
| 95 | * free a buffer of the given size. Returns NULL if the size is larger than the |
| 96 | * largest zone handled by the allocator. |
| 97 | */ |
| 98 | struct busdma_bufzone * busdma_bufalloc_findzone(busdma_bufalloc_t ba, |
| 99 | bus_size_t size); |
| 100 | |
| 101 | /* |
| 102 | * These built-in allocation routines are available for managing a pools of |
| 103 | * uncacheable memory on platforms that support VM_MEMATTR_UNCACHEABLE. |
| 104 | * |
| 105 | * Allocation is done using kmem_alloc_attr() with these parameters: |
| 106 | * lowaddr = 0 |
| 107 | * highaddr = BUS_SPACE_MAXADDR |
| 108 | * memattr = VM_MEMATTR_UNCACHEABLE. |
| 109 | * |
| 110 | * If your platform has no exclusion region (lowaddr/highaddr), and its pmap |
| 111 | * routines support pmap_page_set_memattr() and the VM_MEMATTR_UNCACHEABLE flag |
| 112 | * you can probably use these when you need uncacheable buffers. |
| 113 | */ |
| 114 | void * busdma_bufalloc_alloc_uncacheable(uma_zone_t zone, vm_size_t size, |
| 115 | int domain, uint8_t *pflag, int wait); |
| 116 | void busdma_bufalloc_free_uncacheable(void *item, vm_size_t size, |
| 117 | uint8_t pflag); |
| 118 | |
| 119 | #endif	/* _MACHINE_BUSDMA_BUFALLOC_H_ */ |