From 5c1e2da736a77fc7172da2c621310a9ceaf1e6ce Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 6 Jul 2011 03:48:40 +0200 Subject: Support alignments in kmem allocation --- dma/nwl.c | 2 +- kmem.c | 28 +++++++++++++++++----------- kmem.h | 3 +++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/dma/nwl.c b/dma/nwl.c index ee74a95..32cc2db 100644 --- a/dma/nwl.c +++ b/dma/nwl.c @@ -258,7 +258,7 @@ int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_descriptio if (info->pages) return 0; pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA, info->desc.addr), 0); - pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_PAGE, PCILIB_NWL_DMA_PAGES, 0, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA, info->desc.addr), 0); + pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_PAGE, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA, info->desc.addr), 0); if ((ring)&&(pages)) err = dma_nwl_sync_buffers(ctx, info, pages); else err = PCILIB_ERROR_FAILED; diff --git a/kmem.c b/kmem.c index 8388f2a..10bd88c 100644 --- a/kmem.c +++ b/kmem.c @@ -44,6 +44,10 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type kh.align = alignment; kh.use = use; + if (type != PCILIB_KMEM_TYPE_PAGE) { + kh.size += alignment; + } + for ( i = 0; i < nmemb; i++) { ret = ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_ALLOC, &kh); if (ret) { @@ -56,13 +60,13 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type kbuf->buf.blocks[i].handle_id = kh.handle_id; kbuf->buf.blocks[i].pa = kh.pa; kbuf->buf.blocks[i].size = kh.size; - - if (!i) { - if (kh.pa % alignment) printf("Alignment problem\n"); - else if (kh.pa & ctx->page_mask) printf("Mmap alignment problem\n"); + + if ((alignment)&&(type != PCILIB_KMEM_TYPE_PAGE)) { + if (kh.pa % alignment) kbuf->buf.blocks[i].alignment_offset = alignment - kh.pa % alignment; + kbuf->buf.blocks[i].size -= alignment; } - - addr = mmap( 0, kh.size, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); + + addr = mmap( 0, kh.size + kbuf->buf.blocks[i].alignment_offset, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); if ((!addr)||(addr == MAP_FAILED)) { kbuf->buf.n_blocks = i + 1; pcilib_free_kernel_memory(ctx, kbuf); @@ -71,6 +75,8 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type } kbuf->buf.blocks[i].ua = addr; + + kbuf->buf.blocks[i].mmap_offset = kh.pa & ctx->page_mask; } if (nmemb == 1) { @@ -99,7 +105,7 @@ void pcilib_free_kernel_memory(pcilib_t *ctx, pcilib_kmem_handle_t *k) { else if (ctx->kmem_list == kbuf) ctx->kmem_list = kbuf->next; for (i = 0; i < kbuf->buf.n_blocks; i++) { - if (kbuf->buf.blocks[i].ua) munmap(kbuf->buf.blocks[i].ua, kbuf->buf.blocks[i].size); + if (kbuf->buf.blocks[i].ua) munmap(kbuf->buf.blocks[i].ua, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset); kh.handle_id = kbuf->buf.blocks[i].handle_id; kh.pa = kbuf->buf.blocks[i].pa; @@ -142,22 +148,22 @@ int pcilib_sync_kernel_memory(pcilib_t *ctx, pcilib_kmem_handle_t *k, pcilib_kme void *pcilib_kmem_get_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k) { pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.addr.ua; + return kbuf->buf.addr.ua + kbuf->buf.addr.alignment_offset + kbuf->buf.addr.mmap_offset; } uintptr_t pcilib_kmem_get_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k) { pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.addr.pa; + return kbuf->buf.addr.pa + kbuf->buf.addr.alignment_offset; } void *pcilib_kmem_get_block_ua(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].ua; + return kbuf->buf.blocks[block].ua + kbuf->buf.blocks[block].alignment_offset + kbuf->buf.blocks[block].mmap_offset; } uintptr_t pcilib_kmem_get_block_pa(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { pcilib_kmem_list_t *kbuf = (pcilib_kmem_list_t*)k; - return kbuf->buf.blocks[block].pa; + return kbuf->buf.blocks[block].pa + kbuf->buf.blocks[block].alignment_offset; } size_t pcilib_kmem_get_block_size(pcilib_t *ctx, pcilib_kmem_handle_t *k, size_t block) { diff --git a/kmem.h b/kmem.h index 985864d..a92d55a 100644 --- a/kmem.h +++ b/kmem.h @@ -11,6 +11,9 @@ typedef struct { // uintptr_t va; void *ua; size_t size; + + size_t alignment_offset; + size_t mmap_offset; } pcilib_kmem_addr_t; /** -- cgit v1.2.3