xref: /linux/drivers/gpu/drm/imagination/pvr_params.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
2 /* Copyright (c) 2023 Imagination Technologies Ltd. */
3 
4 #include "pvr_params.h"
5 
6 #include <linux/cache.h>
7 #include <linux/moduleparam.h>
8 
9 static struct pvr_device_params pvr_device_param_defaults __read_mostly = {
10 #define X(type_, name_, value_, desc_, ...) .name_ = (value_),
11 	PVR_DEVICE_PARAMS
12 #undef X
13 };
14 
15 #define PVR_DEVICE_PARAM_NAMED(name_, type_, desc_) \
16 	module_param_named(name_, pvr_device_param_defaults.name_, type_, \
17 			   0400);                                         \
18 	MODULE_PARM_DESC(name_, desc_);
19 
20 /*
21  * This list of defines must contain every type specified in "pvr_params.h" as
22  * ``PVR_PARAM_TYPE_*_C``.
23  */
24 #define PVR_PARAM_TYPE_X32_MODPARAM uint
25 
26 #define X(type_, name_, value_, desc_, ...) \
27 	PVR_DEVICE_PARAM_NAMED(name_, PVR_PARAM_TYPE_##type_##_MODPARAM, desc_);
28 PVR_DEVICE_PARAMS
29 #undef X
30 
31 int
pvr_device_params_init(struct pvr_device_params * params)32 pvr_device_params_init(struct pvr_device_params *params)
33 {
34 	/*
35 	 * If heap-allocated parameters are added in the future (e.g.
36 	 * modparam's charp type), they must be handled specially here (via
37 	 * kstrdup() in the case of charp). Since that's not necessary yet,
38 	 * a straight copy will do for now. This change will also require a
39 	 * pvr_device_params_fini() function to free any heap-allocated copies.
40 	 */
41 
42 	*params = pvr_device_param_defaults;
43 
44 	return 0;
45 }
46 
47 #if defined(CONFIG_DEBUG_FS)
48 #include "pvr_device.h"
49 
50 #include <linux/dcache.h>
51 #include <linux/debugfs.h>
52 #include <linux/export.h>
53 #include <linux/fs.h>
54 #include <linux/stddef.h>
55 
56 /*
57  * This list of defines must contain every type specified in "pvr_params.h" as
58  * ``PVR_PARAM_TYPE_*_C``.
59  */
60 #define PVR_PARAM_TYPE_X32_FMT "0x%08llx"
61 
62 #define X_SET(name_, mode_) X_SET_##mode_(name_)
63 #define X_SET_DEF(name_, update_, mode_) X_SET_DEF_##mode_(name_, update_)
64 
65 #define X_SET_RO(name_) NULL
66 #define X_SET_RW(name_) __pvr_device_param_##name_##set
67 
68 #define X_SET_DEF_RO(name_, update_)
69 #define X_SET_DEF_RW(name_, update_)                                    \
70 	static int                                                      \
71 	X_SET_RW(name_)(void *data, u64 val)                            \
72 	{                                                               \
73 		struct pvr_device *pvr_dev = data;                      \
74 		/* This is not just (update_) to suppress -Waddress. */ \
75 		if ((void *)(update_) != NULL)                          \
76 			(update_)(pvr_dev, pvr_dev->params.name_, val); \
77 		pvr_dev->params.name_ = val;                            \
78 		return 0;                                               \
79 	}
80 
81 #define X(type_, name_, value_, desc_, mode_, update_)                     \
82 	static int                                                         \
83 	__pvr_device_param_##name_##_get(void *data, u64 *val)             \
84 	{                                                                  \
85 		struct pvr_device *pvr_dev = data;                         \
86 		*val = pvr_dev->params.name_;                              \
87 		return 0;                                                  \
88 	}                                                                  \
89 	X_SET_DEF(name_, update_, mode_)                                   \
90 	static int                                                         \
91 	__pvr_device_param_##name_##_open(struct inode *inode,             \
92 					  struct file *file)               \
93 	{                                                                  \
94 		__simple_attr_check_format(PVR_PARAM_TYPE_##type_##_FMT,   \
95 					   0ull);                          \
96 		return simple_attr_open(inode, file,                       \
97 					__pvr_device_param_##name_##_get,  \
98 					X_SET(name_, mode_),               \
99 					PVR_PARAM_TYPE_##type_##_FMT);     \
100 	}
101 PVR_DEVICE_PARAMS
102 #undef X
103 
104 #undef X_SET
105 #undef X_SET_RO
106 #undef X_SET_RW
107 #undef X_SET_DEF
108 #undef X_SET_DEF_RO
109 #undef X_SET_DEF_RW
110 
111 static struct {
112 #define X(type_, name_, value_, desc_, mode_, update_) \
113 	const struct file_operations name_;
114 	PVR_DEVICE_PARAMS
115 #undef X
116 } pvr_device_param_debugfs_fops = {
117 #define X(type_, name_, value_, desc_, mode_, update_)     \
118 	.name_ = {                                         \
119 		.owner = THIS_MODULE,                      \
120 		.open = __pvr_device_param_##name_##_open, \
121 		.release = simple_attr_release,            \
122 		.read = simple_attr_read,                  \
123 		.write = simple_attr_write,                \
124 		.llseek = generic_file_llseek,             \
125 	},
126 	PVR_DEVICE_PARAMS
127 #undef X
128 };
129 
130 void
pvr_params_debugfs_init(struct pvr_device * pvr_dev,struct dentry * dir)131 pvr_params_debugfs_init(struct pvr_device *pvr_dev, struct dentry *dir)
132 {
133 #define X_MODE(mode_) X_MODE_##mode_
134 #define X_MODE_RO 0400
135 #define X_MODE_RW 0600
136 
137 #define X(type_, name_, value_, desc_, mode_, update_)             \
138 	debugfs_create_file(#name_, X_MODE(mode_), dir, pvr_dev,   \
139 			    &pvr_device_param_debugfs_fops.name_);
140 	PVR_DEVICE_PARAMS
141 #undef X
142 
143 #undef X_MODE
144 #undef X_MODE_RO
145 #undef X_MODE_RW
146 }
147 #endif
148