forked from rubenslte/android_kernel_samsung_msm8226
msm: kgsl: Add support for bulk cache operations
Add a new ioctl, IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK, which can be used to sync a number of memory ids at once. This gives the driver an opportunity to optimize the cache operations based on the total working set of memory that needs to be managed. Change-Id: I9693c54cb6f12468b7d9abb0afaef348e631a114 Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <mach/socinfo.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/sort.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include "kgsl.h"
|
||||
#include "kgsl_debugfs.h"
|
||||
@@ -2104,6 +2106,82 @@ kgsl_ioctl_gpumem_sync_cache(struct kgsl_device_private *dev_priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_id_cmp(const void *_a, const void *_b)
|
||||
{
|
||||
const unsigned int *a = _a, *b = _b;
|
||||
int cmp = a - b;
|
||||
return (cmp < 0) ? -1 : (cmp > 0);
|
||||
}
|
||||
|
||||
static long
|
||||
kgsl_ioctl_gpumem_sync_cache_bulk(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
int i;
|
||||
struct kgsl_gpumem_sync_cache_bulk *param = data;
|
||||
struct kgsl_process_private *private = dev_priv->process_priv;
|
||||
unsigned int id, last_id = 0, *id_list = NULL, actual_count = 0;
|
||||
struct kgsl_mem_entry **entries = NULL;
|
||||
long ret = 0;
|
||||
|
||||
if (param->id_list == NULL || param->count == 0
|
||||
|| param->count > (UINT_MAX/sizeof(unsigned int)))
|
||||
return -EINVAL;
|
||||
|
||||
id_list = kzalloc(param->count * sizeof(unsigned int), GFP_KERNEL);
|
||||
if (id_list == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
entries = kzalloc(param->count * sizeof(*entries), GFP_KERNEL);
|
||||
if (entries == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (copy_from_user(id_list, param->id_list,
|
||||
param->count * sizeof(unsigned int))) {
|
||||
ret = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
/* sort the ids so we can weed out duplicates */
|
||||
sort(id_list, param->count, sizeof(int), mem_id_cmp, NULL);
|
||||
|
||||
for (i = 0; i < param->count; i++) {
|
||||
unsigned int cachemode;
|
||||
struct kgsl_mem_entry *entry = NULL;
|
||||
|
||||
id = id_list[i];
|
||||
/* skip 0 ids or duplicates */
|
||||
if (id == last_id)
|
||||
continue;
|
||||
|
||||
entry = kgsl_sharedmem_find_id(private, id);
|
||||
if (entry == NULL)
|
||||
continue;
|
||||
|
||||
/* skip uncached memory */
|
||||
cachemode = kgsl_memdesc_get_cachemode(&entry->memdesc);
|
||||
if (cachemode != KGSL_CACHEMODE_WRITETHROUGH &&
|
||||
cachemode != KGSL_CACHEMODE_WRITEBACK) {
|
||||
kgsl_mem_entry_put(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
entries[actual_count++] = entry;
|
||||
|
||||
last_id = id;
|
||||
}
|
||||
|
||||
for (i = 0; i < actual_count; i++) {
|
||||
_kgsl_gpumem_sync_cache(entries[i], param->op);
|
||||
kgsl_mem_entry_put(entries[i]);
|
||||
}
|
||||
end:
|
||||
kfree(entries);
|
||||
kfree(id_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Legacy cache function, does a flush (clean + invalidate) */
|
||||
|
||||
static long
|
||||
@@ -2510,6 +2588,8 @@ static const struct {
|
||||
kgsl_ioctl_gpumem_get_info, 0),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE,
|
||||
kgsl_ioctl_gpumem_sync_cache, 0),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK,
|
||||
kgsl_ioctl_gpumem_sync_cache_bulk, 0),
|
||||
};
|
||||
|
||||
static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
|
||||
@@ -781,6 +781,27 @@ struct kgsl_perfcounter_read {
|
||||
|
||||
#define IOCTL_KGSL_PERFCOUNTER_READ \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x3B, struct kgsl_perfcounter_read)
|
||||
/*
|
||||
* struct kgsl_gpumem_sync_cache_bulk - argument to
|
||||
* IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK
|
||||
* @id_list: list of GPU buffer ids of the buffers to sync
|
||||
* @count: number of GPU buffer ids in id_list
|
||||
* @op: a mask of KGSL_GPUMEM_CACHE_* values
|
||||
*
|
||||
* Sync the cache for memory headed to and from the GPU. Certain
|
||||
* optimizations can be made on the cache operation based on the total
|
||||
* size of the working set of memory to be managed.
|
||||
*/
|
||||
struct kgsl_gpumem_sync_cache_bulk {
|
||||
unsigned int *id_list;
|
||||
unsigned int count;
|
||||
unsigned int op;
|
||||
/* private: reserved for future use */
|
||||
unsigned int __pad[2]; /* For future binary compatibility */
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x3C, struct kgsl_gpumem_sync_cache_bulk)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_MSM_KGSL_DRM
|
||||
|
||||
Reference in New Issue
Block a user