aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c
blob: 62c7fba8791ee4d6ed2cbac15f5948f872ebaf4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
 * Copyright (C) 2011 ARM Limited. All rights reserved.
 * 
 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
 * 
 * A copy of the licence is included with the program, and can also be obtained from Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


/**
 * @file mali_kernel_sysfs.c
 * Implementation of some sysfs data exports
 */
#include <linux/fs.h>       /* file system operations */
#include <linux/device.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>

/* the mali kernel subsystem types */
#include "mali_kernel_subsystem.h"

#include "mali_kernel_linux.h"
#include "mali_kernel_sysfs.h"

#include "mali_kernel_license.h"

#if MALI_LICENSE_IS_GPL
static struct dentry *mali_debugfs_dir;
#endif


#if MALI_STATE_TRACKING
static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
{
	u32 len = 0;
	u32 size;
	char *buf;

	size = seq_get_buf(seq_file, &buf);

	if(!size)
	{
			return -ENOMEM;
	}

	/* Create the internal state dump. */
	len  = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
	len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);

	len += _mali_kernel_core_dump_state(buf + len, size - len);

	seq_commit(seq_file, len);

	return 0;
}

static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
{
	return single_open(file, mali_seq_internal_state_show, NULL);
}

static const struct file_operations mali_seq_internal_state_fops = {
	.owner = THIS_MODULE,
	.open = mali_seq_internal_state_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};
#endif /* MALI_STATE_TRACKING */

int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
{
	int err = 0;
#if MALI_LICENSE_IS_GPL
	struct device * mdev;

	device->mali_class = class_create(THIS_MODULE, mali_dev_name);
	if (IS_ERR(device->mali_class))
	{
		err = PTR_ERR(device->mali_class);
		goto init_class_err;
	}
	mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
	if (IS_ERR(mdev))
	{
		err = PTR_ERR(mdev);
		goto init_mdev_err;
	}

	mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
	if(ERR_PTR(-ENODEV) == mali_debugfs_dir) {
		/* Debugfs not supported. */
		mali_debugfs_dir = NULL;
	} else {
		if(NULL != mali_debugfs_dir)
		{
			/* Debugfs directory created successfully; create files now */
#if MALI_STATE_TRACKING
			debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
#endif
		}
	}
#endif /* MALI_LICENSE_IS_GPL */

	/* Success! */
	return 0;

	/* Error handling */
#if MALI_LICENSE_IS_GPL
	if(NULL != mali_debugfs_dir)
	{
		debugfs_remove_recursive(mali_debugfs_dir);
	}
	device_destroy(device->mali_class, dev);
init_mdev_err:
	class_destroy(device->mali_class);
init_class_err:
#endif
	return err;
}

int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
{
#if MALI_LICENSE_IS_GPL
	if(NULL != mali_debugfs_dir)
	{
		debugfs_remove_recursive(mali_debugfs_dir);
	}
	device_destroy(device->mali_class, dev);
	class_destroy(device->mali_class);
#endif

	return 0;
}