From dea4ace78ec70271809431885e4b16d4cea777e3 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Thu, 4 Jun 2020 18:04:31 +0900 Subject: [PATCH] drm/vc4: Add gem_info node via debugfs The memps requires gem_info with gem_names to analyze graphics shared memory, so this patch adds gem_info node via common helpers for debugfs. Let's save pid/tgid in private file data only once when gem object is created or prime_fd is imported and use them on gem_info. This is to solve the wrong pid problem of gem_info created as different processes share fd of drm device node. This patch referenced [1] and a modified debugfs interface was applied. [1] f7a145cb5173 drm/vc4: add gem_info node via debugfs Change-Id: Ifbbf4c94ad1c54a682083ed7d30555d8b57164eb Signed-off-by: Joonyoung Shim Signed-off-by: Seung-Woo Kim Signed-off-by: Hoegeun Kwon --- drivers/gpu/drm/vc4/vc4_bo.c | 114 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.c | 2 +- drivers/gpu/drm/vc4/vc4_drv.h | 10 ++++ 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index cfbb610..894298c 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -75,6 +75,75 @@ static int vc4_bo_stats_debugfs(struct seq_file *m, void *unused) return 0; } +struct vc4_gem_info_data { + struct drm_file *filp; + struct seq_file *m; +}; + +static int vc4_gem_one_info(int id, void *ptr, void *data) +{ + struct drm_gem_object *obj = (struct drm_gem_object *)ptr; + struct vc4_gem_info_data *gem_info_data = data; + struct vc4_file *vc4file = gem_info_data->filp->driver_priv; + struct drm_vc4_file_private *file_priv = &vc4file->priv; + + if (!obj) { + DRM_ERROR("failed to get drm_gem_object\n"); + return -EFAULT; + } + + drm_gem_object_get(obj); + + seq_printf(gem_info_data->m, + "%5d\t%5d\t%4d\t%4d\t\t%4d\t0x%08zx\t0x%x\t%4d\t%4d\t\t" + "%4d\t\t0x%p\t%6d\n", + file_priv->pid, + file_priv->tgid, + id, + kref_read(&obj->refcount) - 1, + obj->handle_count, + obj->size, + 0, + 0, + obj->dma_buf ? 1 : 0, + obj->import_attach ? 1 : 0, + obj, + obj->name); + + drm_gem_object_put(obj); + + return 0; +} + +int vc4_debugfs_gem_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_minor *minor = node->minor; + struct drm_device *drm_dev = minor->dev; + struct vc4_gem_info_data gem_info_data; + struct drm_file *filp; + + gem_info_data.m = m; + + seq_puts(gem_info_data.m, + "pid\ttgid\thandle\trefcount\thcount\tsize\t\tflags\t" + "pfnmap\texport_to_fd\timport_from_fd\tobj_addr\t\t" + "name\n"); + + mutex_lock(&drm_dev->struct_mutex); + list_for_each_entry(filp, &drm_dev->filelist, lhead) { + gem_info_data.filp = filp; + + spin_lock(&filp->table_lock); + idr_for_each(&filp->object_idr, vc4_gem_one_info, + &gem_info_data); + spin_unlock(&filp->table_lock); + } + mutex_unlock(&drm_dev->struct_mutex); + + return 0; +} + /* Takes ownership of *name and returns the appropriate slot for it in * the bo_labels[] array, extending it as necessary. * @@ -469,6 +538,26 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, return bo; } +static void vc4_gem_register_pid(struct drm_file *file_priv) +{ + struct vc4_file *vc4file = file_priv->driver_priv; + struct drm_vc4_file_private *driver_priv = &vc4file->priv; + + if (!driver_priv->pid && !driver_priv->tgid) { + driver_priv->pid = task_pid_nr(current); + driver_priv->tgid = task_tgid_nr(current); + } else { + if (driver_priv->pid != task_pid_nr(current)) + DRM_DEBUG_KMS("wrong pid: %ld, %ld\n", + (unsigned long)driver_priv->pid, + (unsigned long)task_pid_nr(current)); + if (driver_priv->tgid != task_tgid_nr(current)) + DRM_DEBUG_KMS("wrong tgid: %ld, %ld\n", + (unsigned long)driver_priv->tgid, + (unsigned long)task_tgid_nr(current)); + } +} + int vc4_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) @@ -492,6 +581,9 @@ int vc4_dumb_create(struct drm_file *file_priv, ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_put(&bo->base.base); + if (!ret) + vc4_gem_register_pid(file_priv); + return ret; } @@ -700,6 +792,21 @@ vm_fault_t vc4_fault(struct vm_fault *vmf) return VM_FAULT_SIGBUS; } +int vc4_drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle) +{ + int ret; + + ret = drm_gem_prime_fd_to_handle(dev, file_priv, prime_fd, handle); + if (ret < 0) + goto out; + + vc4_gem_register_pid(file_priv); + +out: + return ret; +} + int vc4_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_gem_object *gem_obj; @@ -813,6 +920,9 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data, ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_put(&bo->base.base); + if (!ret) + vc4_gem_register_pid(file_priv); + return ret; } @@ -888,6 +998,9 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, */ ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); + if (!ret) + vc4_gem_register_pid(file_priv); + fail: drm_gem_object_put(&bo->base.base); @@ -999,6 +1112,7 @@ int vc4_bo_cache_init(struct drm_device *dev) mutex_init(&vc4->bo_lock); vc4_debugfs_add_file(dev, "bo_stats", vc4_bo_stats_debugfs, NULL); + vc4_debugfs_add_file(dev, "gem_info", vc4_debugfs_gem_info, NULL); INIT_LIST_HEAD(&vc4->bo_cache.time_list); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 4a11bb6..13e6d7d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -197,7 +197,7 @@ static struct drm_driver vc4_drm_driver = { .gem_vm_ops = &vc4_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .prime_fd_to_handle = vc4_drm_gem_prime_fd_to_handle, .gem_prime_export = vc4_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = vc4_prime_import_sg_table, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index ac71e84..1a4699f2 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -718,6 +718,11 @@ struct vc4_exec_info { struct vc4_perfmon *perfmon; }; +struct drm_vc4_file_private { + pid_t pid; + pid_t tgid; +}; + /* Per-open file private data. Any driver-specific resource that has to be * released when the DRM file is closed should be placed here. */ @@ -726,6 +731,7 @@ struct vc4_file { struct idr idr; struct mutex lock; } perfmon; + struct drm_vc4_file_private priv; }; static inline struct vc4_exec_info * @@ -1018,6 +1024,10 @@ bool vc4_check_tex_size(struct vc4_exec_info *exec, struct vc4_validated_shader_info * vc4_validate_shader(struct drm_gem_cma_object *shader_obj); +int vc4_debugfs_gem_info(struct seq_file *m, void *data); +int vc4_drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle); + /* vc4_perfmon.c */ void vc4_perfmon_get(struct vc4_perfmon *perfmon); void vc4_perfmon_put(struct vc4_perfmon *perfmon); -- 2.7.4