diff options
| author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-06-01 16:56:02 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-06-01 16:56:02 -0700 |
| commit | e0b49f46eddb54a1dd6bd6046dcba56c39ed1e6d (patch) | |
| tree | 62c94dc2a762c8275da8ba6025c878cc2d1522ac | |
| parent | d1cf82998e55e50aed7c2282b55909b792c416f9 (diff) | |
| parent | 7490d55401dde0c69815ed9aeadd1fa36a1df7e2 (diff) | |
Merge "msm: kgsl: Use per page cache operation instead of bulk cache operation"
| -rw-r--r-- | drivers/gpu/msm/kgsl_sharedmem.c | 57 |
1 files changed, 29 insertions, 28 deletions
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index fa95b4dfe718..7f4a5a3b251f 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -623,6 +623,9 @@ int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size, unsigned int op) { void *addr = NULL; + struct sg_table *sgt = NULL; + struct scatterlist *sg; + unsigned int i, pos = 0; int ret = 0; if (size == 0 || size > UINT_MAX) @@ -650,40 +653,38 @@ int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset, * If the buffer is not to mapped to kernel, perform cache * operations after mapping to kernel. */ - if (memdesc->sgt != NULL) { - struct scatterlist *sg; - unsigned int i, pos = 0; + if (memdesc->sgt != NULL) + sgt = memdesc->sgt; + else { + if (memdesc->pages == NULL) + return ret; + + sgt = kgsl_alloc_sgt_from_pages(memdesc); + if (IS_ERR(sgt)) + return PTR_ERR(sgt); + } - for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) { - uint64_t sg_offset, sg_left; + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + uint64_t sg_offset, sg_left; - if (offset >= (pos + sg->length)) { - pos += sg->length; - continue; - } - sg_offset = offset > pos ? offset - pos : 0; - sg_left = (sg->length - sg_offset > size) ? size : - sg->length - sg_offset; - ret = kgsl_do_cache_op(sg_page(sg), NULL, sg_offset, - sg_left, op); - size -= sg_left; - if (size == 0) - break; + if (offset >= (pos + sg->length)) { pos += sg->length; + continue; } - } else if (memdesc->pages != NULL) { - addr = vmap(memdesc->pages, memdesc->page_count, - VM_IOREMAP, pgprot_writecombine(PAGE_KERNEL)); - if (addr == NULL) - return -ENOMEM; + sg_offset = offset > pos ? offset - pos : 0; + sg_left = (sg->length - sg_offset > size) ? size : + sg->length - sg_offset; + ret = kgsl_do_cache_op(sg_page(sg), NULL, sg_offset, + sg_left, op); + size -= sg_left; + if (size == 0) + break; + pos += sg->length; + } - /* Make sure the offset + size do not overflow the address */ - if (addr + ((size_t) offset + (size_t) size) < addr) - return -ERANGE; + if (memdesc->sgt == NULL) + kgsl_free_sgt(sgt); - ret = kgsl_do_cache_op(NULL, addr, offset, size, op); - vunmap(addr); - } return ret; } EXPORT_SYMBOL(kgsl_cache_range_op); |
