]> Git Repo - J-linux.git/blob - drivers/crypto/intel/qat/qat_common/adf_cfg.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / crypto / intel / qat / qat_common / adf_cfg.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
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(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 }
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
104 void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
105 {
106         struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
107
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);
112 }
113
114 /**
115  * adf_cfg_dev_remove() - Clears acceleration device configuration table.
116  * @accel_dev:  Pointer to acceleration device.
117  *
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.
121  *
122  * Return: void
123  */
124 void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
125 {
126         struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
127
128         if (!dev_cfg_data)
129                 return;
130
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);
134         kfree(dev_cfg_data);
135         accel_dev->cfg = NULL;
136 }
137 EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
138
139 static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
140                                struct adf_cfg_section *sec)
141 {
142         list_add_tail(&new->list, &sec->param_head);
143 }
144
145 static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec)
146 {
147         struct list_head *head = &sec->param_head;
148         struct list_head *list_ptr, *tmp;
149
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);
153
154                 if (strncmp(ptr->key, key, sizeof(ptr->key)))
155                         continue;
156
157                 list_del(list_ptr);
158                 kfree(ptr);
159                 break;
160         }
161 }
162
163 static void adf_cfg_keyval_del_all(struct list_head *head)
164 {
165         struct list_head *list_ptr, *tmp;
166
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);
170                 list_del(list_ptr);
171                 kfree(ptr);
172         }
173 }
174
175 static void adf_cfg_section_del_all(struct list_head *head)
176 {
177         struct adf_cfg_section *ptr;
178         struct list_head *list, *tmp;
179
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);
183                 list_del(list);
184                 kfree(ptr);
185         }
186 }
187
188 static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
189                                                       const char *key)
190 {
191         struct list_head *list;
192
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))
197                         return ptr;
198         }
199         return NULL;
200 }
201
202 static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
203                                                 const char *sec_name)
204 {
205         struct adf_cfg_device_data *cfg = accel_dev->cfg;
206         struct list_head *list;
207
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))
212                         return ptr;
213         }
214         return NULL;
215 }
216
217 static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
218                                const char *sec_name,
219                                const char *key_name,
220                                char *val)
221 {
222         struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
223         struct adf_cfg_key_val *keyval = NULL;
224
225         if (sec)
226                 keyval = adf_cfg_key_value_find(sec, key_name);
227         if (keyval) {
228                 memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
229                 return 0;
230         }
231         return -ENODATA;
232 }
233
234 /**
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
241  *
242  * Function adds configuration key - value entry in the appropriate section
243  * in the given acceleration device. If the key exists already, the value
244  * is updated.
245  * To be used by QAT device specific drivers.
246  *
247  * Return: 0 on success, error code otherwise.
248  */
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)
253 {
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,
257                                                            section_name);
258         char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
259
260         if (!section)
261                 return -EFAULT;
262
263         key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
264         if (!key_val)
265                 return -ENOMEM;
266
267         INIT_LIST_HEAD(&key_val->list);
268         strscpy(key_val->key, key, sizeof(key_val->key));
269
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);
278         } else {
279                 dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
280                 kfree(key_val);
281                 return -EINVAL;
282         }
283         key_val->type = type;
284
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).
292          */
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);
296                 } else {
297                         kfree(key_val);
298                         return 0;
299                 }
300         }
301
302         down_write(&cfg->lock);
303         adf_cfg_keyval_add(key_val, section);
304         up_write(&cfg->lock);
305         return 0;
306 }
307 EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
308
309 /**
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
313  *
314  * Function adds configuration section where key - value entries
315  * will be stored.
316  * To be used by QAT device specific drivers.
317  *
318  * Return: 0 on success, error code otherwise.
319  */
320 int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
321 {
322         struct adf_cfg_device_data *cfg = accel_dev->cfg;
323         struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
324
325         if (sec)
326                 return 0;
327
328         sec = kzalloc(sizeof(*sec), GFP_KERNEL);
329         if (!sec)
330                 return -ENOMEM;
331
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);
337         return 0;
338 }
339 EXPORT_SYMBOL_GPL(adf_cfg_section_add);
340
341 int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
342                             const char *section, const char *name,
343                             char *value)
344 {
345         struct adf_cfg_device_data *cfg = accel_dev->cfg;
346         int ret;
347
348         down_read(&cfg->lock);
349         ret = adf_cfg_key_val_get(accel_dev, section, name, value);
350         up_read(&cfg->lock);
351         return ret;
352 }
353 EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);
This page took 0.044796 seconds and 4 git commands to generate.