Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc44697c authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ion : Merge ion changes for msm-kona kernel upgrade"

parents 910a62fc 247da9f1
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -55,3 +55,15 @@ config ION_FORCE_DMA_SYNC
	  We generally don't want to enable this config as it breaks the
	  cache maintenance model.
	  If you're not sure say N here.

config ION_DEFER_FREE_NO_SCHED_IDLE
	bool "Increases the priority of ION defer free thread"
	depends on ION
	help
	  Certain heaps such as the system heaps make use of a low priority
	  thread to help free buffer allocations back to the pool which might
	  result in future allocations requests going to the buddy instead of
	  the pool when there is a high buffer allocation rate.
	  Choose this option to remove the SCHED_IDLE flag in case of defer
	  free thereby increasing the priority of defer free thread.
	  if you're not sure say Y here.
+9 −12
Original line number Diff line number Diff line
@@ -119,6 +119,9 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
		if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE))
			goto err2;

		if (ret == -EINTR)
			goto err2;

		ion_heap_freelist_drain(heap, 0);
		ret = heap->ops->allocate(heap, buffer, len, flags);
		if (ret)
@@ -217,7 +220,8 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer)
static void ion_buffer_kmap_put(struct ion_buffer *buffer)
{
	if (buffer->kmap_cnt == 0) {
		WARN(1, "Call dma_buf_begin_cpu_access before dma_buf_end_cpu_access\n");
		pr_warn_ratelimited("Call dma_buf_begin_cpu_access before dma_buf_end_cpu_access, pid:%d\n",
				    current->pid);
		return;
	}

@@ -547,8 +551,10 @@ static int ion_sgl_sync_range(struct device *dev, struct scatterlist *sgl,
			sg_dma_addr = sg_dma_address(sg);

		len += sg->length;
		if (len <= offset)
		if (len <= offset) {
			sg_dma_addr += sg->length;
			continue;
		}

		sg_left = len - offset;
		sg_offset = sg->length - sg_left;
@@ -1052,7 +1058,7 @@ struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask,
		if (!((1 << heap->id) & heap_id_mask))
			continue;
		buffer = ion_buffer_create(heap, dev, len, flags);
		if (!IS_ERR(buffer))
		if (!IS_ERR(buffer) || PTR_ERR(buffer) == -EINTR)
			break;
	}
	up_read(&dev->lock);
@@ -1289,12 +1295,3 @@ struct ion_device *ion_device_create(void)
	return idev;
}
EXPORT_SYMBOL(ion_device_create);

void ion_device_destroy(struct ion_device *dev)
{
	misc_deregister(&dev->dev);
	debugfs_remove_recursive(dev->debug_root);
	/* XXX need to free the heaps and clients ? */
	kfree(dev);
}
EXPORT_SYMBOL(ion_device_destroy);
+4 −16
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#define ION_SYSTEM_HEAP_NAME	"system"
#define ION_MM_HEAP_NAME	"mm"
#define ION_SPSS_HEAP_NAME	"spss"
#define ION_SECURE_CARVEOUT_HEAP_NAME	"secure_carveout"
#define ION_QSECOM_HEAP_NAME	"qsecom"
#define ION_QSECOM_TA_HEAP_NAME	"qsecom_ta"
#define ION_SECURE_HEAP_NAME	"secure_heap"
@@ -255,12 +256,6 @@ bool ion_buffer_cached(struct ion_buffer *buffer);
 */
struct ion_device *ion_device_create(void);

/**
 * ion_device_destroy - free and device and it's resource
 * @dev:		the device
 */
void ion_device_destroy(struct ion_device *dev);

/**
 * ion_device_add_heap - adds a heap to the ion device
 * @dev:		the device
@@ -357,25 +352,19 @@ size_t ion_heap_freelist_size(struct ion_heap *heap);
 */

struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data);
void ion_heap_destroy(struct ion_heap *heap);

struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused);
void ion_system_heap_destroy(struct ion_heap *heap);
struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap);
void ion_system_contig_heap_destroy(struct ion_heap *heap);

struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data);
void ion_carveout_heap_destroy(struct ion_heap *heap);

struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data);
void ion_chunk_heap_destroy(struct ion_heap *heap);

#ifdef CONFIG_CMA
struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *data);
void ion_secure_cma_heap_destroy(struct ion_heap *heap);

struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data);
void ion_cma_heap_destroy(struct ion_heap *heap);
#else
static inline struct ion_heap
			*ion_secure_cma_heap_create(struct ion_platform_heap *h)
@@ -389,15 +378,14 @@ static inline struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *h)
{
	return NULL;
}

static inline void ion_cma_heap_destroy(struct ion_heap *h) {}
#endif

struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *heap);
void ion_system_secure_heap_destroy(struct ion_heap *heap);

struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap);
void ion_cma_secure_heap_destroy(struct ion_heap *heap);

struct ion_heap *
ion_secure_carveout_heap_create(struct ion_platform_heap *heap);

/**
 * functions for creating and destroying a heap pool -- allows you
+200 −3
Original line number Diff line number Diff line
@@ -13,7 +13,12 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <soc/qcom/secure_buffer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/msm_ion.h>
#include "ion.h"
#include "ion_secure_util.h"

#define ION_CARVEOUT_ALLOCATE_FAIL	-1

@@ -113,7 +118,9 @@ static struct ion_heap_ops carveout_heap_ops = {
	.unmap_kernel = ion_heap_unmap_kernel,
};

struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
static struct ion_heap *
__ion_carveout_heap_create(struct ion_platform_heap *heap_data,
			   bool sync)
{
	struct ion_carveout_heap *carveout_heap;
	int ret;
@@ -125,6 +132,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
	page = pfn_to_page(PFN_DOWN(heap_data->base));
	size = heap_data->size;

	if (sync)
		ion_pages_sync_for_device(dev, page, size, DMA_BIDIRECTIONAL);

	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
@@ -150,7 +158,12 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
	return &carveout_heap->heap;
}

void ion_carveout_heap_destroy(struct ion_heap *heap)
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
{
	return __ion_carveout_heap_create(heap_data, true);
}

static void ion_carveout_heap_destroy(struct ion_heap *heap)
{
	struct ion_carveout_heap *carveout_heap =
	     container_of(heap, struct  ion_carveout_heap, heap);
@@ -159,3 +172,187 @@ void ion_carveout_heap_destroy(struct ion_heap *heap)
	kfree(carveout_heap);
	carveout_heap = NULL;
}

struct ion_sc_entry {
	struct list_head list;
	struct ion_heap *heap;
	u32 token;
};

struct ion_sc_heap {
	struct ion_heap heap;
	struct device *dev;
	struct list_head children;
};

static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags)
{
	struct ion_sc_heap *manager;
	struct ion_sc_entry *entry;

	manager = container_of(heap, struct ion_sc_heap, heap);
	flags = flags & ION_FLAGS_CP_MASK;
	list_for_each_entry(entry, &manager->children, list) {
		if (entry->token == flags)
			return entry->heap;
	}
	return NULL;
}

static int ion_sc_heap_allocate(struct ion_heap *heap,
				struct ion_buffer *buffer, unsigned long len,
				 unsigned long flags)
{
	struct ion_heap *child;

	/* cache maintenance is not possible on secure memory */
	flags &= ~((unsigned long)ION_FLAG_CACHED);
	buffer->flags = flags;

	child = ion_sc_find_child(heap, flags);
	if (!child)
		return -EINVAL;
	return ion_carveout_heap_allocate(child, buffer, len, flags);
}

static void ion_sc_heap_free(struct ion_buffer *buffer)
{
	struct ion_heap *child;
	struct sg_table *table = buffer->sg_table;
	struct page *page = sg_page(table->sgl);
	phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));

	child = ion_sc_find_child(buffer->heap, buffer->flags);
	if (!child) {
		WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n.");
		return;
	}

	ion_carveout_free(child, paddr, buffer->size);
	sg_free_table(table);
	kfree(table);
}

static struct ion_heap_ops ion_sc_heap_ops = {
	.allocate = ion_sc_heap_allocate,
	.free = ion_sc_heap_free,
};

static int ion_sc_get_dt_token(struct ion_sc_entry *entry,
			       struct device_node *np, u64 base, u64 size)
{
	u32 token;
	int ret = -EINVAL;

	if (of_property_read_u32(np, "token", &token))
		return -EINVAL;

	ret = ion_hyp_assign_from_flags(base, size, token);
	if (ret)
		pr_err("secure_carveout_heap: Assign token 0x%x failed\n",
		       token);
	else
		entry->token = token;

	return ret;
}

static int ion_sc_add_child(struct ion_sc_heap *manager,
			    struct device_node *np)
{
	struct device *dev = manager->dev;
	struct ion_platform_heap heap_data = {0};
	struct ion_sc_entry *entry;
	struct device_node *phandle;
	const __be32 *basep;
	u64 base, size;
	int ret;

	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
		return -ENOMEM;

	INIT_LIST_HEAD(&entry->list);

	phandle = of_parse_phandle(np, "memory-region", 0);
	if (!phandle)
		goto out_free;

	basep = of_get_address(phandle,  0, &size, NULL);
	if (!basep)
		goto out_free;

	base = of_translate_address(phandle, basep);
	if (base == OF_BAD_ADDR)
		goto out_free;

	heap_data.priv = dev;
	heap_data.base = base;
	heap_data.size = size;

	/* This will zero memory initially */
	entry->heap = __ion_carveout_heap_create(&heap_data, false);
	if (IS_ERR(entry->heap))
		goto out_free;

	ret = ion_sc_get_dt_token(entry, np, base, size);
	if (ret)
		goto out_free_carveout;

	list_add(&entry->list, &manager->children);
	dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n",
		 base, size);
	return 0;

out_free_carveout:
	ion_carveout_heap_destroy(entry->heap);
out_free:
	kfree(entry);
	return -EINVAL;
}

static void ion_secure_carveout_heap_destroy(struct ion_heap *heap)
{
	struct ion_sc_heap *manager =
		container_of(heap, struct ion_sc_heap, heap);
	struct ion_sc_entry *entry, *tmp;

	list_for_each_entry_safe(entry, tmp, &manager->children, list) {
		ion_carveout_heap_destroy(entry->heap);
		kfree(entry);
	}
	kfree(manager);
}

struct ion_heap *
ion_secure_carveout_heap_create(struct ion_platform_heap *heap_data)
{
	struct device *dev = heap_data->priv;
	int ret;
	struct ion_sc_heap *manager;
	struct device_node *np;

	manager = kzalloc(sizeof(*manager), GFP_KERNEL);
	if (!manager)
		return ERR_PTR(-ENOMEM);

	INIT_LIST_HEAD(&manager->children);
	manager->dev = dev;

	for_each_child_of_node(dev->of_node, np) {
		ret = ion_sc_add_child(manager, np);
		if (ret) {
			dev_err(dev, "Creating child pool %s failed\n",
				np->name);
			goto err;
		}
	}

	manager->heap.ops = &ion_sc_heap_ops;
	manager->heap.type = (enum ion_heap_type)ION_HEAP_TYPE_SECURE_CARVEOUT;
	return &manager->heap;

err:
	ion_secure_carveout_heap_destroy(&manager->heap);
	return ERR_PTR(-EINVAL);
}
+0 −10
Original line number Diff line number Diff line
@@ -156,13 +156,3 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
	kfree(chunk_heap);
	return ERR_PTR(ret);
}

void ion_chunk_heap_destroy(struct ion_heap *heap)
{
	struct ion_chunk_heap *chunk_heap =
	     container_of(heap, struct  ion_chunk_heap, heap);

	gen_pool_destroy(chunk_heap->pool);
	kfree(chunk_heap);
	chunk_heap = NULL;
}
Loading