* Allocate a piece of memory that can be efficiently mapped into bus device * space based on the constraints listed in the dma tag. Returns a pointer to * the allocated memory, and a pointer to an associated bus_dmamap. */
| 775 | * the allocated memory, and a pointer to an associated bus_dmamap. |
| 776 | */ |
| 777 | int |
| 778 | bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, |
| 779 | bus_dmamap_t *mapp) |
| 780 | { |
| 781 | busdma_bufalloc_t ba; |
| 782 | struct busdma_bufzone *bufzone; |
| 783 | bus_dmamap_t map; |
| 784 | vm_memattr_t memattr; |
| 785 | int mflags; |
| 786 | |
| 787 | if (flags & BUS_DMA_NOWAIT) |
| 788 | mflags = M_NOWAIT; |
| 789 | else |
| 790 | mflags = M_WAITOK; |
| 791 | if (flags & BUS_DMA_ZERO) |
| 792 | mflags |= M_ZERO; |
| 793 | |
| 794 | *mapp = map = allocate_map(dmat, mflags); |
| 795 | if (map == NULL) { |
| 796 | CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
| 797 | __func__, dmat, dmat->flags, ENOMEM); |
| 798 | return (ENOMEM); |
| 799 | } |
| 800 | map->flags = DMAMAP_DMAMEM_ALLOC; |
| 801 | |
| 802 | /* For coherent memory, set the map flag that disables sync ops. */ |
| 803 | if (flags & BUS_DMA_COHERENT) |
| 804 | map->flags |= DMAMAP_COHERENT; |
| 805 | |
| 806 | /* |
| 807 | * Choose a busdma buffer allocator based on memory type flags. |
| 808 | * If the tag's COHERENT flag is set, that means normal memory |
| 809 | * is already coherent, use the normal allocator. |
| 810 | */ |
| 811 | if ((flags & BUS_DMA_COHERENT) && |
| 812 | ((dmat->flags & BUS_DMA_COHERENT) == 0)) { |
| 813 | memattr = VM_MEMATTR_UNCACHEABLE; |
| 814 | ba = coherent_allocator; |
| 815 | } else { |
| 816 | memattr = VM_MEMATTR_DEFAULT; |
| 817 | ba = standard_allocator; |
| 818 | } |
| 819 | |
| 820 | /* |
| 821 | * Try to find a bufzone in the allocator that holds a cache of buffers |
| 822 | * of the right size for this request. If the buffer is too big to be |
| 823 | * held in the allocator cache, this returns NULL. |
| 824 | */ |
| 825 | bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize); |
| 826 | |
| 827 | /* |
| 828 | * Allocate the buffer from the uma(9) allocator if... |
| 829 | * - It's small enough to be in the allocator (bufzone not NULL). |
| 830 | * - The alignment constraint isn't larger than the allocation size |
| 831 | * (the allocator aligns buffers to their size boundaries). |
| 832 | * - There's no need to handle lowaddr/highaddr exclusion zones. |
| 833 | * else allocate non-contiguous pages if... |
| 834 | * - The page count that could get allocated doesn't exceed |
no test coverage detected