/**1* \file drm_debugfs.c2* debugfs support for DRM3*4* \author Ben Gamari <[email protected]>5*/67/*8* Created: Sun Dec 21 13:08:50 2008 by [email protected]9*10* Copyright 2008 Ben Gamari <[email protected]>11*12* Permission is hereby granted, free of charge, to any person obtaining a13* copy of this software and associated documentation files (the "Software"),14* to deal in the Software without restriction, including without limitation15* the rights to use, copy, modify, merge, publish, distribute, sublicense,16* and/or sell copies of the Software, and to permit persons to whom the17* Software is furnished to do so, subject to the following conditions:18*19* The above copyright notice and this permission notice (including the next20* paragraph) shall be included in all copies or substantial portions of the21* Software.22*23* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR24* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,25* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL26* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR27* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,28* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR29* OTHER DEALINGS IN THE SOFTWARE.30*/3132#include <linux/debugfs.h>33#include <linux/seq_file.h>34#include <linux/slab.h>35#include "drmP.h"3637#if defined(CONFIG_DEBUG_FS)3839/***************************************************40* Initialization, etc.41**************************************************/4243static struct drm_info_list drm_debugfs_list[] = {44{"name", drm_name_info, 0},45{"vm", drm_vm_info, 0},46{"clients", drm_clients_info, 0},47{"queues", drm_queues_info, 0},48{"bufs", drm_bufs_info, 0},49{"gem_names", drm_gem_name_info, DRIVER_GEM},50#if DRM_DEBUG_CODE51{"vma", drm_vma_info, 0},52#endif53};54#define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list)555657static int drm_debugfs_open(struct inode *inode, struct file *file)58{59struct drm_info_node *node = inode->i_private;6061return single_open(file, node->info_ent->show, node);62}636465static const struct file_operations drm_debugfs_fops = {66.owner = THIS_MODULE,67.open = drm_debugfs_open,68.read = seq_read,69.llseek = seq_lseek,70.release = single_release,71};727374/**75* Initialize a given set of debugfs files for a device76*77* \param files The array of files to create78* \param count The number of files given79* \param root DRI debugfs dir entry.80* \param minor device minor number81* \return Zero on success, non-zero on failure82*83* Create a given set of debugfs files represented by an array of84* gdm_debugfs_lists in the given root directory.85*/86int drm_debugfs_create_files(struct drm_info_list *files, int count,87struct dentry *root, struct drm_minor *minor)88{89struct drm_device *dev = minor->dev;90struct dentry *ent;91struct drm_info_node *tmp;92char name[64];93int i, ret;9495for (i = 0; i < count; i++) {96u32 features = files[i].driver_features;9798if (features != 0 &&99(dev->driver->driver_features & features) != features)100continue;101102tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);103if (tmp == NULL) {104ret = -1;105goto fail;106}107ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,108root, tmp, &drm_debugfs_fops);109if (!ent) {110DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",111name, files[i].name);112kfree(tmp);113ret = -1;114goto fail;115}116117tmp->minor = minor;118tmp->dent = ent;119tmp->info_ent = &files[i];120list_add(&(tmp->list), &(minor->debugfs_nodes.list));121}122return 0;123124fail:125drm_debugfs_remove_files(files, count, minor);126return ret;127}128EXPORT_SYMBOL(drm_debugfs_create_files);129130/**131* Initialize the DRI debugfs filesystem for a device132*133* \param dev DRM device134* \param minor device minor number135* \param root DRI debugfs dir entry.136*137* Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry138* "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as139* "/sys/kernel/debug/dri/%minor%/%name%".140*/141int drm_debugfs_init(struct drm_minor *minor, int minor_id,142struct dentry *root)143{144struct drm_device *dev = minor->dev;145char name[64];146int ret;147148INIT_LIST_HEAD(&minor->debugfs_nodes.list);149sprintf(name, "%d", minor_id);150minor->debugfs_root = debugfs_create_dir(name, root);151if (!minor->debugfs_root) {152DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s\n", name);153return -1;154}155156ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES,157minor->debugfs_root, minor);158if (ret) {159debugfs_remove(minor->debugfs_root);160minor->debugfs_root = NULL;161DRM_ERROR("Failed to create core drm debugfs files\n");162return ret;163}164165if (dev->driver->debugfs_init) {166ret = dev->driver->debugfs_init(minor);167if (ret) {168DRM_ERROR("DRM: Driver failed to initialize "169"/sys/kernel/debug/dri.\n");170return ret;171}172}173return 0;174}175176177/**178* Remove a list of debugfs files179*180* \param files The list of files181* \param count The number of files182* \param minor The minor of which we should remove the files183* \return always zero.184*185* Remove all debugfs entries created by debugfs_init().186*/187int drm_debugfs_remove_files(struct drm_info_list *files, int count,188struct drm_minor *minor)189{190struct list_head *pos, *q;191struct drm_info_node *tmp;192int i;193194for (i = 0; i < count; i++) {195list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {196tmp = list_entry(pos, struct drm_info_node, list);197if (tmp->info_ent == &files[i]) {198debugfs_remove(tmp->dent);199list_del(pos);200kfree(tmp);201}202}203}204return 0;205}206EXPORT_SYMBOL(drm_debugfs_remove_files);207208/**209* Cleanup the debugfs filesystem resources.210*211* \param minor device minor number.212* \return always zero.213*214* Remove all debugfs entries created by debugfs_init().215*/216int drm_debugfs_cleanup(struct drm_minor *minor)217{218struct drm_device *dev = minor->dev;219220if (!minor->debugfs_root)221return 0;222223if (dev->driver->debugfs_cleanup)224dev->driver->debugfs_cleanup(minor);225226drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);227228debugfs_remove(minor->debugfs_root);229minor->debugfs_root = NULL;230231return 0;232}233234#endif /* CONFIG_DEBUG_FS */235236237238