GNU Linux-libre 5.16.19-gnu
[releases.git] / drivers / crypto / 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
78         /* accel_dev->debugfs_dir should always be non-NULL here */
79         dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
80                                                   accel_dev->debugfs_dir,
81                                                   dev_cfg_data,
82                                                   &qat_dev_cfg_fops);
83         return 0;
84 }
85 EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
86
87 static void adf_cfg_section_del_all(struct list_head *head);
88
89 void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
90 {
91         struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
92
93         down_write(&dev_cfg_data->lock);
94         adf_cfg_section_del_all(&dev_cfg_data->sec_list);
95         up_write(&dev_cfg_data->lock);
96         clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
97 }
98
99 /**
100  * adf_cfg_dev_remove() - Clears acceleration device configuration table.
101  * @accel_dev:  Pointer to acceleration device.
102  *
103  * Function removes configuration table from the given acceleration device
104  * and frees all allocated memory.
105  * To be used by QAT device specific drivers.
106  *
107  * Return: void
108  */
109 void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
110 {
111         struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
112
113         if (!dev_cfg_data)
114                 return;
115
116         down_write(&dev_cfg_data->lock);
117         adf_cfg_section_del_all(&dev_cfg_data->sec_list);
118         up_write(&dev_cfg_data->lock);
119         debugfs_remove(dev_cfg_data->debug);
120         kfree(dev_cfg_data);
121         accel_dev->cfg = NULL;
122 }
123 EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
124
125 static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
126                                struct adf_cfg_section *sec)
127 {
128         list_add_tail(&new->list, &sec->param_head);
129 }
130
131 static void adf_cfg_keyval_del_all(struct list_head *head)
132 {
133         struct list_head *list_ptr, *tmp;
134
135         list_for_each_prev_safe(list_ptr, tmp, head) {
136                 struct adf_cfg_key_val *ptr =
137                         list_entry(list_ptr, struct adf_cfg_key_val, list);
138                 list_del(list_ptr);
139                 kfree(ptr);
140         }
141 }
142
143 static void adf_cfg_section_del_all(struct list_head *head)
144 {
145         struct adf_cfg_section *ptr;
146         struct list_head *list, *tmp;
147
148         list_for_each_prev_safe(list, tmp, head) {
149                 ptr = list_entry(list, struct adf_cfg_section, list);
150                 adf_cfg_keyval_del_all(&ptr->param_head);
151                 list_del(list);
152                 kfree(ptr);
153         }
154 }
155
156 static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
157                                                       const char *key)
158 {
159         struct list_head *list;
160
161         list_for_each(list, &s->param_head) {
162                 struct adf_cfg_key_val *ptr =
163                         list_entry(list, struct adf_cfg_key_val, list);
164                 if (!strcmp(ptr->key, key))
165                         return ptr;
166         }
167         return NULL;
168 }
169
170 static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
171                                                 const char *sec_name)
172 {
173         struct adf_cfg_device_data *cfg = accel_dev->cfg;
174         struct list_head *list;
175
176         list_for_each(list, &cfg->sec_list) {
177                 struct adf_cfg_section *ptr =
178                         list_entry(list, struct adf_cfg_section, list);
179                 if (!strcmp(ptr->name, sec_name))
180                         return ptr;
181         }
182         return NULL;
183 }
184
185 static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
186                                const char *sec_name,
187                                const char *key_name,
188                                char *val)
189 {
190         struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
191         struct adf_cfg_key_val *keyval = NULL;
192
193         if (sec)
194                 keyval = adf_cfg_key_value_find(sec, key_name);
195         if (keyval) {
196                 memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
197                 return 0;
198         }
199         return -ENODATA;
200 }
201
202 /**
203  * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
204  * @accel_dev:  Pointer to acceleration device.
205  * @section_name: Name of the section where the param will be added
206  * @key: The key string
207  * @val: Value pain for the given @key
208  * @type: Type - string, int or address
209  *
210  * Function adds configuration key - value entry in the appropriate section
211  * in the given acceleration device
212  * To be used by QAT device specific drivers.
213  *
214  * Return: 0 on success, error code otherwise.
215  */
216 int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
217                                 const char *section_name,
218                                 const char *key, const void *val,
219                                 enum adf_cfg_val_type type)
220 {
221         struct adf_cfg_device_data *cfg = accel_dev->cfg;
222         struct adf_cfg_key_val *key_val;
223         struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
224                                                            section_name);
225         if (!section)
226                 return -EFAULT;
227
228         key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
229         if (!key_val)
230                 return -ENOMEM;
231
232         INIT_LIST_HEAD(&key_val->list);
233         strlcpy(key_val->key, key, sizeof(key_val->key));
234
235         if (type == ADF_DEC) {
236                 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
237                          "%ld", (*((long *)val)));
238         } else if (type == ADF_STR) {
239                 strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
240         } else if (type == ADF_HEX) {
241                 snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
242                          "0x%lx", (unsigned long)val);
243         } else {
244                 dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
245                 kfree(key_val);
246                 return -EINVAL;
247         }
248         key_val->type = type;
249         down_write(&cfg->lock);
250         adf_cfg_keyval_add(key_val, section);
251         up_write(&cfg->lock);
252         return 0;
253 }
254 EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
255
256 /**
257  * adf_cfg_section_add() - Add config section entry to config table.
258  * @accel_dev:  Pointer to acceleration device.
259  * @name: Name of the section
260  *
261  * Function adds configuration section where key - value entries
262  * will be stored.
263  * To be used by QAT device specific drivers.
264  *
265  * Return: 0 on success, error code otherwise.
266  */
267 int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
268 {
269         struct adf_cfg_device_data *cfg = accel_dev->cfg;
270         struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
271
272         if (sec)
273                 return 0;
274
275         sec = kzalloc(sizeof(*sec), GFP_KERNEL);
276         if (!sec)
277                 return -ENOMEM;
278
279         strlcpy(sec->name, name, sizeof(sec->name));
280         INIT_LIST_HEAD(&sec->param_head);
281         down_write(&cfg->lock);
282         list_add_tail(&sec->list, &cfg->sec_list);
283         up_write(&cfg->lock);
284         return 0;
285 }
286 EXPORT_SYMBOL_GPL(adf_cfg_section_add);
287
288 int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
289                             const char *section, const char *name,
290                             char *value)
291 {
292         struct adf_cfg_device_data *cfg = accel_dev->cfg;
293         int ret;
294
295         down_read(&cfg->lock);
296         ret = adf_cfg_key_val_get(accel_dev, section, name, value);
297         up_read(&cfg->lock);
298         return ret;
299 }