Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/crypto/intel/qat/qat_common/adf_cfg.c
29278 views
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
static void adf_cfg_section_del_all_except(struct list_head *head,
104
const char *section_name);
105
106
void 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
116
void 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
*/
137
void 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
}
150
EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
151
152
static 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
158
static 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
176
static 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
188
static 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
201
static 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
217
static 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
231
static 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
246
static 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
*/
278
int 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
334
out:
335
up_write(&cfg->lock);
336
return 0;
337
}
338
EXPORT_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
*/
351
int 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
}
370
EXPORT_SYMBOL_GPL(adf_cfg_section_add);
371
372
int 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
}
384
EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);
385
386