diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 176f22ba570c..c2ef091d72ce 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -157,6 +157,15 @@ int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, } EXPORT_SYMBOL(msm_ion_do_cache_op); +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd) +{ + return ion_do_cache_op(client, handle, vaddr, offset, len, cmd); +} +EXPORT_SYMBOL(msm_ion_do_cache_offset_op); + static int ion_no_pages_cache_ops(struct ion_client *client, struct ion_handle *handle, void *vaddr, @@ -305,13 +314,23 @@ static int ion_pages_cache_ops(struct ion_client *client, }; for_each_sg(table->sgl, sg, table->nents, i) { + unsigned int sg_offset, sg_left, size = 0; + len += sg->length; - if (len < offset) + if (len <= offset) continue; - __do_cache_ops(sg_page(sg), sg->offset, sg->length, op); + sg_left = len - offset; + sg_offset = sg->length - sg_left; - if (len > length + offset) + size = (length < sg_left) ? length : sg_left; + + __do_cache_ops(sg_page(sg), sg_offset, size, op); + + offset += size; + length -= size; + + if (length == 0) break; } return 0; diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h index d8677b2fb55a..098104d56fdb 100644 --- a/drivers/staging/android/ion/msm/msm_ion.h +++ b/drivers/staging/android/ion/msm/msm_ion.h @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #ifndef _MSM_MSM_ION_H #define _MSM_MSM_ION_H @@ -157,6 +170,11 @@ int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle, int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, void *vaddr, unsigned long len, unsigned int cmd); +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd); + #else static inline struct ion_client *msm_ion_client_create(const char *name) { @@ -176,6 +194,14 @@ static inline int msm_ion_do_cache_op(struct ion_client *client, return -ENODEV; } +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd) +{ + return -ENODEV; +} + #endif /* CONFIG_ION */ #endif