summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imagination/pvr_params.c
blob: b91759f362c571c59d2a61af33e1e0634fb9ef9f (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
138
139
140
141
142
143
144
145
146
147
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/* Copyright (c) 2023 Imagination Technologies Ltd. */

#include "pvr_params.h"

#include <linux/cache.h>
#include <linux/moduleparam.h>

static struct pvr_device_params pvr_device_param_defaults __read_mostly = {
#define X(type_, name_, value_, desc_, ...) .name_ = (value_),
	PVR_DEVICE_PARAMS
#undef X
};

#define PVR_DEVICE_PARAM_NAMED(name_, type_, desc_) \
	module_param_named(name_, pvr_device_param_defaults.name_, type_, \
			   0400);                                         \
	MODULE_PARM_DESC(name_, desc_);

/*
 * This list of defines must contain every type specified in "pvr_params.h" as
 * ``PVR_PARAM_TYPE_*_C``.
 */
#define PVR_PARAM_TYPE_X32_MODPARAM uint

#define X(type_, name_, value_, desc_, ...) \
	PVR_DEVICE_PARAM_NAMED(name_, PVR_PARAM_TYPE_##type_##_MODPARAM, desc_);
PVR_DEVICE_PARAMS
#undef X

int
pvr_device_params_init(struct pvr_device_params *params)
{
	/*
	 * If heap-allocated parameters are added in the future (e.g.
	 * modparam's charp type), they must be handled specially here (via
	 * kstrdup() in the case of charp). Since that's not necessary yet,
	 * a straight copy will do for now. This change will also require a
	 * pvr_device_params_fini() function to free any heap-allocated copies.
	 */

	*params = pvr_device_param_defaults;

	return 0;
}

#if defined(CONFIG_DEBUG_FS)
#include "pvr_device.h"

#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/stddef.h>

/*
 * This list of defines must contain every type specified in "pvr_params.h" as
 * ``PVR_PARAM_TYPE_*_C``.
 */
#define PVR_PARAM_TYPE_X32_FMT "0x%08llx"

#define X_SET(name_, mode_) X_SET_##mode_(name_)
#define X_SET_DEF(name_, update_, mode_) X_SET_DEF_##mode_(name_, update_)

#define X_SET_RO(name_) NULL
#define X_SET_RW(name_) __pvr_device_param_##name_##set

#define X_SET_DEF_RO(name_, update_)
#define X_SET_DEF_RW(name_, update_)                                    \
	static int                                                      \
	X_SET_RW(name_)(void *data, u64 val)                            \
	{                                                               \
		struct pvr_device *pvr_dev = data;                      \
		/* This is not just (update_) to suppress -Waddress. */ \
		if ((void *)(update_) != NULL)                          \
			(update_)(pvr_dev, pvr_dev->params.name_, val); \
		pvr_dev->params.name_ = val;                            \
		return 0;                                               \
	}

#define X(type_, name_, value_, desc_, mode_, update_)                     \
	static int                                                         \
	__pvr_device_param_##name_##_get(void *data, u64 *val)             \
	{                                                                  \
		struct pvr_device *pvr_dev = data;                         \
		*val = pvr_dev->params.name_;                              \
		return 0;                                                  \
	}                                                                  \
	X_SET_DEF(name_, update_, mode_)                                   \
	static int                                                         \
	__pvr_device_param_##name_##_open(struct inode *inode,             \
					  struct file *file)               \
	{                                                                  \
		__simple_attr_check_format(PVR_PARAM_TYPE_##type_##_FMT,   \
					   0ull);                          \
		return simple_attr_open(inode, file,                       \
					__pvr_device_param_##name_##_get,  \
					X_SET(name_, mode_),               \
					PVR_PARAM_TYPE_##type_##_FMT);     \
	}
PVR_DEVICE_PARAMS
#undef X

#undef X_SET
#undef X_SET_RO
#undef X_SET_RW
#undef X_SET_DEF
#undef X_SET_DEF_RO
#undef X_SET_DEF_RW

static struct {
#define X(type_, name_, value_, desc_, mode_, update_) \
	const struct file_operations name_;
	PVR_DEVICE_PARAMS
#undef X
} pvr_device_param_debugfs_fops = {
#define X(type_, name_, value_, desc_, mode_, update_)     \
	.name_ = {                                         \
		.owner = THIS_MODULE,                      \
		.open = __pvr_device_param_##name_##_open, \
		.release = simple_attr_release,            \
		.read = simple_attr_read,                  \
		.write = simple_attr_write,                \
		.llseek = generic_file_llseek,             \
	},
	PVR_DEVICE_PARAMS
#undef X
};

void
pvr_params_debugfs_init(struct pvr_device *pvr_dev, struct dentry *dir)
{
#define X_MODE(mode_) X_MODE_##mode_
#define X_MODE_RO 0400
#define X_MODE_RW 0600

#define X(type_, name_, value_, desc_, mode_, update_)             \
	debugfs_create_file(#name_, X_MODE(mode_), dir, pvr_dev,   \
			    &pvr_device_param_debugfs_fops.name_);
	PVR_DEVICE_PARAMS
#undef X

#undef X_MODE
#undef X_MODE_RO
#undef X_MODE_RW
}
#endif