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"
9 #include "adf_common_drv.h"
11 static DEFINE_MUTEX(qat_cfg_read_lock);
13 static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
15 struct adf_cfg_device_data *dev_cfg = sfile->private;
17 mutex_lock(&qat_cfg_read_lock);
18 return seq_list_start(&dev_cfg->sec_list, *pos);
21 static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
23 struct list_head *list;
24 struct adf_cfg_section *sec =
25 list_entry(v, struct adf_cfg_section, list);
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);
36 static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
38 struct adf_cfg_device_data *dev_cfg = sfile->private;
40 return seq_list_next(v, &dev_cfg->sec_list, pos);
43 static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
45 mutex_unlock(&qat_cfg_read_lock);
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
55 DEFINE_SEQ_ATTRIBUTE(qat_dev_cfg);
58 * adf_cfg_dev_add() - Create an acceleration device configuration table.
59 * @accel_dev: Pointer to acceleration device.
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.
65 * Return: 0 on success, error code otherwise.
67 int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
69 struct adf_cfg_device_data *dev_cfg_data;
71 dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
74 INIT_LIST_HEAD(&dev_cfg_data->sec_list);
75 init_rwsem(&dev_cfg_data->lock);
76 accel_dev->cfg = dev_cfg_data;
79 EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
81 void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev)
83 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
85 dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400,
86 accel_dev->debugfs_dir,
91 void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev)
93 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
98 debugfs_remove(dev_cfg_data->debug);
99 dev_cfg_data->debug = NULL;
102 static void adf_cfg_section_del_all(struct list_head *head);
104 void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
106 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
108 down_write(&dev_cfg_data->lock);
109 adf_cfg_section_del_all(&dev_cfg_data->sec_list);
110 up_write(&dev_cfg_data->lock);
111 clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
115 * adf_cfg_dev_remove() - Clears acceleration device configuration table.
116 * @accel_dev: Pointer to acceleration device.
118 * Function removes configuration table from the given acceleration device
119 * and frees all allocated memory.
120 * To be used by QAT device specific drivers.
124 void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
126 struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
131 down_write(&dev_cfg_data->lock);
132 adf_cfg_section_del_all(&dev_cfg_data->sec_list);
133 up_write(&dev_cfg_data->lock);
135 accel_dev->cfg = NULL;
137 EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
139 static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
140 struct adf_cfg_section *sec)
142 list_add_tail(&new->list, &sec->param_head);
145 static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
147 struct list_head *head = &sec->param_head;
148 struct list_head *list_ptr, *tmp;
150 list_for_each_prev_safe(list_ptr, tmp, head) {
151 struct adf_cfg_key_val *ptr =
152 list_entry(list_ptr, struct adf_cfg_key_val, list);
154 if (strncmp(ptr->key, key, sizeof(ptr->key)))
163 static void adf_cfg_keyval_del_all(struct list_head *head)
165 struct list_head *list_ptr, *tmp;
167 list_for_each_prev_safe(list_ptr, tmp, head) {
168 struct adf_cfg_key_val *ptr =
169 list_entry(list_ptr, struct adf_cfg_key_val, list);
175 static void adf_cfg_section_del_all(struct list_head *head)
177 struct adf_cfg_section *ptr;
178 struct list_head *list, *tmp;
180 list_for_each_prev_safe(list, tmp, head) {
181 ptr = list_entry(list, struct adf_cfg_section, list);
182 adf_cfg_keyval_del_all(&ptr->param_head);
188 static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
191 struct list_head *list;
193 list_for_each(list, &s->param_head) {
194 struct adf_cfg_key_val *ptr =
195 list_entry(list, struct adf_cfg_key_val, list);
196 if (!strcmp(ptr->key, key))
202 static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
203 const char *sec_name)
205 struct adf_cfg_device_data *cfg = accel_dev->cfg;
206 struct list_head *list;
208 list_for_each(list, &cfg->sec_list) {
209 struct adf_cfg_section *ptr =
210 list_entry(list, struct adf_cfg_section, list);
211 if (!strcmp(ptr->name, sec_name))
217 static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
218 const char *sec_name,
219 const char *key_name,
222 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
223 struct adf_cfg_key_val *keyval = NULL;
226 keyval = adf_cfg_key_value_find(sec, key_name);
228 memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
235 * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
236 * @accel_dev: Pointer to acceleration device.
237 * @section_name: Name of the section where the param will be added
238 * @key: The key string
239 * @val: Value pain for the given @key
240 * @type: Type - string, int or address
242 * Function adds configuration key - value entry in the appropriate section
243 * in the given acceleration device. If the key exists already, the value
245 * To be used by QAT device specific drivers.
247 * Return: 0 on success, error code otherwise.
249 int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
250 const char *section_name,
251 const char *key, const void *val,
252 enum adf_cfg_val_type type)
254 struct adf_cfg_device_data *cfg = accel_dev->cfg;
255 struct adf_cfg_key_val *key_val;
256 struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
258 char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
263 key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
267 INIT_LIST_HEAD(&key_val->list);
268 strscpy(key_val->key, key, sizeof(key_val->key));
270 if (type == ADF_DEC) {
271 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
272 "%ld", (*((long *)val)));
273 } else if (type == ADF_STR) {
274 strscpy(key_val->val, (char *)val, sizeof(key_val->val));
275 } else if (type == ADF_HEX) {
276 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
277 "0x%lx", (unsigned long)val);
279 dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
283 key_val->type = type;
285 /* Add the key-value pair as below policy:
286 * 1. if the key doesn't exist, add it;
287 * 2. if the key already exists with a different value then update it
288 * to the new value (the key is deleted and the newly created
289 * key_val containing the new value is added to the database);
290 * 3. if the key exists with the same value, then return without doing
291 * anything (the newly created key_val is freed).
293 if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) {
294 if (strncmp(temp_val, key_val->val, sizeof(temp_val))) {
295 adf_cfg_keyval_remove(key, section);
302 down_write(&cfg->lock);
303 adf_cfg_keyval_add(key_val, section);
304 up_write(&cfg->lock);
307 EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
310 * adf_cfg_section_add() - Add config section entry to config table.
311 * @accel_dev: Pointer to acceleration device.
312 * @name: Name of the section
314 * Function adds configuration section where key - value entries
316 * To be used by QAT device specific drivers.
318 * Return: 0 on success, error code otherwise.
320 int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
322 struct adf_cfg_device_data *cfg = accel_dev->cfg;
323 struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
328 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
332 strscpy(sec->name, name, sizeof(sec->name));
333 INIT_LIST_HEAD(&sec->param_head);
334 down_write(&cfg->lock);
335 list_add_tail(&sec->list, &cfg->sec_list);
336 up_write(&cfg->lock);
339 EXPORT_SYMBOL_GPL(adf_cfg_section_add);
341 int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
342 const char *section, const char *name,
345 struct adf_cfg_device_data *cfg = accel_dev->cfg;
348 down_read(&cfg->lock);
349 ret = adf_cfg_key_val_get(accel_dev, section, name, value);
353 EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);