1
2
3#include <linux/mutex.h>
4#include <linux/slab.h>
5#include <linux/list.h>
6#include <linux/seq_file.h>
7#include "adf_accel_devices.h"
8#include "adf_cfg.h"
9#include "adf_common_drv.h"
10
11static DEFINE_MUTEX(qat_cfg_read_lock);
12
13static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
14{
15 struct adf_cfg_device_data *dev_cfg = sfile->private;
16
17 mutex_lock(&qat_cfg_read_lock);
18 return seq_list_start(&dev_cfg->sec_list, *pos);
19}
20
21static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
22{
23 struct list_head *list;
24 struct adf_cfg_section *sec =
25 list_entry(v, struct adf_cfg_section, list);
26
27 seq_printf(sfile, "[%s]\n", sec->name);
28 list_for_each(list, &sec->param_head) {
29 struct adf_cfg_key_val *ptr =
30 list_entry(list, struct adf_cfg_key_val, list);
31 seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
32 }
33 return 0;
34}
35
36static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
37{
38 struct adf_cfg_device_data *dev_cfg = sfile->private;
39
40 return seq_list_next(v, &dev_cfg->sec_list, pos);
41}
42
43static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
44{
45 mutex_unlock(&qat_cfg_read_lock);
46}
47
48static const struct seq_operations qat_dev_cfg_sops = {
49 .start = qat_dev_cfg_start,
50 .next = qat_dev_cfg_next,
51 .stop = qat_dev_cfg_stop,
52 .show = qat_dev_cfg_show
53};
54
55static int qat_dev_cfg_open(struct inode *inode, struct file *file)
56{
57 int ret = seq_open(file, &qat_dev_cfg_sops);
58
59 if (!ret) {
60 struct seq_file *seq_f = file->private_data;
61
62 seq_f->private = inode->i_private;
63 }
64 return ret;
65}
66
67static const struct file_operations qat_dev_cfg_fops = {
68 .open = qat_dev_cfg_open,
69 .read = seq_read,
70 .llseek = seq_lseek,
71 .release = seq_release
72};
73
74
75
76
77
78
79
80
81
82
83
84int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
85{
86 struct adf_cfg_device_data *dev_cfg_data;
87
88 dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
89 if (!dev_cfg_data)
90 return -ENOMEM;
91 INIT_LIST_HEAD(&dev_cfg_data->sec_list);
92 init_rwsem(&dev_cfg_data->lock);
93 accel_dev->cfg = dev_cfg_data;
94
95
96 dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
97 accel_dev->debugfs_dir,
98 dev_cfg_data,
99 &qat_dev_cfg_fops);
100 return 0;
101}
102EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
103
104static void adf_cfg_section_del_all(struct list_head *head);
105
106void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
107{
108 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
109
110 down_write(&dev_cfg_data->lock);
111 adf_cfg_section_del_all(&dev_cfg_data->sec_list);
112 up_write(&dev_cfg_data->lock);
113 clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
114}
115
116
117
118
119
120
121
122
123
124
125
126void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
127{
128 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
129
130 if (!dev_cfg_data)
131 return;
132
133 down_write(&dev_cfg_data->lock);
134 adf_cfg_section_del_all(&dev_cfg_data->sec_list);
135 up_write(&dev_cfg_data->lock);
136 debugfs_remove(dev_cfg_data->debug);
137 kfree(dev_cfg_data);
138 accel_dev->cfg = NULL;
139}
140EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
141
142static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
143 struct adf_cfg_section *sec)
144{
145 list_add_tail(&new->list, &sec->param_head);
146}
147
148static void adf_cfg_keyval_del_all(struct list_head *head)
149{
150 struct list_head *list_ptr, *tmp;
151
152 list_for_each_prev_safe(list_ptr, tmp, head) {
153 struct adf_cfg_key_val *ptr =
154 list_entry(list_ptr, struct adf_cfg_key_val, list);
155 list_del(list_ptr);
156 kfree(ptr);
157 }
158}
159
160static void adf_cfg_section_del_all(struct list_head *head)
161{
162 struct adf_cfg_section *ptr;
163 struct list_head *list, *tmp;
164
165 list_for_each_prev_safe(list, tmp, head) {
166 ptr = list_entry(list, struct adf_cfg_section, list);
167 adf_cfg_keyval_del_all(&ptr->param_head);
168 list_del(list);
169 kfree(ptr);
170 }
171}
172
173static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
174 const char *key)
175{
176 struct list_head *list;
177
178 list_for_each(list, &s->param_head) {
179 struct adf_cfg_key_val *ptr =
180 list_entry(list, struct adf_cfg_key_val, list);
181 if (!strcmp(ptr->key, key))
182 return ptr;
183 }
184 return NULL;
185}
186
187static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
188 const char *sec_name)
189{
190 struct adf_cfg_device_data *cfg = accel_dev->cfg;
191 struct list_head *list;
192
193 list_for_each(list, &cfg->sec_list) {
194 struct adf_cfg_section *ptr =
195 list_entry(list, struct adf_cfg_section, list);
196 if (!strcmp(ptr->name, sec_name))
197 return ptr;
198 }
199 return NULL;
200}
201
202static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
203 const char *sec_name,
204 const char *key_name,
205 char *val)
206{
207 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
208 struct adf_cfg_key_val *keyval = NULL;
209
210 if (sec)
211 keyval = adf_cfg_key_value_find(sec, key_name);
212 if (keyval) {
213 memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
214 return 0;
215 }
216 return -1;
217}
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
234 const char *section_name,
235 const char *key, const void *val,
236 enum adf_cfg_val_type type)
237{
238 struct adf_cfg_device_data *cfg = accel_dev->cfg;
239 struct adf_cfg_key_val *key_val;
240 struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
241 section_name);
242 if (!section)
243 return -EFAULT;
244
245 key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
246 if (!key_val)
247 return -ENOMEM;
248
249 INIT_LIST_HEAD(&key_val->list);
250 strlcpy(key_val->key, key, sizeof(key_val->key));
251
252 if (type == ADF_DEC) {
253 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
254 "%ld", (*((long *)val)));
255 } else if (type == ADF_STR) {
256 strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
257 } else if (type == ADF_HEX) {
258 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
259 "0x%lx", (unsigned long)val);
260 } else {
261 dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
262 kfree(key_val);
263 return -1;
264 }
265 key_val->type = type;
266 down_write(&cfg->lock);
267 adf_cfg_keyval_add(key_val, section);
268 up_write(&cfg->lock);
269 return 0;
270}
271EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
272
273
274
275
276
277
278
279
280
281
282
283
284int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
285{
286 struct adf_cfg_device_data *cfg = accel_dev->cfg;
287 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
288
289 if (sec)
290 return 0;
291
292 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
293 if (!sec)
294 return -ENOMEM;
295
296 strlcpy(sec->name, name, sizeof(sec->name));
297 INIT_LIST_HEAD(&sec->param_head);
298 down_write(&cfg->lock);
299 list_add_tail(&sec->list, &cfg->sec_list);
300 up_write(&cfg->lock);
301 return 0;
302}
303EXPORT_SYMBOL_GPL(adf_cfg_section_add);
304
305int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
306 const char *section, const char *name,
307 char *value)
308{
309 struct adf_cfg_device_data *cfg = accel_dev->cfg;
310 int ret;
311
312 down_read(&cfg->lock);
313 ret = adf_cfg_key_val_get(accel_dev, section, name, value);
314 up_read(&cfg->lock);
315 return ret;
316}
317