@@ -42,6 +42,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/dma-buf.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/freezer.h>
@@ -2482,8 +2483,10 @@ static int binder_translate_fd_array(struct list_head *pf_head,
{
binder_size_t fdi, fd_buf_size;
binder_size_t fda_offset;
+ bool transfer_gpu_charge = false;
const void __user *sender_ufda_base;
struct binder_proc *proc = thread->proc;
+ struct binder_proc *target_proc = t->to_proc;
int ret;
fd_buf_size = sizeof(u32) * fda->num_fds;
@@ -2521,8 +2524,15 @@ static int binder_translate_fd_array(struct list_head *pf_head,
if (ret)
return ret;
+ if (IS_ENABLED(CONFIG_CGROUP_GPU) &&
+ parent->flags & BINDER_BUFFER_FLAG_SENDER_NO_NEED)
+ transfer_gpu_charge = true;
+
for (fdi = 0; fdi < fda->num_fds; fdi++) {
u32 fd;
+ struct dma_buf *dmabuf;
+ struct gpucg *gpucg;
+
binder_size_t offset = fda_offset + fdi * sizeof(fd);
binder_size_t sender_uoffset = fdi * sizeof(fd);
@@ -2532,6 +2542,22 @@ static int binder_translate_fd_array(struct list_head *pf_head,
in_reply_to);
if (ret)
return ret > 0 ? -EINVAL : ret;
+
+ if (!transfer_gpu_charge)
+ continue;
+
+ dmabuf = dma_buf_get(fd);
+ if (IS_ERR(dmabuf))
+ continue;
+
+ gpucg = gpucg_get(target_proc->tsk);
+ ret = dma_buf_transfer_charge(dmabuf, gpucg);
+ if (ret) {
+ pr_warn("%d:%d Unable to transfer DMA-BUF fd charge to %d",
+ proc->pid, thread->pid, target_proc->pid);
+ gpucg_put(gpucg);
+ }
+ dma_buf_put(dmabuf);
}
return 0;
}
@@ -137,6 +137,7 @@ struct binder_buffer_object {
enum {
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
+ BINDER_BUFFER_FLAG_SENDER_NO_NEED = 0x02,
};
/* struct binder_fd_array_object - object describing an array of fds in a buffer