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
;
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
,
85 EXPORT_SYMBOL_GPL(adf_cfg_dev_add
);
87 static void adf_cfg_section_del_all(struct list_head
*head
);
89 void adf_cfg_del_all(struct adf_accel_dev
*accel_dev
)
91 struct adf_cfg_device_data
*dev_cfg_data
= accel_dev
->cfg
;
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
);
100 * adf_cfg_dev_remove() - Clears acceleration device configuration table.
101 * @accel_dev: Pointer to acceleration device.
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.
109 void adf_cfg_dev_remove(struct adf_accel_dev
*accel_dev
)
111 struct adf_cfg_device_data
*dev_cfg_data
= accel_dev
->cfg
;
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
);
121 accel_dev
->cfg
= NULL
;
123 EXPORT_SYMBOL_GPL(adf_cfg_dev_remove
);
125 static void adf_cfg_keyval_add(struct adf_cfg_key_val
*new,
126 struct adf_cfg_section
*sec
)
128 list_add_tail(&new->list
, &sec
->param_head
);
131 static void adf_cfg_keyval_del_all(struct list_head
*head
)
133 struct list_head
*list_ptr
, *tmp
;
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
);
143 static void adf_cfg_section_del_all(struct list_head
*head
)
145 struct adf_cfg_section
*ptr
;
146 struct list_head
*list
, *tmp
;
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
);
156 static struct adf_cfg_key_val
*adf_cfg_key_value_find(struct adf_cfg_section
*s
,
159 struct list_head
*list
;
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
))
170 static struct adf_cfg_section
*adf_cfg_sec_find(struct adf_accel_dev
*accel_dev
,
171 const char *sec_name
)
173 struct adf_cfg_device_data
*cfg
= accel_dev
->cfg
;
174 struct list_head
*list
;
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
))
185 static int adf_cfg_key_val_get(struct adf_accel_dev
*accel_dev
,
186 const char *sec_name
,
187 const char *key_name
,
190 struct adf_cfg_section
*sec
= adf_cfg_sec_find(accel_dev
, sec_name
);
191 struct adf_cfg_key_val
*keyval
= NULL
;
194 keyval
= adf_cfg_key_value_find(sec
, key_name
);
196 memcpy(val
, keyval
->val
, ADF_CFG_MAX_VAL_LEN_IN_BYTES
);
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
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.
214 * Return: 0 on success, error code otherwise.
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
)
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
,
228 key_val
= kzalloc(sizeof(*key_val
), GFP_KERNEL
);
232 INIT_LIST_HEAD(&key_val
->list
);
233 strlcpy(key_val
->key
, key
, sizeof(key_val
->key
));
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
);
244 dev_err(&GET_DEV(accel_dev
), "Unknown type given.\n");
248 key_val
->type
= type
;
249 down_write(&cfg
->lock
);
250 adf_cfg_keyval_add(key_val
, section
);
251 up_write(&cfg
->lock
);
254 EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param
);
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
261 * Function adds configuration section where key - value entries
263 * To be used by QAT device specific drivers.
265 * Return: 0 on success, error code otherwise.
267 int adf_cfg_section_add(struct adf_accel_dev
*accel_dev
, const char *name
)
269 struct adf_cfg_device_data
*cfg
= accel_dev
->cfg
;
270 struct adf_cfg_section
*sec
= adf_cfg_sec_find(accel_dev
, name
);
275 sec
= kzalloc(sizeof(*sec
), GFP_KERNEL
);
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
);
286 EXPORT_SYMBOL_GPL(adf_cfg_section_add
);
288 int adf_cfg_get_param_value(struct adf_accel_dev
*accel_dev
,
289 const char *section
, const char *name
,
292 struct adf_cfg_device_data
*cfg
= accel_dev
->cfg
;
295 down_read(&cfg
->lock
);
296 ret
= adf_cfg_key_val_get(accel_dev
, section
, name
, value
);