mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
lx_emul: comply boundary constraints of dma pool
Several DMA pools of the EHCI/UHCI USB host controller driver declare that buffers should not cross 4K boundaries. If this property is not met fatal errors like NMIs may happen during USB operation. Discussed in issue #5000
This commit is contained in:
parent
e337f2cb0f
commit
963b8b0607
@ -20,6 +20,8 @@ struct dma_pool
|
|||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t align;
|
size_t align;
|
||||||
|
unsigned boundary; /* power-of-two */
|
||||||
|
char name[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
void * dma_pool_alloc(struct dma_pool * pool, gfp_t mem_flags, dma_addr_t * handle)
|
void * dma_pool_alloc(struct dma_pool * pool, gfp_t mem_flags, dma_addr_t * handle)
|
||||||
@ -31,6 +33,16 @@ void * dma_pool_alloc(struct dma_pool * pool, gfp_t mem_flags, dma_addr_t * hand
|
|||||||
void * ret =
|
void * ret =
|
||||||
lx_emul_mem_alloc_aligned_uncached(pool->size, pool->align);
|
lx_emul_mem_alloc_aligned_uncached(pool->size, pool->align);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (pool->boundary && ret) {
|
||||||
|
unsigned long b = ((unsigned long)ret) >> pool->boundary;
|
||||||
|
unsigned long e = ((unsigned long)ret + pool->size - 1) >> pool->boundary;
|
||||||
|
|
||||||
|
if (b != e)
|
||||||
|
printk("%s: allocation crosses %s pool boundary of %#lx bytes\n",
|
||||||
|
__func__, pool->name, 1ul << pool->boundary);
|
||||||
|
}
|
||||||
|
|
||||||
*handle = lx_emul_mem_dma_addr(ret);
|
*handle = lx_emul_mem_dma_addr(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -48,8 +60,16 @@ struct dma_pool * dma_pool_create(const char * name,
|
|||||||
|
|
||||||
/* TODO check if it makes sense to add min(align, PAGE_SIZE) check */
|
/* TODO check if it makes sense to add min(align, PAGE_SIZE) check */
|
||||||
|
|
||||||
pool->size = size;
|
/* ensure allocations do not cross the given boundary */
|
||||||
pool->align = align;
|
if (boundary)
|
||||||
|
align = max_t(size_t, roundup_pow_of_two(size), align);
|
||||||
|
|
||||||
|
pool->size = size;
|
||||||
|
pool->align = align;
|
||||||
|
pool->boundary = order_base_2(boundary);
|
||||||
|
|
||||||
|
strscpy(pool->name, name, sizeof(pool->name));
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,15 +88,17 @@ struct dma_pool *dmam_pool_create(const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Caller guarantees that no more memory from the pool is in use,
|
||||||
|
* and that nothing will try to use the pool after this call.
|
||||||
|
*/
|
||||||
void dma_pool_destroy(struct dma_pool * pool)
|
void dma_pool_destroy(struct dma_pool * pool)
|
||||||
{
|
{
|
||||||
kfree(pool);
|
kfree(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dma_pool_free(struct dma_pool * pool,void * vaddr,dma_addr_t dma)
|
void dma_pool_free(struct dma_pool * pool,void * vaddr,dma_addr_t dma)
|
||||||
{
|
{
|
||||||
lx_emul_mem_free(vaddr);
|
lx_emul_mem_free(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user