mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
msm: kgsl: Use system memory for kernel globals
Kernel global GPU memory usually lasts for the life of the driver. It doesn't make any sense to take them out of the KGSL pool since they will never be recycled. Add a flag to allocate 4k pages from system memory and use them by default for global objects. Change-Id: Ic0dedbadd0ff1f558d5f9711ec9843451593aee4 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
parent
d014ef6064
commit
0977dc6d53
2 changed files with 120 additions and 6 deletions
|
|
@ -176,6 +176,8 @@ struct kgsl_memdesc_ops {
|
|||
#define KGSL_MEMDESC_UCODE BIT(7)
|
||||
/* For global buffers, randomly assign an address from the region */
|
||||
#define KGSL_MEMDESC_RANDOM BIT(8)
|
||||
/* Allocate memory from the system instead of the pools */
|
||||
#define KGSL_MEMDESC_SYSMEM BIT(9)
|
||||
|
||||
/**
|
||||
* struct kgsl_memdesc - GPU memory object descriptor
|
||||
|
|
|
|||
|
|
@ -862,6 +862,38 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc)
|
|||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER)
|
||||
static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
int ret = unlock_sgt(memdesc->sgt);
|
||||
|
||||
if (ret) {
|
||||
/*
|
||||
* Unlock of the secure buffer failed. This buffer will
|
||||
* be stuck in secure side forever and is unrecoverable.
|
||||
* Give up on the buffer and don't return it to the
|
||||
* pool.
|
||||
*/
|
||||
pr_err("kgsl: secure buf unlock failed: gpuaddr: %llx size: %llx ret: %d\n",
|
||||
memdesc->gpuaddr, memdesc->size, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_long_sub(memdesc->size, &kgsl_driver.stats.secure);
|
||||
|
||||
for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
|
||||
struct page *page = sg_page(sg);
|
||||
|
||||
__free_pages(page, get_order(PAGE_SIZE));
|
||||
}
|
||||
|
||||
sg_free_table(memdesc->sgt);
|
||||
kfree(memdesc->sgt);
|
||||
|
||||
memdesc->sgt = NULL;
|
||||
}
|
||||
|
||||
static void kgsl_free_secure_pool_pages(struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int ret = unlock_sgt(memdesc->sgt);
|
||||
|
|
@ -904,6 +936,23 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc)
|
|||
memdesc->pages = NULL;
|
||||
}
|
||||
|
||||
static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int i;
|
||||
|
||||
kgsl_paged_unmap_kernel(memdesc);
|
||||
WARN_ON(memdesc->hostptr);
|
||||
|
||||
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
|
||||
|
||||
for (i = 0; i < memdesc->page_count; i++)
|
||||
__free_pages(memdesc->pages[i], get_order(PAGE_SIZE));
|
||||
|
||||
memdesc->page_count = 0;
|
||||
kvfree(memdesc->pages);
|
||||
memdesc->pages = NULL;
|
||||
}
|
||||
|
||||
static struct kgsl_memdesc_ops kgsl_contiguous_ops = {
|
||||
.free = kgsl_contiguous_free,
|
||||
.vmflags = VM_DONTDUMP | VM_PFNMAP | VM_DONTEXPAND | VM_DONTCOPY,
|
||||
|
|
@ -911,6 +960,11 @@ static struct kgsl_memdesc_ops kgsl_contiguous_ops = {
|
|||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER)
|
||||
static struct kgsl_memdesc_ops kgsl_secure_system_ops = {
|
||||
.free = kgsl_free_secure_system_pages,
|
||||
/* FIXME: Make sure vmflags / vmfault does the right thing here */
|
||||
};
|
||||
|
||||
static struct kgsl_memdesc_ops kgsl_secure_pool_ops = {
|
||||
.free = kgsl_free_secure_pool_pages,
|
||||
/* FIXME: Make sure vmflags / vmfault does the right thing here */
|
||||
|
|
@ -925,6 +979,49 @@ static struct kgsl_memdesc_ops kgsl_pool_ops = {
|
|||
.unmap_kernel = kgsl_paged_unmap_kernel,
|
||||
};
|
||||
|
||||
static struct kgsl_memdesc_ops kgsl_system_ops = {
|
||||
.free = kgsl_free_system_pages,
|
||||
.vmflags = VM_DONTDUMP | VM_DONTEXPAND | VM_DONTCOPY | VM_MIXEDMAP,
|
||||
.vmfault = kgsl_paged_vmfault,
|
||||
.map_kernel = kgsl_paged_map_kernel,
|
||||
.unmap_kernel = kgsl_paged_unmap_kernel,
|
||||
};
|
||||
|
||||
static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
|
||||
struct device *dev)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
struct page **local;
|
||||
int i, npages = size >> PAGE_SHIFT;
|
||||
|
||||
local = kvcalloc(npages, sizeof(*pages), GFP_KERNEL | __GFP_NORETRY);
|
||||
if (!local)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < npages; i++) {
|
||||
gfp_t gfp = __GFP_ZERO | __GFP_HIGHMEM |
|
||||
GFP_KERNEL | __GFP_NORETRY;
|
||||
|
||||
local[i] = alloc_pages(gfp, get_order(PAGE_SIZE));
|
||||
if (!local[i]) {
|
||||
for (i = i - 1; i >= 0; i--)
|
||||
__free_pages(local[i], get_order(PAGE_SIZE));
|
||||
kvfree(local);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Make sure the cache is clean */
|
||||
sg_init_table(&sg, 1);
|
||||
sg_set_page(&sg, local[i], PAGE_SIZE, 0);
|
||||
sg_dma_address(&sg) = page_to_phys(local[i]);
|
||||
|
||||
dma_sync_sg_for_device(dev, &sg, 1, DMA_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
*pages = local;
|
||||
return npages;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER)
|
||||
static int kgsl_alloc_secure_pages(struct kgsl_device *device,
|
||||
struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv)
|
||||
|
|
@ -942,8 +1039,13 @@ static int kgsl_alloc_secure_pages(struct kgsl_device *device,
|
|||
kgsl_memdesc_init(device, memdesc, flags);
|
||||
memdesc->priv |= priv;
|
||||
|
||||
memdesc->ops = &kgsl_secure_pool_ops;
|
||||
count = kgsl_pool_alloc_pages(size, &pages, device->dev);
|
||||
if (priv & KGSL_MEMDESC_SYSMEM) {
|
||||
memdesc->ops = &kgsl_secure_system_ops;
|
||||
count = kgsl_system_alloc_pages(size, &pages, device->dev);
|
||||
} else {
|
||||
memdesc->ops = &kgsl_secure_pool_ops;
|
||||
count = kgsl_pool_alloc_pages(size, &pages, device->dev);
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
|
@ -997,8 +1099,13 @@ static int kgsl_alloc_pages(struct kgsl_device *device,
|
|||
kgsl_memdesc_init(device, memdesc, flags);
|
||||
memdesc->priv |= priv;
|
||||
|
||||
memdesc->ops = &kgsl_pool_ops;
|
||||
count = kgsl_pool_alloc_pages(size, &pages, device->dev);
|
||||
if (priv & KGSL_MEMDESC_SYSMEM) {
|
||||
memdesc->ops = &kgsl_system_ops;
|
||||
count = kgsl_system_alloc_pages(size, &pages, device->dev);
|
||||
} else {
|
||||
memdesc->ops = &kgsl_pool_ops;
|
||||
count = kgsl_pool_alloc_pages(size, &pages, device->dev);
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
|
@ -1158,7 +1265,8 @@ kgsl_allocate_secure_global(struct kgsl_device *device,
|
|||
if (!md)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
priv |= KGSL_MEMDESC_GLOBAL;
|
||||
/* Make sure that we get global memory from system memory */
|
||||
priv |= KGSL_MEMDESC_GLOBAL | KGSL_MEMDESC_SYSMEM;
|
||||
|
||||
ret = kgsl_allocate_secure(device, &md->memdesc, size, flags, priv);
|
||||
if (ret) {
|
||||
|
|
@ -1197,7 +1305,11 @@ struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device,
|
|||
if (!md)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
priv |= KGSL_MEMDESC_GLOBAL;
|
||||
/*
|
||||
* Make sure that we get global memory from system memory to keep from
|
||||
* taking up pool memory for the life of the driver
|
||||
*/
|
||||
priv |= KGSL_MEMDESC_GLOBAL | KGSL_MEMDESC_SYSMEM;
|
||||
|
||||
ret = kgsl_allocate_kernel(device, &md->memdesc, size, flags, priv);
|
||||
if (ret) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue