mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
staging: ion: refactor ion's heap manipulators into a separate file.
This patch is preparatory work for making ion heaps modular. The patch itself doesn't make any significant changes except for re-organizing the heap manipulator functions in a single file. This will be helpful later when we specifically export some of these functions to be used by a heap module. Bug: 133508579 Test: ion-unit-tests Change-Id: I19205b4874a3bf52408f1fa14c3e145de1293fb4 Co-developed-by: Isaac J. Manjarres <isaacm@codeaurora.org> Signed-off-by: Sandeep Patil <sspatil@google.com>
This commit is contained in:
parent
144555039f
commit
5d41593935
|
|
@ -155,6 +155,14 @@ struct ion_heap {
|
|||
*/
|
||||
void ion_device_add_heap(struct ion_heap *heap);
|
||||
|
||||
/* ion_buffer_zero - zeroes out an ion buffer respecting the ION_FLAGs.
|
||||
*
|
||||
* @buffer: ion_buffer to zero
|
||||
*
|
||||
* Returns 0 on success, negative error otherwise.
|
||||
*/
|
||||
int ion_buffer_zero(struct ion_buffer *buffer);
|
||||
|
||||
/**
|
||||
* some helpers for common operations on buffers using the sg_table
|
||||
* and vaddr fields
|
||||
|
|
@ -163,8 +171,9 @@ void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
|
|||
void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
|
||||
int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
|
||||
struct vm_area_struct *vma);
|
||||
int ion_heap_buffer_zero(struct ion_buffer *buffer);
|
||||
int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
|
||||
int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents,
|
||||
pgprot_t pgprot);
|
||||
|
||||
/**
|
||||
* ion_heap_init_shrinker
|
||||
|
|
|
|||
|
|
@ -133,6 +133,23 @@ struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
int ion_buffer_zero(struct ion_buffer *buffer)
|
||||
{
|
||||
struct sg_table *table;
|
||||
pgprot_t pgprot;
|
||||
|
||||
if (!buffer)
|
||||
return -EINVAL;
|
||||
|
||||
table = buffer->sg_table;
|
||||
if (buffer->flags & ION_FLAG_CACHED)
|
||||
pgprot = PAGE_KERNEL;
|
||||
else
|
||||
pgprot = pgprot_writecombine(PAGE_KERNEL);
|
||||
|
||||
return ion_heap_sglist_zero(table->sgl, table->nents, pgprot);
|
||||
}
|
||||
|
||||
void ion_buffer_release(struct ion_buffer *buffer)
|
||||
{
|
||||
if (buffer->kmap_cnt > 0) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,120 @@
|
|||
|
||||
#include "ion_private.h"
|
||||
|
||||
static unsigned long ion_heap_shrink_count(struct shrinker *shrinker,
|
||||
struct shrink_control *sc)
|
||||
{
|
||||
struct ion_heap *heap = container_of(shrinker, struct ion_heap,
|
||||
shrinker);
|
||||
int total = 0;
|
||||
|
||||
total = ion_heap_freelist_size(heap) / PAGE_SIZE;
|
||||
|
||||
if (heap->ops->shrink)
|
||||
total += heap->ops->shrink(heap, sc->gfp_mask, 0);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
|
||||
struct shrink_control *sc)
|
||||
{
|
||||
struct ion_heap *heap = container_of(shrinker, struct ion_heap,
|
||||
shrinker);
|
||||
int freed = 0;
|
||||
int to_scan = sc->nr_to_scan;
|
||||
|
||||
if (to_scan == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* shrink the free list first, no point in zeroing the memory if we're
|
||||
* just going to reclaim it. Also, skip any possible page pooling.
|
||||
*/
|
||||
if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
|
||||
freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) /
|
||||
PAGE_SIZE;
|
||||
|
||||
to_scan -= freed;
|
||||
if (to_scan <= 0)
|
||||
return freed;
|
||||
|
||||
if (heap->ops->shrink)
|
||||
freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan);
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot)
|
||||
{
|
||||
void *addr = vm_map_ram(pages, num, -1, pgprot);
|
||||
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
memset(addr, 0, PAGE_SIZE * num);
|
||||
vm_unmap_ram(addr, num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size,
|
||||
bool skip_pools)
|
||||
{
|
||||
struct ion_buffer *buffer;
|
||||
size_t total_drained = 0;
|
||||
|
||||
if (ion_heap_freelist_size(heap) == 0)
|
||||
return 0;
|
||||
|
||||
spin_lock(&heap->free_lock);
|
||||
if (size == 0)
|
||||
size = heap->free_list_size;
|
||||
|
||||
while (!list_empty(&heap->free_list)) {
|
||||
if (total_drained >= size)
|
||||
break;
|
||||
buffer = list_first_entry(&heap->free_list, struct ion_buffer,
|
||||
list);
|
||||
list_del(&buffer->list);
|
||||
heap->free_list_size -= buffer->size;
|
||||
if (skip_pools)
|
||||
buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE;
|
||||
total_drained += buffer->size;
|
||||
spin_unlock(&heap->free_lock);
|
||||
ion_buffer_release(buffer);
|
||||
spin_lock(&heap->free_lock);
|
||||
}
|
||||
spin_unlock(&heap->free_lock);
|
||||
|
||||
return total_drained;
|
||||
}
|
||||
|
||||
static int ion_heap_deferred_free(void *data)
|
||||
{
|
||||
struct ion_heap *heap = data;
|
||||
|
||||
while (true) {
|
||||
struct ion_buffer *buffer;
|
||||
|
||||
wait_event_freezable(heap->waitqueue,
|
||||
ion_heap_freelist_size(heap) > 0);
|
||||
|
||||
spin_lock(&heap->free_lock);
|
||||
if (list_empty(&heap->free_list)) {
|
||||
spin_unlock(&heap->free_lock);
|
||||
continue;
|
||||
}
|
||||
buffer = list_first_entry(&heap->free_list, struct ion_buffer,
|
||||
list);
|
||||
list_del(&buffer->list);
|
||||
heap->free_list_size -= buffer->size;
|
||||
spin_unlock(&heap->free_lock);
|
||||
ion_buffer_release(buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *ion_heap_map_kernel(struct ion_heap *heap,
|
||||
struct ion_buffer *buffer)
|
||||
{
|
||||
|
|
@ -97,20 +211,8 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot)
|
||||
{
|
||||
void *addr = vm_map_ram(pages, num, -1, pgprot);
|
||||
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
memset(addr, 0, PAGE_SIZE * num);
|
||||
vm_unmap_ram(addr, num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents,
|
||||
pgprot_t pgprot)
|
||||
int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents,
|
||||
pgprot_t pgprot)
|
||||
{
|
||||
int p = 0;
|
||||
int ret = 0;
|
||||
|
|
@ -132,19 +234,6 @@ static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ion_heap_buffer_zero(struct ion_buffer *buffer)
|
||||
{
|
||||
struct sg_table *table = buffer->sg_table;
|
||||
pgprot_t pgprot;
|
||||
|
||||
if (buffer->flags & ION_FLAG_CACHED)
|
||||
pgprot = PAGE_KERNEL;
|
||||
else
|
||||
pgprot = pgprot_writecombine(PAGE_KERNEL);
|
||||
|
||||
return ion_heap_sglist_zero(table->sgl, table->nents, pgprot);
|
||||
}
|
||||
|
||||
int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
|
|
@ -174,38 +263,6 @@ size_t ion_heap_freelist_size(struct ion_heap *heap)
|
|||
return size;
|
||||
}
|
||||
|
||||
static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size,
|
||||
bool skip_pools)
|
||||
{
|
||||
struct ion_buffer *buffer;
|
||||
size_t total_drained = 0;
|
||||
|
||||
if (ion_heap_freelist_size(heap) == 0)
|
||||
return 0;
|
||||
|
||||
spin_lock(&heap->free_lock);
|
||||
if (size == 0)
|
||||
size = heap->free_list_size;
|
||||
|
||||
while (!list_empty(&heap->free_list)) {
|
||||
if (total_drained >= size)
|
||||
break;
|
||||
buffer = list_first_entry(&heap->free_list, struct ion_buffer,
|
||||
list);
|
||||
list_del(&buffer->list);
|
||||
heap->free_list_size -= buffer->size;
|
||||
if (skip_pools)
|
||||
buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE;
|
||||
total_drained += buffer->size;
|
||||
spin_unlock(&heap->free_lock);
|
||||
ion_buffer_release(buffer);
|
||||
spin_lock(&heap->free_lock);
|
||||
}
|
||||
spin_unlock(&heap->free_lock);
|
||||
|
||||
return total_drained;
|
||||
}
|
||||
|
||||
size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
|
||||
{
|
||||
return _ion_heap_freelist_drain(heap, size, false);
|
||||
|
|
@ -216,32 +273,6 @@ size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size)
|
|||
return _ion_heap_freelist_drain(heap, size, true);
|
||||
}
|
||||
|
||||
static int ion_heap_deferred_free(void *data)
|
||||
{
|
||||
struct ion_heap *heap = data;
|
||||
|
||||
while (true) {
|
||||
struct ion_buffer *buffer;
|
||||
|
||||
wait_event_freezable(heap->waitqueue,
|
||||
ion_heap_freelist_size(heap) > 0);
|
||||
|
||||
spin_lock(&heap->free_lock);
|
||||
if (list_empty(&heap->free_list)) {
|
||||
spin_unlock(&heap->free_lock);
|
||||
continue;
|
||||
}
|
||||
buffer = list_first_entry(&heap->free_list, struct ion_buffer,
|
||||
list);
|
||||
list_del(&buffer->list);
|
||||
heap->free_list_size -= buffer->size;
|
||||
spin_unlock(&heap->free_lock);
|
||||
ion_buffer_release(buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ion_heap_init_deferred_free(struct ion_heap *heap)
|
||||
{
|
||||
struct sched_param param = { .sched_priority = 0 };
|
||||
|
|
@ -260,50 +291,6 @@ int ion_heap_init_deferred_free(struct ion_heap *heap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ion_heap_shrink_count(struct shrinker *shrinker,
|
||||
struct shrink_control *sc)
|
||||
{
|
||||
struct ion_heap *heap = container_of(shrinker, struct ion_heap,
|
||||
shrinker);
|
||||
int total = 0;
|
||||
|
||||
total = ion_heap_freelist_size(heap) / PAGE_SIZE;
|
||||
|
||||
if (heap->ops->shrink)
|
||||
total += heap->ops->shrink(heap, sc->gfp_mask, 0);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
|
||||
struct shrink_control *sc)
|
||||
{
|
||||
struct ion_heap *heap = container_of(shrinker, struct ion_heap,
|
||||
shrinker);
|
||||
int freed = 0;
|
||||
int to_scan = sc->nr_to_scan;
|
||||
|
||||
if (to_scan == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* shrink the free list first, no point in zeroing the memory if we're
|
||||
* just going to reclaim it. Also, skip any possible page pooling.
|
||||
*/
|
||||
if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
|
||||
freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) /
|
||||
PAGE_SIZE;
|
||||
|
||||
to_scan -= freed;
|
||||
if (to_scan <= 0)
|
||||
return freed;
|
||||
|
||||
if (heap->ops->shrink)
|
||||
freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan);
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
int ion_heap_init_shrinker(struct ion_heap *heap)
|
||||
{
|
||||
heap->shrinker.count_objects = ion_heap_shrink_count;
|
||||
|
|
|
|||
|
|
@ -52,5 +52,4 @@ extern struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len,
|
|||
unsigned int flags);
|
||||
extern int ion_free(struct ion_buffer *buffer);
|
||||
|
||||
|
||||
#endif /* _ION_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer)
|
|||
|
||||
/* zero the buffer before goto page pool */
|
||||
if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE))
|
||||
ion_heap_buffer_zero(buffer);
|
||||
ion_buffer_zero(buffer);
|
||||
|
||||
for_each_sg(table->sgl, sg, table->nents, i)
|
||||
free_buffer_page(sys_heap, buffer, sg_page(sg));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user