1a4b16dadSTom Zanussi // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2a4b16dadSTom Zanussi /* Copyright(c) 2014 - 2020 Intel Corporation */
3a4b16dadSTom Zanussi #include <linux/mutex.h>
4a4b16dadSTom Zanussi #include <linux/slab.h>
5a4b16dadSTom Zanussi #include <linux/list.h>
6a4b16dadSTom Zanussi #include <linux/seq_file.h>
7a4b16dadSTom Zanussi #include "adf_accel_devices.h"
8a4b16dadSTom Zanussi #include "adf_cfg.h"
9a4b16dadSTom Zanussi #include "adf_common_drv.h"
10a4b16dadSTom Zanussi 
11a4b16dadSTom Zanussi static DEFINE_MUTEX(qat_cfg_read_lock);
12a4b16dadSTom Zanussi 
qat_dev_cfg_start(struct seq_file * sfile,loff_t * pos)13a4b16dadSTom Zanussi static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
14a4b16dadSTom Zanussi {
15a4b16dadSTom Zanussi 	struct adf_cfg_device_data *dev_cfg = sfile->private;
16a4b16dadSTom Zanussi 
17a4b16dadSTom Zanussi 	mutex_lock(&qat_cfg_read_lock);
18a4b16dadSTom Zanussi 	return seq_list_start(&dev_cfg->sec_list, *pos);
19a4b16dadSTom Zanussi }
20a4b16dadSTom Zanussi 
qat_dev_cfg_show(struct seq_file * sfile,void * v)21a4b16dadSTom Zanussi static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
22a4b16dadSTom Zanussi {
23a4b16dadSTom Zanussi 	struct list_head *list;
24a4b16dadSTom Zanussi 	struct adf_cfg_section *sec =
25a4b16dadSTom Zanussi 				list_entry(v, struct adf_cfg_section, list);
26a4b16dadSTom Zanussi 
27a4b16dadSTom Zanussi 	seq_printf(sfile, "[%s]\n", sec->name);
28a4b16dadSTom Zanussi 	list_for_each(list, &sec->param_head) {
29a4b16dadSTom Zanussi 		struct adf_cfg_key_val *ptr =
30a4b16dadSTom Zanussi 			list_entry(list, struct adf_cfg_key_val, list);
31a4b16dadSTom Zanussi 		seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
32a4b16dadSTom Zanussi 	}
33a4b16dadSTom Zanussi 	return 0;
34a4b16dadSTom Zanussi }
35a4b16dadSTom Zanussi 
qat_dev_cfg_next(struct seq_file * sfile,void * v,loff_t * pos)36a4b16dadSTom Zanussi static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
37a4b16dadSTom Zanussi {
38a4b16dadSTom Zanussi 	struct adf_cfg_device_data *dev_cfg = sfile->private;
39a4b16dadSTom Zanussi 
40a4b16dadSTom Zanussi 	return seq_list_next(v, &dev_cfg->sec_list, pos);
41a4b16dadSTom Zanussi }
42a4b16dadSTom Zanussi 
qat_dev_cfg_stop(struct seq_file * sfile,void * v)43a4b16dadSTom Zanussi static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
44a4b16dadSTom Zanussi {
45a4b16dadSTom Zanussi 	mutex_unlock(&qat_cfg_read_lock);
46a4b16dadSTom Zanussi }
47a4b16dadSTom Zanussi 
48a4b16dadSTom Zanussi static const struct seq_operations qat_dev_cfg_sops = {
49a4b16dadSTom Zanussi 	.start = qat_dev_cfg_start,
50a4b16dadSTom Zanussi 	.next = qat_dev_cfg_next,
51a4b16dadSTom Zanussi 	.stop = qat_dev_cfg_stop,
52a4b16dadSTom Zanussi 	.show = qat_dev_cfg_show
53a4b16dadSTom Zanussi };
54a4b16dadSTom Zanussi 
55a4b16dadSTom Zanussi DEFINE_SEQ_ATTRIBUTE(qat_dev_cfg);
56a4b16dadSTom Zanussi 
57a4b16dadSTom Zanussi /**
58a4b16dadSTom Zanussi  * adf_cfg_dev_add() - Create an acceleration device configuration table.
59a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
60a4b16dadSTom Zanussi  *
61a4b16dadSTom Zanussi  * Function creates a configuration table for the given acceleration device.
62a4b16dadSTom Zanussi  * The table stores device specific config values.
63a4b16dadSTom Zanussi  * To be used by QAT device specific drivers.
64a4b16dadSTom Zanussi  *
65a4b16dadSTom Zanussi  * Return: 0 on success, error code otherwise.
66a4b16dadSTom Zanussi  */
adf_cfg_dev_add(struct adf_accel_dev * accel_dev)67a4b16dadSTom Zanussi int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
68a4b16dadSTom Zanussi {
69a4b16dadSTom Zanussi 	struct adf_cfg_device_data *dev_cfg_data;
70a4b16dadSTom Zanussi 
71a4b16dadSTom Zanussi 	dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
72a4b16dadSTom Zanussi 	if (!dev_cfg_data)
73a4b16dadSTom Zanussi 		return -ENOMEM;
74a4b16dadSTom Zanussi 	INIT_LIST_HEAD(&dev_cfg_data->sec_list);
75a4b16dadSTom Zanussi 	init_rwsem(&dev_cfg_data->lock);
76a4b16dadSTom Zanussi 	accel_dev->cfg = dev_cfg_data;
77a4b16dadSTom Zanussi 	return 0;
78a4b16dadSTom Zanussi }
79a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
80a4b16dadSTom Zanussi 
adf_cfg_dev_dbgfs_add(struct adf_accel_dev * accel_dev)819260db66SDamian Muszynski void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev)
829260db66SDamian Muszynski {
839260db66SDamian Muszynski 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
849260db66SDamian Muszynski 
859260db66SDamian Muszynski 	dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400,
869260db66SDamian Muszynski 						  accel_dev->debugfs_dir,
879260db66SDamian Muszynski 						  dev_cfg_data,
889260db66SDamian Muszynski 						  &qat_dev_cfg_fops);
899260db66SDamian Muszynski }
909260db66SDamian Muszynski 
adf_cfg_dev_dbgfs_rm(struct adf_accel_dev * accel_dev)919260db66SDamian Muszynski void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev)
929260db66SDamian Muszynski {
939260db66SDamian Muszynski 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
949260db66SDamian Muszynski 
959260db66SDamian Muszynski 	if (!dev_cfg_data)
969260db66SDamian Muszynski 		return;
979260db66SDamian Muszynski 
989260db66SDamian Muszynski 	debugfs_remove(dev_cfg_data->debug);
999260db66SDamian Muszynski 	dev_cfg_data->debug = NULL;
1009260db66SDamian Muszynski }
1019260db66SDamian Muszynski 
102a4b16dadSTom Zanussi static void adf_cfg_section_del_all(struct list_head *head);
103*4e190a57SAdam Guerin static void adf_cfg_section_del_all_except(struct list_head *head,
104*4e190a57SAdam Guerin 					   const char *section_name);
105a4b16dadSTom Zanussi 
adf_cfg_del_all(struct adf_accel_dev * accel_dev)106a4b16dadSTom Zanussi void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
107a4b16dadSTom Zanussi {
108a4b16dadSTom Zanussi 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
109a4b16dadSTom Zanussi 
110a4b16dadSTom Zanussi 	down_write(&dev_cfg_data->lock);
111a4b16dadSTom Zanussi 	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
112a4b16dadSTom Zanussi 	up_write(&dev_cfg_data->lock);
113a4b16dadSTom Zanussi 	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
114a4b16dadSTom Zanussi }
115a4b16dadSTom Zanussi 
adf_cfg_del_all_except(struct adf_accel_dev * accel_dev,const char * section_name)116*4e190a57SAdam Guerin void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev,
117*4e190a57SAdam Guerin 			    const char *section_name)
118*4e190a57SAdam Guerin {
119*4e190a57SAdam Guerin 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
120*4e190a57SAdam Guerin 
121*4e190a57SAdam Guerin 	down_write(&dev_cfg_data->lock);
122*4e190a57SAdam Guerin 	adf_cfg_section_del_all_except(&dev_cfg_data->sec_list, section_name);
123*4e190a57SAdam Guerin 	up_write(&dev_cfg_data->lock);
124*4e190a57SAdam Guerin 	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
125*4e190a57SAdam Guerin }
126*4e190a57SAdam Guerin 
127a4b16dadSTom Zanussi /**
128a4b16dadSTom Zanussi  * adf_cfg_dev_remove() - Clears acceleration device configuration table.
129a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
130a4b16dadSTom Zanussi  *
131a4b16dadSTom Zanussi  * Function removes configuration table from the given acceleration device
132a4b16dadSTom Zanussi  * and frees all allocated memory.
133a4b16dadSTom Zanussi  * To be used by QAT device specific drivers.
134a4b16dadSTom Zanussi  *
135a4b16dadSTom Zanussi  * Return: void
136a4b16dadSTom Zanussi  */
adf_cfg_dev_remove(struct adf_accel_dev * accel_dev)137a4b16dadSTom Zanussi void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
138a4b16dadSTom Zanussi {
139a4b16dadSTom Zanussi 	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
140a4b16dadSTom Zanussi 
141a4b16dadSTom Zanussi 	if (!dev_cfg_data)
142a4b16dadSTom Zanussi 		return;
143a4b16dadSTom Zanussi 
144a4b16dadSTom Zanussi 	down_write(&dev_cfg_data->lock);
145a4b16dadSTom Zanussi 	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
146a4b16dadSTom Zanussi 	up_write(&dev_cfg_data->lock);
147a4b16dadSTom Zanussi 	kfree(dev_cfg_data);
148a4b16dadSTom Zanussi 	accel_dev->cfg = NULL;
149a4b16dadSTom Zanussi }
150a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
151a4b16dadSTom Zanussi 
adf_cfg_keyval_add(struct adf_cfg_key_val * new,struct adf_cfg_section * sec)152a4b16dadSTom Zanussi static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
153a4b16dadSTom Zanussi 			       struct adf_cfg_section *sec)
154a4b16dadSTom Zanussi {
155a4b16dadSTom Zanussi 	list_add_tail(&new->list, &sec->param_head);
156a4b16dadSTom Zanussi }
157a4b16dadSTom Zanussi 
adf_cfg_keyval_remove(const char * key,struct adf_cfg_section * sec)158a4b16dadSTom Zanussi static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
159a4b16dadSTom Zanussi {
160a4b16dadSTom Zanussi 	struct list_head *head = &sec->param_head;
161a4b16dadSTom Zanussi 	struct list_head *list_ptr, *tmp;
162a4b16dadSTom Zanussi 
163a4b16dadSTom Zanussi 	list_for_each_prev_safe(list_ptr, tmp, head) {
164a4b16dadSTom Zanussi 		struct adf_cfg_key_val *ptr =
165a4b16dadSTom Zanussi 			list_entry(list_ptr, struct adf_cfg_key_val, list);
166a4b16dadSTom Zanussi 
167a4b16dadSTom Zanussi 		if (strncmp(ptr->key, key, sizeof(ptr->key)))
168a4b16dadSTom Zanussi 			continue;
169a4b16dadSTom Zanussi 
170a4b16dadSTom Zanussi 		list_del(list_ptr);
171a4b16dadSTom Zanussi 		kfree(ptr);
172a4b16dadSTom Zanussi 		break;
173a4b16dadSTom Zanussi 	}
174a4b16dadSTom Zanussi }
175a4b16dadSTom Zanussi 
adf_cfg_keyval_del_all(struct list_head * head)176a4b16dadSTom Zanussi static void adf_cfg_keyval_del_all(struct list_head *head)
177a4b16dadSTom Zanussi {
178a4b16dadSTom Zanussi 	struct list_head *list_ptr, *tmp;
179a4b16dadSTom Zanussi 
180a4b16dadSTom Zanussi 	list_for_each_prev_safe(list_ptr, tmp, head) {
181a4b16dadSTom Zanussi 		struct adf_cfg_key_val *ptr =
182a4b16dadSTom Zanussi 			list_entry(list_ptr, struct adf_cfg_key_val, list);
183a4b16dadSTom Zanussi 		list_del(list_ptr);
184a4b16dadSTom Zanussi 		kfree(ptr);
185a4b16dadSTom Zanussi 	}
186a4b16dadSTom Zanussi }
187a4b16dadSTom Zanussi 
adf_cfg_section_del_all(struct list_head * head)188a4b16dadSTom Zanussi static void adf_cfg_section_del_all(struct list_head *head)
189a4b16dadSTom Zanussi {
190a4b16dadSTom Zanussi 	struct adf_cfg_section *ptr;
191a4b16dadSTom Zanussi 	struct list_head *list, *tmp;
192a4b16dadSTom Zanussi 
193a4b16dadSTom Zanussi 	list_for_each_prev_safe(list, tmp, head) {
194a4b16dadSTom Zanussi 		ptr = list_entry(list, struct adf_cfg_section, list);
195a4b16dadSTom Zanussi 		adf_cfg_keyval_del_all(&ptr->param_head);
196a4b16dadSTom Zanussi 		list_del(list);
197a4b16dadSTom Zanussi 		kfree(ptr);
198a4b16dadSTom Zanussi 	}
199a4b16dadSTom Zanussi }
200a4b16dadSTom Zanussi 
adf_cfg_section_del_all_except(struct list_head * head,const char * section_name)201*4e190a57SAdam Guerin static void adf_cfg_section_del_all_except(struct list_head *head,
202*4e190a57SAdam Guerin 					   const char *section_name)
203*4e190a57SAdam Guerin {
204*4e190a57SAdam Guerin 	struct list_head *list, *tmp;
205*4e190a57SAdam Guerin 	struct adf_cfg_section *ptr;
206*4e190a57SAdam Guerin 
207*4e190a57SAdam Guerin 	list_for_each_prev_safe(list, tmp, head) {
208*4e190a57SAdam Guerin 		ptr = list_entry(list, struct adf_cfg_section, list);
209*4e190a57SAdam Guerin 		if (!strcmp(ptr->name, section_name))
210*4e190a57SAdam Guerin 			continue;
211*4e190a57SAdam Guerin 		adf_cfg_keyval_del_all(&ptr->param_head);
212*4e190a57SAdam Guerin 		list_del(list);
213*4e190a57SAdam Guerin 		kfree(ptr);
214*4e190a57SAdam Guerin 	}
215*4e190a57SAdam Guerin }
216*4e190a57SAdam Guerin 
adf_cfg_key_value_find(struct adf_cfg_section * s,const char * key)217a4b16dadSTom Zanussi static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
218a4b16dadSTom Zanussi 						      const char *key)
219a4b16dadSTom Zanussi {
220a4b16dadSTom Zanussi 	struct list_head *list;
221a4b16dadSTom Zanussi 
222a4b16dadSTom Zanussi 	list_for_each(list, &s->param_head) {
223a4b16dadSTom Zanussi 		struct adf_cfg_key_val *ptr =
224a4b16dadSTom Zanussi 			list_entry(list, struct adf_cfg_key_val, list);
225a4b16dadSTom Zanussi 		if (!strcmp(ptr->key, key))
226a4b16dadSTom Zanussi 			return ptr;
227a4b16dadSTom Zanussi 	}
228a4b16dadSTom Zanussi 	return NULL;
229a4b16dadSTom Zanussi }
230a4b16dadSTom Zanussi 
adf_cfg_sec_find(struct adf_accel_dev * accel_dev,const char * sec_name)231a4b16dadSTom Zanussi static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
232a4b16dadSTom Zanussi 						const char *sec_name)
233a4b16dadSTom Zanussi {
234a4b16dadSTom Zanussi 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
235a4b16dadSTom Zanussi 	struct list_head *list;
236a4b16dadSTom Zanussi 
237a4b16dadSTom Zanussi 	list_for_each(list, &cfg->sec_list) {
238a4b16dadSTom Zanussi 		struct adf_cfg_section *ptr =
239a4b16dadSTom Zanussi 			list_entry(list, struct adf_cfg_section, list);
240a4b16dadSTom Zanussi 		if (!strcmp(ptr->name, sec_name))
241a4b16dadSTom Zanussi 			return ptr;
242a4b16dadSTom Zanussi 	}
243a4b16dadSTom Zanussi 	return NULL;
244a4b16dadSTom Zanussi }
245a4b16dadSTom Zanussi 
adf_cfg_key_val_get(struct adf_accel_dev * accel_dev,const char * sec_name,const char * key_name,char * val)246a4b16dadSTom Zanussi static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
247a4b16dadSTom Zanussi 			       const char *sec_name,
248a4b16dadSTom Zanussi 			       const char *key_name,
249a4b16dadSTom Zanussi 			       char *val)
250a4b16dadSTom Zanussi {
251a4b16dadSTom Zanussi 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
252a4b16dadSTom Zanussi 	struct adf_cfg_key_val *keyval = NULL;
253a4b16dadSTom Zanussi 
254a4b16dadSTom Zanussi 	if (sec)
255a4b16dadSTom Zanussi 		keyval = adf_cfg_key_value_find(sec, key_name);
256a4b16dadSTom Zanussi 	if (keyval) {
257a4b16dadSTom Zanussi 		memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
258a4b16dadSTom Zanussi 		return 0;
259a4b16dadSTom Zanussi 	}
260a4b16dadSTom Zanussi 	return -ENODATA;
261a4b16dadSTom Zanussi }
262a4b16dadSTom Zanussi 
263a4b16dadSTom Zanussi /**
264a4b16dadSTom Zanussi  * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
265a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
266a4b16dadSTom Zanussi  * @section_name: Name of the section where the param will be added
267a4b16dadSTom Zanussi  * @key: The key string
268a4b16dadSTom Zanussi  * @val: Value pain for the given @key
269a4b16dadSTom Zanussi  * @type: Type - string, int or address
270a4b16dadSTom Zanussi  *
271a4b16dadSTom Zanussi  * Function adds configuration key - value entry in the appropriate section
272a4b16dadSTom Zanussi  * in the given acceleration device. If the key exists already, the value
273a4b16dadSTom Zanussi  * is updated.
274a4b16dadSTom Zanussi  * To be used by QAT device specific drivers.
275a4b16dadSTom Zanussi  *
276a4b16dadSTom Zanussi  * Return: 0 on success, error code otherwise.
277a4b16dadSTom Zanussi  */
adf_cfg_add_key_value_param(struct adf_accel_dev * accel_dev,const char * section_name,const char * key,const void * val,enum adf_cfg_val_type type)278a4b16dadSTom Zanussi int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
279a4b16dadSTom Zanussi 				const char *section_name,
280a4b16dadSTom Zanussi 				const char *key, const void *val,
281a4b16dadSTom Zanussi 				enum adf_cfg_val_type type)
282a4b16dadSTom Zanussi {
283a4b16dadSTom Zanussi 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
284a4b16dadSTom Zanussi 	struct adf_cfg_key_val *key_val;
285a4b16dadSTom Zanussi 	struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
286a4b16dadSTom Zanussi 							   section_name);
287a4b16dadSTom Zanussi 	char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
288a4b16dadSTom Zanussi 
289a4b16dadSTom Zanussi 	if (!section)
290a4b16dadSTom Zanussi 		return -EFAULT;
291a4b16dadSTom Zanussi 
292a4b16dadSTom Zanussi 	key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
293a4b16dadSTom Zanussi 	if (!key_val)
294a4b16dadSTom Zanussi 		return -ENOMEM;
295a4b16dadSTom Zanussi 
296a4b16dadSTom Zanussi 	INIT_LIST_HEAD(&key_val->list);
297a4b16dadSTom Zanussi 	strscpy(key_val->key, key, sizeof(key_val->key));
298a4b16dadSTom Zanussi 
299a4b16dadSTom Zanussi 	if (type == ADF_DEC) {
300a4b16dadSTom Zanussi 		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
301a4b16dadSTom Zanussi 			 "%ld", (*((long *)val)));
302a4b16dadSTom Zanussi 	} else if (type == ADF_STR) {
303a4b16dadSTom Zanussi 		strscpy(key_val->val, (char *)val, sizeof(key_val->val));
304a4b16dadSTom Zanussi 	} else if (type == ADF_HEX) {
305a4b16dadSTom Zanussi 		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
306a4b16dadSTom Zanussi 			 "0x%lx", (unsigned long)val);
307a4b16dadSTom Zanussi 	} else {
308a4b16dadSTom Zanussi 		dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
309a4b16dadSTom Zanussi 		kfree(key_val);
310a4b16dadSTom Zanussi 		return -EINVAL;
311a4b16dadSTom Zanussi 	}
312a4b16dadSTom Zanussi 	key_val->type = type;
313a4b16dadSTom Zanussi 
314a4b16dadSTom Zanussi 	/* Add the key-value pair as below policy:
315a4b16dadSTom Zanussi 	 * 1. if the key doesn't exist, add it;
316a4b16dadSTom Zanussi 	 * 2. if the key already exists with a different value then update it
317a4b16dadSTom Zanussi 	 *    to the new value (the key is deleted and the newly created
318a4b16dadSTom Zanussi 	 *    key_val containing the new value is added to the database);
319a4b16dadSTom Zanussi 	 * 3. if the key exists with the same value, then return without doing
320a4b16dadSTom Zanussi 	 *    anything (the newly created key_val is freed).
321a4b16dadSTom Zanussi 	 */
3226424da7dSNivas Varadharajan Mugunthakumar 	down_write(&cfg->lock);
323a4b16dadSTom Zanussi 	if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) {
324a4b16dadSTom Zanussi 		if (strncmp(temp_val, key_val->val, sizeof(temp_val))) {
325a4b16dadSTom Zanussi 			adf_cfg_keyval_remove(key, section);
326a4b16dadSTom Zanussi 		} else {
327a4b16dadSTom Zanussi 			kfree(key_val);
3286424da7dSNivas Varadharajan Mugunthakumar 			goto out;
329a4b16dadSTom Zanussi 		}
330a4b16dadSTom Zanussi 	}
331a4b16dadSTom Zanussi 
332a4b16dadSTom Zanussi 	adf_cfg_keyval_add(key_val, section);
3336424da7dSNivas Varadharajan Mugunthakumar 
3346424da7dSNivas Varadharajan Mugunthakumar out:
335a4b16dadSTom Zanussi 	up_write(&cfg->lock);
336a4b16dadSTom Zanussi 	return 0;
337a4b16dadSTom Zanussi }
338a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
339a4b16dadSTom Zanussi 
340a4b16dadSTom Zanussi /**
341a4b16dadSTom Zanussi  * adf_cfg_section_add() - Add config section entry to config table.
342a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
343a4b16dadSTom Zanussi  * @name: Name of the section
344a4b16dadSTom Zanussi  *
345a4b16dadSTom Zanussi  * Function adds configuration section where key - value entries
346a4b16dadSTom Zanussi  * will be stored.
347a4b16dadSTom Zanussi  * To be used by QAT device specific drivers.
348a4b16dadSTom Zanussi  *
349a4b16dadSTom Zanussi  * Return: 0 on success, error code otherwise.
350a4b16dadSTom Zanussi  */
adf_cfg_section_add(struct adf_accel_dev * accel_dev,const char * name)351a4b16dadSTom Zanussi int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
352a4b16dadSTom Zanussi {
353a4b16dadSTom Zanussi 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
354a4b16dadSTom Zanussi 	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
355a4b16dadSTom Zanussi 
356a4b16dadSTom Zanussi 	if (sec)
357a4b16dadSTom Zanussi 		return 0;
358a4b16dadSTom Zanussi 
359a4b16dadSTom Zanussi 	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
360a4b16dadSTom Zanussi 	if (!sec)
361a4b16dadSTom Zanussi 		return -ENOMEM;
362a4b16dadSTom Zanussi 
363a4b16dadSTom Zanussi 	strscpy(sec->name, name, sizeof(sec->name));
364a4b16dadSTom Zanussi 	INIT_LIST_HEAD(&sec->param_head);
365a4b16dadSTom Zanussi 	down_write(&cfg->lock);
366a4b16dadSTom Zanussi 	list_add_tail(&sec->list, &cfg->sec_list);
367a4b16dadSTom Zanussi 	up_write(&cfg->lock);
368a4b16dadSTom Zanussi 	return 0;
369a4b16dadSTom Zanussi }
370a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_cfg_section_add);
371a4b16dadSTom Zanussi 
adf_cfg_get_param_value(struct adf_accel_dev * accel_dev,const char * section,const char * name,char * value)372a4b16dadSTom Zanussi int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
373a4b16dadSTom Zanussi 			    const char *section, const char *name,
374a4b16dadSTom Zanussi 			    char *value)
375a4b16dadSTom Zanussi {
376a4b16dadSTom Zanussi 	struct adf_cfg_device_data *cfg = accel_dev->cfg;
377a4b16dadSTom Zanussi 	int ret;
378a4b16dadSTom Zanussi 
379a4b16dadSTom Zanussi 	down_read(&cfg->lock);
380a4b16dadSTom Zanussi 	ret = adf_cfg_key_val_get(accel_dev, section, name, value);
381a4b16dadSTom Zanussi 	up_read(&cfg->lock);
382a4b16dadSTom Zanussi 	return ret;
383a4b16dadSTom Zanussi }
384a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);
385