staging: android: ion: support partial cpu access

Change-Id: I8250c0bb26b776b8c8f5e4c3ee0cb71e26445743
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
This commit is contained in:
Jianqun Xu
2021-04-07 10:20:12 +08:00
parent d37b518b0e
commit 975372e2cb

View File

@@ -402,6 +402,62 @@ static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
ion_dma_buf_vunmap(dmabuf, ptr); ion_dma_buf_vunmap(dmabuf, ptr);
} }
static int ion_sgl_sync_range(struct device *dev, struct scatterlist *sgl,
unsigned int nents, unsigned int offset,
unsigned int length,
enum dma_data_direction dir, bool for_cpu)
{
int i;
struct scatterlist *sg;
unsigned int len = 0;
dma_addr_t sg_dma_addr;
for_each_sg(sgl, sg, nents, i) {
if (sg_dma_len(sg) == 0)
break;
if (i > 0) {
pr_warn_ratelimited("Partial cmo only supported with 1 segment\n"
"is dma_set_max_seg_size being set on dev:%s\n",
dev_name(dev));
return -EINVAL;
}
}
for_each_sg(sgl, sg, nents, i) {
unsigned int sg_offset, sg_left, size = 0;
if (i == 0)
sg_dma_addr = sg_dma_address(sg);
len += sg->length;
if (len <= offset) {
sg_dma_addr += sg->length;
continue;
}
sg_left = len - offset;
sg_offset = sg->length - sg_left;
size = (length < sg_left) ? length : sg_left;
if (for_cpu)
dma_sync_single_range_for_cpu(dev, sg_dma_addr,
sg_offset, size, dir);
else
dma_sync_single_range_for_device(dev, sg_dma_addr,
sg_offset, size, dir);
offset += size;
length -= size;
sg_dma_addr += sg->length;
if (length == 0)
break;
}
return 0;
}
static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
enum dma_data_direction direction) enum dma_data_direction direction)
{ {
@@ -466,6 +522,56 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return 0; return 0;
} }
static int ion_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction dir,
unsigned int offset,
unsigned int len)
{
struct ion_buffer *buffer = dmabuf->priv;
struct ion_dma_buf_attachment *a;
int ret = 0;
if (!(buffer->flags & ION_FLAG_CACHED))
return 0;
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped)
continue;
ret = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents,
offset, len, dir, true);
}
mutex_unlock(&buffer->lock);
return ret;
}
static int ion_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction direction,
unsigned int offset,
unsigned int len)
{
struct ion_buffer *buffer = dmabuf->priv;
struct ion_dma_buf_attachment *a;
int ret = 0;
if (!(buffer->flags & ION_FLAG_CACHED))
return 0;
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped)
continue;
ret = ion_sgl_sync_range(a->dev, a->table->sgl, a->table->nents,
offset, len, direction, false);
}
mutex_unlock(&buffer->lock);
return ret;
}
static const struct dma_buf_ops dma_buf_ops = { static const struct dma_buf_ops dma_buf_ops = {
.map_dma_buf = ion_map_dma_buf, .map_dma_buf = ion_map_dma_buf,
.unmap_dma_buf = ion_unmap_dma_buf, .unmap_dma_buf = ion_unmap_dma_buf,
@@ -475,6 +581,8 @@ static const struct dma_buf_ops dma_buf_ops = {
.detach = ion_dma_buf_detatch, .detach = ion_dma_buf_detatch,
.begin_cpu_access = ion_dma_buf_begin_cpu_access, .begin_cpu_access = ion_dma_buf_begin_cpu_access,
.end_cpu_access = ion_dma_buf_end_cpu_access, .end_cpu_access = ion_dma_buf_end_cpu_access,
.begin_cpu_access_partial = ion_dma_buf_begin_cpu_access_partial,
.end_cpu_access_partial = ion_dma_buf_end_cpu_access_partial,
.map = ion_dma_buf_kmap, .map = ion_dma_buf_kmap,
.unmap = ion_dma_buf_kunmap, .unmap = ion_dma_buf_kunmap,
.vmap = ion_dma_buf_vmap, .vmap = ion_dma_buf_vmap,