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

Commit 20ef1f47 authored by Jeremy Gebben's avatar Jeremy Gebben
Browse files

msm: kgsl: set usermem type in the memdesc flags



It is sometimes helpful for userspace to know if
a buffer is allocated memory or mapped in from
another driver. Add  KGSL_MEMFLAGS_USERMEM_ values
so this information can be stored into the flags,
which are visible to userspace after the allocation
and map ioctls return, or via IOCTL_KGSL_GPUMEM_GET_INFO.

Because enum kgsl_user_mem_type only accounted for
mapped memory types, the flags value adds 1 to each
enum so that 0 can mean allocated (not mapped)
memory.

Change-Id: I1af71ca5527adb4bae04cfe003afa7d4db1d0a21
Signed-off-by: default avatarJeremy Gebben <jgebben@codeaurora.org>
parent d3dde527
Loading
Loading
Loading
Loading
+41 −24
Original line number Diff line number Diff line
@@ -183,11 +183,18 @@ kgsl_mem_entry_destroy(struct kref *kref)
	struct kgsl_mem_entry *entry = container_of(kref,
						    struct kgsl_mem_entry,
						    refcount);
	unsigned int memtype;

	if (entry == NULL)
		return;

	/* pull out the memtype before the flags get cleared */
	memtype = kgsl_memdesc_usermem_type(&entry->memdesc);

	/* Detach from process list */
	kgsl_mem_entry_detach_process(entry);

	if (entry->memtype != KGSL_MEM_ENTRY_KERNEL)
	if (memtype != KGSL_MEM_ENTRY_KERNEL)
		kgsl_driver.stats.mapped -= entry->memdesc.size;

	/*
@@ -195,14 +202,12 @@ kgsl_mem_entry_destroy(struct kref *kref)
	 * clear the sg before freeing the sharedmem so kgsl_sharedmem_free
	 * doesn't try to free it again
	 */

	if (entry->memtype == KGSL_MEM_ENTRY_ION) {
	if (memtype == KGSL_MEM_ENTRY_ION)
		entry->memdesc.sg = NULL;
	}

	kgsl_sharedmem_free(&entry->memdesc);

	switch (entry->memtype) {
	switch (memtype) {
	case KGSL_MEM_ENTRY_PMEM:
	case KGSL_MEM_ENTRY_ASHMEM:
		if (entry->priv_data)
@@ -211,6 +216,8 @@ kgsl_mem_entry_destroy(struct kref *kref)
	case KGSL_MEM_ENTRY_ION:
		kgsl_destroy_ion(entry->priv_data);
		break;
	default:
		break;
	}

	kfree(entry);
@@ -361,6 +368,7 @@ err_put_proc_priv:

static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
{
	unsigned int type;
	if (entry == NULL)
		return;

@@ -374,7 +382,8 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
		idr_remove(&entry->priv->mem_idr, entry->id);
	entry->id = 0;

	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
	type = kgsl_memdesc_usermem_type(&entry->memdesc);
	entry->priv->stats[type].cur -= entry->memdesc.size;
	spin_unlock(&entry->priv->mem_lock);
	kgsl_put_process_private(entry->dev_priv->device, entry->priv);

@@ -2433,6 +2442,7 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry,
	entry->memdesc.hostptr = (void *) (virt + offset);
	/* USE_CPU_MAP is not impemented for PMEM. */
	entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
	entry->memdesc.flags = KGSL_MEMFLAGS_USERMEM_PMEM;

	ret = memdesc_sg_phys(&entry->memdesc, phys + offset, size);
	if (ret)
@@ -2556,6 +2566,7 @@ static int kgsl_setup_useraddr(struct kgsl_mem_entry *entry,
	entry->memdesc.useraddr = useraddr + (offset & PAGE_MASK);
	if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
		entry->memdesc.gpuaddr = entry->memdesc.useraddr;
	entry->memdesc.flags = KGSL_MEMFLAGS_USERMEM_ADDR;

	return memdesc_sg_virt(&entry->memdesc, entry->memdesc.useraddr,
				size);
@@ -2623,6 +2634,7 @@ static int kgsl_setup_ashmem(struct kgsl_mem_entry *entry,
	entry->memdesc.useraddr = useraddr;
	if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
		entry->memdesc.gpuaddr = entry->memdesc.useraddr;
	entry->memdesc.flags = KGSL_MEMFLAGS_USERMEM_ASHMEM;

	ret = memdesc_sg_virt(&entry->memdesc, useraddr, size);
	if (ret)
@@ -2679,11 +2691,12 @@ static int kgsl_setup_ion(struct kgsl_mem_entry *entry,
	meta->dmabuf = dmabuf;
	meta->attach = attach;

	entry->memtype = KGSL_MEM_ENTRY_ION;
	entry->priv_data = meta;
	entry->memdesc.pagetable = pagetable;
	entry->memdesc.size = 0;
	/* USE_CPU_MAP is not impemented for ION. */
	entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
	entry->memdesc.flags = KGSL_MEMFLAGS_USERMEM_ION;

	sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE);

@@ -2736,17 +2749,21 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
	struct kgsl_map_user_mem *param = data;
	struct kgsl_mem_entry *entry = NULL;
	struct kgsl_process_private *private = dev_priv->process_priv;
	enum kgsl_user_mem_type memtype;
	unsigned int memtype;

	entry = kgsl_mem_entry_create();

	if (entry == NULL)
		return -ENOMEM;

	/*
	 * Convert from enum value to KGSL_MEM_ENTRY value, so that
	 * we can use the latter consistently everywhere.
	 */
	if (_IOC_SIZE(cmd) == sizeof(struct kgsl_sharedmem_from_pmem))
		memtype = KGSL_USER_MEM_TYPE_PMEM;
		memtype = KGSL_MEM_ENTRY_PMEM;
	else
		memtype = param->memtype;
		memtype = param->memtype + 1;

	/*
	 * Mask off unknown flags from userspace. This way the caller can
@@ -2755,11 +2772,11 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
	 * determined by type of allocation being mapped.
	 */
	param->flags &= KGSL_MEMFLAGS_GPUREADONLY
			| KGSL_MEMTYPE_MASK
			| KGSL_MEMALIGN_MASK
			| KGSL_MEMFLAGS_USE_CPU_MAP;

	entry->memdesc.flags = param->flags;

	if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu))
		entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;

@@ -2767,17 +2784,16 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
		entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE;

	switch (memtype) {
	case KGSL_USER_MEM_TYPE_PMEM:
	case KGSL_MEM_ENTRY_PMEM:
		if (param->fd == 0 || param->len == 0)
			break;

		result = kgsl_setup_phys_file(entry, private->pagetable,
					      param->fd, param->offset,
					      param->len);
		entry->memtype = KGSL_MEM_ENTRY_PMEM;
		break;

	case KGSL_USER_MEM_TYPE_ADDR:
	case KGSL_MEM_ENTRY_USER:
		KGSL_DEV_ERR_ONCE(dev_priv->device, "User mem type "
				"KGSL_USER_MEM_TYPE_ADDR is deprecated\n");
		if (!kgsl_mmu_enabled()) {
@@ -2793,10 +2809,9 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
		result = kgsl_setup_useraddr(entry, private->pagetable,
					    param->hostptr,
					    param->offset, param->len);
		entry->memtype = KGSL_MEM_ENTRY_USER;
		break;

	case KGSL_USER_MEM_TYPE_ASHMEM:
	case KGSL_MEM_ENTRY_ASHMEM:
		if (!kgsl_mmu_enabled()) {
			KGSL_DRV_ERR(dev_priv->device,
				"Cannot map paged memory with the "
@@ -2811,9 +2826,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
					   param->fd, param->hostptr,
					   param->len);

		entry->memtype = KGSL_MEM_ENTRY_ASHMEM;
		break;
	case KGSL_USER_MEM_TYPE_ION:
	case KGSL_MEM_ENTRY_ION:
		result = kgsl_setup_ion(entry, private->pagetable, data,
					dev_priv->device);
		break;
@@ -2843,14 +2857,15 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
	KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped,
		kgsl_driver.stats.mapped_max);

	kgsl_process_add_stats(private, entry->memtype, param->len);
	kgsl_process_add_stats(private,
			kgsl_memdesc_usermem_type(&entry->memdesc), param->len);

	trace_kgsl_mem_map(entry, param->fd);

	return result;

error_attach:
	switch (entry->memtype) {
	switch (memtype) {
	case KGSL_MEM_ENTRY_PMEM:
	case KGSL_MEM_ENTRY_ASHMEM:
		if (entry->priv_data)
@@ -3094,8 +3109,6 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv,
	if (result != 0)
		goto err;

	entry->memtype = KGSL_MEM_ENTRY_KERNEL;

	*ret_entry = entry;
	return result;
err:
@@ -3121,7 +3134,9 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
	if (result != 0)
		goto err;

	kgsl_process_add_stats(private, entry->memtype, param->size);
	kgsl_process_add_stats(private,
			kgsl_memdesc_usermem_type(&entry->memdesc),
			param->size);
	trace_kgsl_mem_alloc(entry);

	param->gpuaddr = entry->memdesc.gpuaddr;
@@ -3154,7 +3169,9 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
	if (result != 0)
		goto err;

	kgsl_process_add_stats(private, entry->memtype, param->size);
	kgsl_process_add_stats(private,
			kgsl_memdesc_usermem_type(&entry->memdesc),
			param->size);
	trace_kgsl_mem_alloc(entry);

	param->id = entry->id;
+32 −12
Original line number Diff line number Diff line
@@ -181,27 +181,47 @@ struct kgsl_memdesc {
	struct device *dev;
};

/* List of different memory entry types */

/*
 * List of different memory entry types. The usermem enum
 * starts at 0, which we use for allocated memory, so 1 is
 * added to the enum values.
 */
#define KGSL_MEM_ENTRY_KERNEL 0
#define KGSL_MEM_ENTRY_PMEM   1
#define KGSL_MEM_ENTRY_ASHMEM 2
#define KGSL_MEM_ENTRY_USER   3
#define KGSL_MEM_ENTRY_ION    4
#define KGSL_MEM_ENTRY_MAX    5
#define KGSL_MEM_ENTRY_PMEM (KGSL_USER_MEM_TYPE_PMEM + 1)
#define KGSL_MEM_ENTRY_ASHMEM (KGSL_USER_MEM_TYPE_ASHMEM + 1)
#define KGSL_MEM_ENTRY_USER (KGSL_USER_MEM_TYPE_ADDR + 1)
#define KGSL_MEM_ENTRY_ION (KGSL_USER_MEM_TYPE_ION + 1)
#define KGSL_MEM_ENTRY_MAX (KGSL_USER_MEM_TYPE_MAX + 1)

/* symbolic table for trace and debugfs */
#define KGSL_MEM_TYPES \
	{ KGSL_MEM_ENTRY_KERNEL, "gpumem" }, \
	{ KGSL_MEM_ENTRY_PMEM, "pmem" }, \
	{ KGSL_MEM_ENTRY_ASHMEM, "ashmem" }, \
	{ KGSL_MEM_ENTRY_USER, "usermem" }, \
	{ KGSL_MEM_ENTRY_ION, "ion" }

/*
 * struct kgsl_mem_entry - a userspace memory allocation
 * @refcount: reference count. Currently userspace can only
 *  hold a single reference count, but the kernel may hold more.
 * @memdesc: description of the memory
 * @priv_data: type-specific data, such as the dma-buf attachment pointer.
 * @node: rb_node for the gpu address lookup rb tree
 * @id: idr index for this entry, can be used to find memory that does not have
 *  a valid GPU address.
 * @priv: back pointer to the process that owns this memory
 * @pending_free: if !0, userspace requested that his memory be freed, but there
 *  are still references to it.
 * @dev_priv: back pointer to the device file that created this entry.
 */
struct kgsl_mem_entry {
	struct kref refcount;
	struct kgsl_memdesc memdesc;
	int memtype;
	void *priv_data;
	struct rb_node node;
	unsigned int id;
	unsigned int context_id;
	/* back pointer to private structure under whose context this
	* allocation is made */
	struct kgsl_process_private *priv;
	/* Initialized to 0, set to 1 when entry is marked for freeing */
	int pending_free;
	struct kgsl_device_private *dev_priv;
};
+11 −9
Original line number Diff line number Diff line
@@ -120,18 +120,19 @@ void kgsl_device_debugfs_init(struct kgsl_device *device)
				&memfree_hist_fops);
}

static const char * const memtype_strings[] = {
	"gpumem",
	"pmem",
	"ashmem",
	"usermap",
	"ion",
struct type_entry {
	int type;
	const char *str;
};

static const struct type_entry memtypes[] = { KGSL_MEM_TYPES };

static const char *memtype_str(int memtype)
{
	if (memtype < ARRAY_SIZE(memtype_strings))
		return memtype_strings[memtype];
	int i;
	for (i = 0; i < ARRAY_SIZE(memtypes); i++)
		if (memtypes[i].type == memtype)
			return memtypes[i].str;
	return "unknown";
}

@@ -175,7 +176,8 @@ static void print_mem_entry(struct seq_file *s, struct kgsl_mem_entry *entry)
			(unsigned long *)(uintptr_t) m->gpuaddr,
			(unsigned long *) m->useraddr,
			m->size, entry->id, flags,
			memtype_str(entry->memtype), usage, m->sglen);
			memtype_str(kgsl_memdesc_usermem_type(m)),
			usage, m->sglen);
}

static int process_mem_print(struct seq_file *s, void *unused)
+15 −0
Original line number Diff line number Diff line
@@ -110,6 +110,21 @@ kgsl_memdesc_set_align(struct kgsl_memdesc *memdesc, unsigned int align)
	return 0;
}

/*
 * kgsl_memdesc_usermem_type - return buffer type
 * @memdesc - the memdesc
 *
 * Returns a KGSL_MEM_ENTRY_* value for this buffer, which
 * identifies if was allocated by us, or imported from
 * another allocator.
 */
static inline unsigned int
kgsl_memdesc_usermem_type(const struct kgsl_memdesc *memdesc)
{
	return (memdesc->flags & KGSL_MEMFLAGS_USERMEM_MASK)
		>> KGSL_MEMFLAGS_USERMEM_SHIFT;
}

static inline unsigned int kgsl_get_sg_pa(struct scatterlist *sg)
{
	/*
+1 −1
Original line number Diff line number Diff line
@@ -401,7 +401,7 @@ int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase,
	}

	/* We can't freeze external memory, because we don't own it */
	if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) {
	if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_MASK) {
		KGSL_DRV_ERR(device,
			"Only internal GPU buffers can be frozen\n");
		goto err_put;
Loading