@@ -8,10 +8,11 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/
+#include <linux/cgroup_dmem.h>
#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/refcount.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
@@ -40,10 +41,14 @@ struct vb2_dc_buf {
struct sg_table *sgt_base;
/* DMABUF related */
struct dma_buf_attachment *db_attach;
+#ifdef CONFIG_CGROUP_DMEM
+ struct dmem_cgroup_pool_state *cgroup_pool_state;
+#endif
+
struct vb2_buffer *vb;
bool non_coherent_mem;
};
/*********************************************/
@@ -169,10 +174,14 @@ static void vb2_dc_put(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;
if (!refcount_dec_and_test(&buf->refcount))
return;
+#ifdef CONFIG_CGROUP_DMEM
+ dmem_cgroup_uncharge(buf->cgroup_pool_state, buf->size);
+#endif
+
if (buf->non_coherent_mem) {
if (buf->vaddr)
dma_vunmap_noncontiguous(buf->dev, buf->vaddr);
dma_free_noncontiguous(buf->dev, buf->size,
buf->dma_sgt, buf->dma_dir);
@@ -230,10 +239,11 @@ static int vb2_dc_alloc_non_coherent(struct vb2_dc_buf *buf)
static void *vb2_dc_alloc(struct vb2_buffer *vb,
struct device *dev,
unsigned long size)
{
+ struct dmem_cgroup_pool_state *pool;
struct vb2_dc_buf *buf;
int ret;
if (WARN_ON(!dev))
return ERR_PTR(-EINVAL);
@@ -249,25 +259,34 @@ static void *vb2_dc_alloc(struct vb2_buffer *vb,
buf->size = size;
/* Prevent the device from being released while the buffer is used */
buf->dev = get_device(dev);
+ ret = dmem_cgroup_try_charge(dma_get_dmem_cgroup_region(dev), size, &pool, NULL);
+ if (ret)
+ return ret;
+
if (buf->non_coherent_mem)
ret = vb2_dc_alloc_non_coherent(buf);
else
ret = vb2_dc_alloc_coherent(buf);
if (ret) {
dev_err(dev, "dma alloc of size %lu failed\n", size);
+ dmem_cgroup_uncharge(pool, size);
kfree(buf);
return ERR_PTR(-ENOMEM);
}
buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
+#ifdef CONFIG_CGROUP_DMEM
+ buf->cgroup_pool_state = pool;
+#endif
+
refcount_set(&buf->refcount, 1);
return buf;
}
The dmem cgroup allows to track any DMA memory allocation made by the userspace. Let's charge our allocations in videobuf2 to enable proper memory tracking. Signed-off-by: Maxime Ripard <mripard@kernel.org> --- drivers/media/common/videobuf2/videobuf2-dma-contig.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)