The DMA-BUF op can be invoked when a process that allocated a buffer relinquishes its ownership and passes it over to another process.
Signed-off-by: Hridya Valsaraju hridya@google.com --- drivers/dma-buf/heaps/system_heap.c | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index adfdc8c576f2..70f5b98f1157 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -307,6 +307,48 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) kfree(buffer); }
+#ifdef CONFIG_CGROUP_GPU +static int system_heap_dma_buf_charge(struct dma_buf *dmabuf, struct gpucg *gpucg) +{ + struct gpucg *current_gpucg; + struct gpucg_device *gpucg_dev; + struct system_heap_buffer *buffer = dmabuf->priv; + size_t len = buffer->len; + int ret = 0; + + /* + * Check that the process requesting the transfer is the same as the one + * to whom the buffer is currently charged to. + */ + current_gpucg = gpucg_get(current); + if (current_gpucg != buffer->gpucg) + ret = -EPERM; + + gpucg_put(current_gpucg); + if (ret) + return ret; + + gpucg_dev = dma_heap_get_gpucg_dev(buffer->heap); + + ret = gpucg_try_charge(gpucg, gpucg_dev, len); + if (ret) + return ret; + + /* uncharge the buffer from the cgroup its currently charged to. */ + gpucg_uncharge(buffer->gpucg, gpucg_dev, buffer->len); + gpucg_put(buffer->gpucg); + + buffer->gpucg = gpucg; + + return 0; +} +#else +static int system_heap_dma_buf_charge(struct dma_buf *dmabuf, struct gpucg *gpucg) +{ + return 0; +} +#endif + static const struct dma_buf_ops system_heap_buf_ops = { .attach = system_heap_attach, .detach = system_heap_detach, @@ -318,6 +360,7 @@ static const struct dma_buf_ops system_heap_buf_ops = { .vmap = system_heap_vmap, .vunmap = system_heap_vunmap, .release = system_heap_dma_buf_release, + .charge_to_cgroup = system_heap_dma_buf_charge, };
static struct page *alloc_largest_available(unsigned long size,