File Index
Files and directories
Sign in
FILE

adf_cfg.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/intel/qat/qat_common/adf_cfg.c C
  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
 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
 55DEFINE_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 */
 67int 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(sizeof(*dev_cfg_data), GFP_KERNEL);
 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}
 79EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
 80
 81void 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
 91void 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
102static void adf_cfg_section_del_all(struct list_head *head);
103static void adf_cfg_section_del_all_except(struct list_head *head,
104					   const char *section_name);
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
116void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev,
117			    const char *section_name)
118{
119	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
120
121	down_write(&dev_cfg_data->lock);
122	adf_cfg_section_del_all_except(&dev_cfg_data->sec_list, section_name);
123	up_write(&dev_cfg_data->lock);
124	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
125}
126
127/**
128 * adf_cfg_dev_remove() - Clears acceleration device configuration table.
129 * @accel_dev:  Pointer to acceleration device.
130 *
131 * Function removes configuration table from the given acceleration device
132 * and frees all allocated memory.
133 * To be used by QAT device specific drivers.
134 *
135 * Return: void
136 */
137void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
138{
139	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
140
141	if (!dev_cfg_data)
142		return;
143
144	down_write(&dev_cfg_data->lock);
145	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
146	up_write(&dev_cfg_data->lock);
147	kfree(dev_cfg_data);
148	accel_dev->cfg = NULL;
149}
150EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
151
152static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
153			       struct adf_cfg_section *sec)
154{
155	list_add_tail(&new->list, &sec->param_head);
156}
157
158static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
159{
160	struct list_head *head = &sec->param_head;
161	struct list_head *list_ptr, *tmp;
162
163	list_for_each_prev_safe(list_ptr, tmp, head) {
164		struct adf_cfg_key_val *ptr =
165			list_entry(list_ptr, struct adf_cfg_key_val, list);
166
167		if (strncmp(ptr->key, key, sizeof(ptr->key)))
168			continue;
169
170		list_del(list_ptr);
171		kfree(ptr);
172		break;
173	}
174}
175
176static void adf_cfg_keyval_del_all(struct list_head *head)
177{
178	struct list_head *list_ptr, *tmp;
179
180	list_for_each_prev_safe(list_ptr, tmp, head) {
181		struct adf_cfg_key_val *ptr =
182			list_entry(list_ptr, struct adf_cfg_key_val, list);
183		list_del(list_ptr);
184		kfree(ptr);
185	}
186}
187
188static void adf_cfg_section_del_all(struct list_head *head)
189{
190	struct adf_cfg_section *ptr;
191	struct list_head *list, *tmp;
192
193	list_for_each_prev_safe(list, tmp, head) {
194		ptr = list_entry(list, struct adf_cfg_section, list);
195		adf_cfg_keyval_del_all(&ptr->param_head);
196		list_del(list);
197		kfree(ptr);
198	}
199}
200
201static void adf_cfg_section_del_all_except(struct list_head *head,
202					   const char *section_name)
203{
204	struct list_head *list, *tmp;
205	struct adf_cfg_section *ptr;
206
207	list_for_each_prev_safe(list, tmp, head) {
208		ptr = list_entry(list, struct adf_cfg_section, list);
209		if (!strcmp(ptr->name, section_name))
210			continue;
211		adf_cfg_keyval_del_all(&ptr->param_head);
212		list_del(list);
213		kfree(ptr);
214	}
215}
216
217static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
218						      const char *key)
219{
220	struct list_head *list;
221
222	list_for_each(list, &s->param_head) {
223		struct adf_cfg_key_val *ptr =
224			list_entry(list, struct adf_cfg_key_val, list);
225		if (!strcmp(ptr->key, key))
226			return ptr;
227	}
228	return NULL;
229}
230
231static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
232						const char *sec_name)
233{
234	struct adf_cfg_device_data *cfg = accel_dev->cfg;
235	struct list_head *list;
236
237	list_for_each(list, &cfg->sec_list) {
238		struct adf_cfg_section *ptr =
239			list_entry(list, struct adf_cfg_section, list);
240		if (!strcmp(ptr->name, sec_name))
241			return ptr;
242	}
243	return NULL;
244}
245
246static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
247			       const char *sec_name,
248			       const char *key_name,
249			       char *val)
250{
251	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
252	struct adf_cfg_key_val *keyval = NULL;
253
254	if (sec)
255		keyval = adf_cfg_key_value_find(sec, key_name);
256	if (keyval) {
257		memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
258		return 0;
259	}
260	return -ENODATA;
261}
262
263/**
264 * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
265 * @accel_dev:  Pointer to acceleration device.
266 * @section_name: Name of the section where the param will be added
267 * @key: The key string
268 * @val: Value pain for the given @key
269 * @type: Type - string, int or address
270 *
271 * Function adds configuration key - value entry in the appropriate section
272 * in the given acceleration device. If the key exists already, the value
273 * is updated.
274 * To be used by QAT device specific drivers.
275 *
276 * Return: 0 on success, error code otherwise.
277 */
278int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
279				const char *section_name,
280				const char *key, const void *val,
281				enum adf_cfg_val_type type)
282{
283	struct adf_cfg_device_data *cfg = accel_dev->cfg;
284	struct adf_cfg_key_val *key_val;
285	struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
286							   section_name);
287	char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
288
289	if (!section)
290		return -EFAULT;
291
292	key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
293	if (!key_val)
294		return -ENOMEM;
295
296	INIT_LIST_HEAD(&key_val->list);
297	strscpy(key_val->key, key, sizeof(key_val->key));
298
299	if (type == ADF_DEC) {
300		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
301			 "%ld", (*((long *)val)));
302	} else if (type == ADF_STR) {
303		strscpy(key_val->val, (char *)val, sizeof(key_val->val));
304	} else if (type == ADF_HEX) {
305		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
306			 "0x%lx", (unsigned long)val);
307	} else {
308		dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
309		kfree(key_val);
310		return -EINVAL;
311	}
312	key_val->type = type;
313
314	/* Add the key-value pair as below policy:
315	 * 1. if the key doesn't exist, add it;
316	 * 2. if the key already exists with a different value then update it
317	 *    to the new value (the key is deleted and the newly created
318	 *    key_val containing the new value is added to the database);
319	 * 3. if the key exists with the same value, then return without doing
320	 *    anything (the newly created key_val is freed).
321	 */
322	down_write(&cfg->lock);
323	if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) {
324		if (strncmp(temp_val, key_val->val, sizeof(temp_val))) {
325			adf_cfg_keyval_remove(key, section);
326		} else {
327			kfree(key_val);
328			goto out;
329		}
330	}
331
332	adf_cfg_keyval_add(key_val, section);
333
334out:
335	up_write(&cfg->lock);
336	return 0;
337}
338EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
339
340/**
341 * adf_cfg_section_add() - Add config section entry to config table.
342 * @accel_dev:  Pointer to acceleration device.
343 * @name: Name of the section
344 *
345 * Function adds configuration section where key - value entries
346 * will be stored.
347 * To be used by QAT device specific drivers.
348 *
349 * Return: 0 on success, error code otherwise.
350 */
351int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
352{
353	struct adf_cfg_device_data *cfg = accel_dev->cfg;
354	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
355
356	if (sec)
357		return 0;
358
359	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
360	if (!sec)
361		return -ENOMEM;
362
363	strscpy(sec->name, name, sizeof(sec->name));
364	INIT_LIST_HEAD(&sec->param_head);
365	down_write(&cfg->lock);
366	list_add_tail(&sec->list, &cfg->sec_list);
367	up_write(&cfg->lock);
368	return 0;
369}
370EXPORT_SYMBOL_GPL(adf_cfg_section_add);
371
372int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
373			    const char *section, const char *name,
374			    char *value)
375{
376	struct adf_cfg_device_data *cfg = accel_dev->cfg;
377	int ret;
378
379	down_read(&cfg->lock);
380	ret = adf_cfg_key_val_get(accel_dev, section, name, value);
381	up_read(&cfg->lock);
382	return ret;
383}
384EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);
~/ Read-only file preview.