xref: /linux/drivers/crypto/intel/qat/qat_common/adf_cfg.c (revision d237230728c567297f2f98b425d63156ab2ed17f)
1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2 /* Copyright(c) 2014 - 2020 Intel Corporation */
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 
11 static DEFINE_MUTEX(qat_cfg_read_lock);
12 
13 static 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 
21 static 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 
36 static 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 
43 static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
44 {
45 	mutex_unlock(&qat_cfg_read_lock);
46 }
47 
48 static 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 
55 DEFINE_SEQ_ATTRIBUTE(qat_dev_cfg);
56 
57 /**
58  * adf_cfg_dev_add() - Create an acceleration device configuration table.
59  * @accel_dev:  Pointer to acceleration device.
60  *
61  * Function creates a configuration table for the given acceleration device.
62  * The table stores device specific config values.
63  * To be used by QAT device specific drivers.
64  *
65  * Return: 0 on success, error code otherwise.
66  */
67 int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
68 {
69 	struct adf_cfg_device_data *dev_cfg_data;
70 
71 	dev_cfg_data = kzalloc_obj(*dev_cfg_data);
72 	if (!dev_cfg_data)
73 		return -ENOMEM;
74 	INIT_LIST_HEAD(&dev_cfg_data->sec_list);
75 	init_rwsem(&dev_cfg_data->lock);
76 	accel_dev->cfg = dev_cfg_data;
77 	return 0;
78 }
79 EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
80 
81 void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev)
82 {
83 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
84 
85 	dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400,
86 						  accel_dev->debugfs_dir,
87 						  dev_cfg_data,
88 						  &qat_dev_cfg_fops);
89 }
90 
91 void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev)
92 {
93 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
94 
95 	if (!dev_cfg_data)
96 		return;
97 
98 	debugfs_remove(dev_cfg_data->debug);
99 	dev_cfg_data->debug = NULL;
100 }
101 
102 static void adf_cfg_section_del_all(struct list_head *head);
103 static void adf_cfg_section_del_all_except(struct list_head *head,
104 					   const char *section_name);
105 
106 void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev,
107 			    const char *section_name)
108 {
109 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
110 
111 	down_write(&dev_cfg_data->lock);
112 	adf_cfg_section_del_all_except(&dev_cfg_data->sec_list, section_name);
113 	up_write(&dev_cfg_data->lock);
114 	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
115 }
116 
117 /**
118  * adf_cfg_dev_remove() - Clears acceleration device configuration table.
119  * @accel_dev:  Pointer to acceleration device.
120  *
121  * Function removes configuration table from the given acceleration device
122  * and frees all allocated memory.
123  * To be used by QAT device specific drivers.
124  *
125  * Return: void
126  */
127 void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
128 {
129 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
130 
131 	if (!dev_cfg_data)
132 		return;
133 
134 	down_write(&dev_cfg_data->lock);
135 	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
136 	up_write(&dev_cfg_data->lock);
137 	kfree(dev_cfg_data);
138 	accel_dev->cfg = NULL;
139 }
140 EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
141 
142 static 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 
148 static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
149 {
150 	struct list_head *head = &sec->param_head;
151 	struct list_head *list_ptr, *tmp;
152 
153 	list_for_each_prev_safe(list_ptr, tmp, head) {
154 		struct adf_cfg_key_val *ptr =
155 			list_entry(list_ptr, struct adf_cfg_key_val, list);
156 
157 		if (strncmp(ptr->key, key, sizeof(ptr->key)))
158 			continue;
159 
160 		list_del(list_ptr);
161 		kfree(ptr);
162 		break;
163 	}
164 }
165 
166 static void adf_cfg_keyval_del_all(struct list_head *head)
167 {
168 	struct list_head *list_ptr, *tmp;
169 
170 	list_for_each_prev_safe(list_ptr, tmp, head) {
171 		struct adf_cfg_key_val *ptr =
172 			list_entry(list_ptr, struct adf_cfg_key_val, list);
173 		list_del(list_ptr);
174 		kfree(ptr);
175 	}
176 }
177 
178 static void adf_cfg_section_del_all(struct list_head *head)
179 {
180 	struct adf_cfg_section *ptr;
181 	struct list_head *list, *tmp;
182 
183 	list_for_each_prev_safe(list, tmp, head) {
184 		ptr = list_entry(list, struct adf_cfg_section, list);
185 		adf_cfg_keyval_del_all(&ptr->param_head);
186 		list_del(list);
187 		kfree(ptr);
188 	}
189 }
190 
191 static void adf_cfg_section_del_all_except(struct list_head *head,
192 					   const char *section_name)
193 {
194 	struct list_head *list, *tmp;
195 	struct adf_cfg_section *ptr;
196 
197 	list_for_each_prev_safe(list, tmp, head) {
198 		ptr = list_entry(list, struct adf_cfg_section, list);
199 		if (!strcmp(ptr->name, section_name))
200 			continue;
201 		adf_cfg_keyval_del_all(&ptr->param_head);
202 		list_del(list);
203 		kfree(ptr);
204 	}
205 }
206 
207 static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
208 						      const char *key)
209 {
210 	struct list_head *list;
211 
212 	list_for_each(list, &s->param_head) {
213 		struct adf_cfg_key_val *ptr =
214 			list_entry(list, struct adf_cfg_key_val, list);
215 		if (!strcmp(ptr->key, key))
216 			return ptr;
217 	}
218 	return NULL;
219 }
220 
221 static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
222 						const char *sec_name)
223 {
224 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
225 	struct list_head *list;
226 
227 	list_for_each(list, &cfg->sec_list) {
228 		struct adf_cfg_section *ptr =
229 			list_entry(list, struct adf_cfg_section, list);
230 		if (!strcmp(ptr->name, sec_name))
231 			return ptr;
232 	}
233 	return NULL;
234 }
235 
236 static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
237 			       const char *sec_name,
238 			       const char *key_name,
239 			       char *val)
240 {
241 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
242 	struct adf_cfg_key_val *keyval = NULL;
243 
244 	if (sec)
245 		keyval = adf_cfg_key_value_find(sec, key_name);
246 	if (keyval) {
247 		memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
248 		return 0;
249 	}
250 	return -ENODATA;
251 }
252 
253 /**
254  * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
255  * @accel_dev:  Pointer to acceleration device.
256  * @section_name: Name of the section where the param will be added
257  * @key: The key string
258  * @val: Value pain for the given @key
259  * @type: Type - string, int or address
260  *
261  * Function adds configuration key - value entry in the appropriate section
262  * in the given acceleration device. If the key exists already, the value
263  * is updated.
264  * To be used by QAT device specific drivers.
265  *
266  * Return: 0 on success, error code otherwise.
267  */
268 int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
269 				const char *section_name,
270 				const char *key, const void *val,
271 				enum adf_cfg_val_type type)
272 {
273 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
274 	struct adf_cfg_key_val *key_val;
275 	struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
276 							   section_name);
277 	char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
278 
279 	if (!section)
280 		return -EFAULT;
281 
282 	key_val = kzalloc_obj(*key_val);
283 	if (!key_val)
284 		return -ENOMEM;
285 
286 	INIT_LIST_HEAD(&key_val->list);
287 	strscpy(key_val->key, key, sizeof(key_val->key));
288 
289 	if (type == ADF_DEC) {
290 		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
291 			 "%ld", (*((long *)val)));
292 	} else if (type == ADF_STR) {
293 		strscpy(key_val->val, (char *)val, sizeof(key_val->val));
294 	} else if (type == ADF_HEX) {
295 		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
296 			 "0x%lx", (unsigned long)val);
297 	} else {
298 		dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
299 		kfree(key_val);
300 		return -EINVAL;
301 	}
302 	key_val->type = type;
303 
304 	/* Add the key-value pair as below policy:
305 	 * 1. if the key doesn't exist, add it;
306 	 * 2. if the key already exists with a different value then update it
307 	 *    to the new value (the key is deleted and the newly created
308 	 *    key_val containing the new value is added to the database);
309 	 * 3. if the key exists with the same value, then return without doing
310 	 *    anything (the newly created key_val is freed).
311 	 */
312 	down_write(&cfg->lock);
313 	if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) {
314 		if (strncmp(temp_val, key_val->val, sizeof(temp_val))) {
315 			adf_cfg_keyval_remove(key, section);
316 		} else {
317 			kfree(key_val);
318 			goto out;
319 		}
320 	}
321 
322 	adf_cfg_keyval_add(key_val, section);
323 
324 out:
325 	up_write(&cfg->lock);
326 	return 0;
327 }
328 EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
329 
330 /**
331  * adf_cfg_section_add() - Add config section entry to config table.
332  * @accel_dev:  Pointer to acceleration device.
333  * @name: Name of the section
334  *
335  * Function adds configuration section where key - value entries
336  * will be stored.
337  * To be used by QAT device specific drivers.
338  *
339  * Return: 0 on success, error code otherwise.
340  */
341 int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
342 {
343 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
344 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
345 
346 	if (sec)
347 		return 0;
348 
349 	sec = kzalloc_obj(*sec);
350 	if (!sec)
351 		return -ENOMEM;
352 
353 	strscpy(sec->name, name, sizeof(sec->name));
354 	INIT_LIST_HEAD(&sec->param_head);
355 	down_write(&cfg->lock);
356 	list_add_tail(&sec->list, &cfg->sec_list);
357 	up_write(&cfg->lock);
358 	return 0;
359 }
360 EXPORT_SYMBOL_GPL(adf_cfg_section_add);
361 
362 int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
363 			    const char *section, const char *name,
364 			    char *value)
365 {
366 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
367 	int ret;
368 
369 	down_read(&cfg->lock);
370 	ret = adf_cfg_key_val_get(accel_dev, section, name, value);
371 	up_read(&cfg->lock);
372 	return ret;
373 }
374 EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);
375