/**1* \file drm_proc.c2* /proc support for DRM3*4* \author Rickard E. (Rik) Faith <[email protected]>5* \author Gareth Hughes <[email protected]>6*7* \par Acknowledgements:8* Matthew J Sottek <[email protected]> sent in a patch to fix9* the problem with the proc files not outputting all their information.10*/1112/*13* Created: Mon Jan 11 09:48:47 1999 by [email protected]14*15* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.16* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.17* All Rights Reserved.18*19* Permission is hereby granted, free of charge, to any person obtaining a20* copy of this software and associated documentation files (the "Software"),21* to deal in the Software without restriction, including without limitation22* the rights to use, copy, modify, merge, publish, distribute, sublicense,23* and/or sell copies of the Software, and to permit persons to whom the24* Software is furnished to do so, subject to the following conditions:25*26* The above copyright notice and this permission notice (including the next27* paragraph) shall be included in all copies or substantial portions of the28* Software.29*30* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR31* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,32* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL33* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR34* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,35* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR36* OTHER DEALINGS IN THE SOFTWARE.37*/3839#include <linux/seq_file.h>40#include <linux/slab.h>41#include "drmP.h"4243/***************************************************44* Initialization, etc.45**************************************************/4647/**48* Proc file list.49*/50static struct drm_info_list drm_proc_list[] = {51{"name", drm_name_info, 0},52{"vm", drm_vm_info, 0},53{"clients", drm_clients_info, 0},54{"queues", drm_queues_info, 0},55{"bufs", drm_bufs_info, 0},56{"gem_names", drm_gem_name_info, DRIVER_GEM},57#if DRM_DEBUG_CODE58{"vma", drm_vma_info, 0},59#endif60};61#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)6263static int drm_proc_open(struct inode *inode, struct file *file)64{65struct drm_info_node* node = PDE(inode)->data;6667return single_open(file, node->info_ent->show, node);68}6970static const struct file_operations drm_proc_fops = {71.owner = THIS_MODULE,72.open = drm_proc_open,73.read = seq_read,74.llseek = seq_lseek,75.release = single_release,76};777879/**80* Initialize a given set of proc files for a device81*82* \param files The array of files to create83* \param count The number of files given84* \param root DRI proc dir entry.85* \param minor device minor number86* \return Zero on success, non-zero on failure87*88* Create a given set of proc files represented by an array of89* gdm_proc_lists in the given root directory.90*/91int drm_proc_create_files(struct drm_info_list *files, int count,92struct proc_dir_entry *root, struct drm_minor *minor)93{94struct drm_device *dev = minor->dev;95struct proc_dir_entry *ent;96struct drm_info_node *tmp;97char name[64];98int i, ret;99100for (i = 0; i < count; i++) {101u32 features = files[i].driver_features;102103if (features != 0 &&104(dev->driver->driver_features & features) != features)105continue;106107tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);108if (tmp == NULL) {109ret = -1;110goto fail;111}112tmp->minor = minor;113tmp->info_ent = &files[i];114list_add(&tmp->list, &minor->proc_nodes.list);115116ent = proc_create_data(files[i].name, S_IRUGO, root,117&drm_proc_fops, tmp);118if (!ent) {119DRM_ERROR("Cannot create /proc/dri/%s/%s\n",120name, files[i].name);121list_del(&tmp->list);122kfree(tmp);123ret = -1;124goto fail;125}126127}128return 0;129130fail:131for (i = 0; i < count; i++)132remove_proc_entry(drm_proc_list[i].name, minor->proc_root);133return ret;134}135136/**137* Initialize the DRI proc filesystem for a device138*139* \param dev DRM device140* \param minor device minor number141* \param root DRI proc dir entry.142* \param dev_root resulting DRI device proc dir entry.143* \return root entry pointer on success, or NULL on failure.144*145* Create the DRI proc root entry "/proc/dri", the device proc root entry146* "/proc/dri/%minor%/", and each entry in proc_list as147* "/proc/dri/%minor%/%name%".148*/149int drm_proc_init(struct drm_minor *minor, int minor_id,150struct proc_dir_entry *root)151{152char name[64];153int ret;154155INIT_LIST_HEAD(&minor->proc_nodes.list);156sprintf(name, "%d", minor_id);157minor->proc_root = proc_mkdir(name, root);158if (!minor->proc_root) {159DRM_ERROR("Cannot create /proc/dri/%s\n", name);160return -1;161}162163ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,164minor->proc_root, minor);165if (ret) {166remove_proc_entry(name, root);167minor->proc_root = NULL;168DRM_ERROR("Failed to create core drm proc files\n");169return ret;170}171172return 0;173}174175int drm_proc_remove_files(struct drm_info_list *files, int count,176struct drm_minor *minor)177{178struct list_head *pos, *q;179struct drm_info_node *tmp;180int i;181182for (i = 0; i < count; i++) {183list_for_each_safe(pos, q, &minor->proc_nodes.list) {184tmp = list_entry(pos, struct drm_info_node, list);185if (tmp->info_ent == &files[i]) {186remove_proc_entry(files[i].name,187minor->proc_root);188list_del(pos);189kfree(tmp);190}191}192}193return 0;194}195196/**197* Cleanup the proc filesystem resources.198*199* \param minor device minor number.200* \param root DRI proc dir entry.201* \param dev_root DRI device proc dir entry.202* \return always zero.203*204* Remove all proc entries created by proc_init().205*/206int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)207{208char name[64];209210if (!root || !minor->proc_root)211return 0;212213drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);214215sprintf(name, "%d", minor->index);216remove_proc_entry(name, root);217218return 0;219}220221222223