1*4882a593Smuzhiyun // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2*4882a593Smuzhiyun /* Copyright(c) 2014 - 2020 Intel Corporation */
3*4882a593Smuzhiyun #include <linux/mutex.h>
4*4882a593Smuzhiyun #include <linux/slab.h>
5*4882a593Smuzhiyun #include <linux/list.h>
6*4882a593Smuzhiyun #include <linux/seq_file.h>
7*4882a593Smuzhiyun #include "adf_accel_devices.h"
8*4882a593Smuzhiyun #include "adf_cfg.h"
9*4882a593Smuzhiyun #include "adf_common_drv.h"
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun static DEFINE_MUTEX(qat_cfg_read_lock);
12*4882a593Smuzhiyun
qat_dev_cfg_start(struct seq_file * sfile,loff_t * pos)13*4882a593Smuzhiyun static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun struct adf_cfg_device_data *dev_cfg = sfile->private;
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun mutex_lock(&qat_cfg_read_lock);
18*4882a593Smuzhiyun return seq_list_start(&dev_cfg->sec_list, *pos);
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun
qat_dev_cfg_show(struct seq_file * sfile,void * v)21*4882a593Smuzhiyun static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun struct list_head *list;
24*4882a593Smuzhiyun struct adf_cfg_section *sec =
25*4882a593Smuzhiyun list_entry(v, struct adf_cfg_section, list);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun seq_printf(sfile, "[%s]\n", sec->name);
28*4882a593Smuzhiyun list_for_each(list, &sec->param_head) {
29*4882a593Smuzhiyun struct adf_cfg_key_val *ptr =
30*4882a593Smuzhiyun list_entry(list, struct adf_cfg_key_val, list);
31*4882a593Smuzhiyun seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun return 0;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
qat_dev_cfg_next(struct seq_file * sfile,void * v,loff_t * pos)36*4882a593Smuzhiyun static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun struct adf_cfg_device_data *dev_cfg = sfile->private;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun return seq_list_next(v, &dev_cfg->sec_list, pos);
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
qat_dev_cfg_stop(struct seq_file * sfile,void * v)43*4882a593Smuzhiyun static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun mutex_unlock(&qat_cfg_read_lock);
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static const struct seq_operations qat_dev_cfg_sops = {
49*4882a593Smuzhiyun .start = qat_dev_cfg_start,
50*4882a593Smuzhiyun .next = qat_dev_cfg_next,
51*4882a593Smuzhiyun .stop = qat_dev_cfg_stop,
52*4882a593Smuzhiyun .show = qat_dev_cfg_show
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun DEFINE_SEQ_ATTRIBUTE(qat_dev_cfg);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /**
58*4882a593Smuzhiyun * adf_cfg_dev_add() - Create an acceleration device configuration table.
59*4882a593Smuzhiyun * @accel_dev: Pointer to acceleration device.
60*4882a593Smuzhiyun *
61*4882a593Smuzhiyun * Function creates a configuration table for the given acceleration device.
62*4882a593Smuzhiyun * The table stores device specific config values.
63*4882a593Smuzhiyun * To be used by QAT device specific drivers.
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * Return: 0 on success, error code otherwise.
66*4882a593Smuzhiyun */
adf_cfg_dev_add(struct adf_accel_dev * accel_dev)67*4882a593Smuzhiyun int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun struct adf_cfg_device_data *dev_cfg_data;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
72*4882a593Smuzhiyun if (!dev_cfg_data)
73*4882a593Smuzhiyun return -ENOMEM;
74*4882a593Smuzhiyun INIT_LIST_HEAD(&dev_cfg_data->sec_list);
75*4882a593Smuzhiyun init_rwsem(&dev_cfg_data->lock);
76*4882a593Smuzhiyun accel_dev->cfg = dev_cfg_data;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* accel_dev->debugfs_dir should always be non-NULL here */
79*4882a593Smuzhiyun dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
80*4882a593Smuzhiyun accel_dev->debugfs_dir,
81*4882a593Smuzhiyun dev_cfg_data,
82*4882a593Smuzhiyun &qat_dev_cfg_fops);
83*4882a593Smuzhiyun return 0;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun static void adf_cfg_section_del_all(struct list_head *head);
88*4882a593Smuzhiyun
adf_cfg_del_all(struct adf_accel_dev * accel_dev)89*4882a593Smuzhiyun void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun down_write(&dev_cfg_data->lock);
94*4882a593Smuzhiyun adf_cfg_section_del_all(&dev_cfg_data->sec_list);
95*4882a593Smuzhiyun up_write(&dev_cfg_data->lock);
96*4882a593Smuzhiyun clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /**
100*4882a593Smuzhiyun * adf_cfg_dev_remove() - Clears acceleration device configuration table.
101*4882a593Smuzhiyun * @accel_dev: Pointer to acceleration device.
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun * Function removes configuration table from the given acceleration device
104*4882a593Smuzhiyun * and frees all allocated memory.
105*4882a593Smuzhiyun * To be used by QAT device specific drivers.
106*4882a593Smuzhiyun *
107*4882a593Smuzhiyun * Return: void
108*4882a593Smuzhiyun */
adf_cfg_dev_remove(struct adf_accel_dev * accel_dev)109*4882a593Smuzhiyun void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (!dev_cfg_data)
114*4882a593Smuzhiyun return;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun down_write(&dev_cfg_data->lock);
117*4882a593Smuzhiyun adf_cfg_section_del_all(&dev_cfg_data->sec_list);
118*4882a593Smuzhiyun up_write(&dev_cfg_data->lock);
119*4882a593Smuzhiyun debugfs_remove(dev_cfg_data->debug);
120*4882a593Smuzhiyun kfree(dev_cfg_data);
121*4882a593Smuzhiyun accel_dev->cfg = NULL;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
124*4882a593Smuzhiyun
adf_cfg_keyval_add(struct adf_cfg_key_val * new,struct adf_cfg_section * sec)125*4882a593Smuzhiyun static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
126*4882a593Smuzhiyun struct adf_cfg_section *sec)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun list_add_tail(&new->list, &sec->param_head);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
adf_cfg_keyval_del_all(struct list_head * head)131*4882a593Smuzhiyun static void adf_cfg_keyval_del_all(struct list_head *head)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun struct list_head *list_ptr, *tmp;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun list_for_each_prev_safe(list_ptr, tmp, head) {
136*4882a593Smuzhiyun struct adf_cfg_key_val *ptr =
137*4882a593Smuzhiyun list_entry(list_ptr, struct adf_cfg_key_val, list);
138*4882a593Smuzhiyun list_del(list_ptr);
139*4882a593Smuzhiyun kfree(ptr);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
adf_cfg_section_del_all(struct list_head * head)143*4882a593Smuzhiyun static void adf_cfg_section_del_all(struct list_head *head)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct adf_cfg_section *ptr;
146*4882a593Smuzhiyun struct list_head *list, *tmp;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun list_for_each_prev_safe(list, tmp, head) {
149*4882a593Smuzhiyun ptr = list_entry(list, struct adf_cfg_section, list);
150*4882a593Smuzhiyun adf_cfg_keyval_del_all(&ptr->param_head);
151*4882a593Smuzhiyun list_del(list);
152*4882a593Smuzhiyun kfree(ptr);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
adf_cfg_key_value_find(struct adf_cfg_section * s,const char * key)156*4882a593Smuzhiyun static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
157*4882a593Smuzhiyun const char *key)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun struct list_head *list;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun list_for_each(list, &s->param_head) {
162*4882a593Smuzhiyun struct adf_cfg_key_val *ptr =
163*4882a593Smuzhiyun list_entry(list, struct adf_cfg_key_val, list);
164*4882a593Smuzhiyun if (!strcmp(ptr->key, key))
165*4882a593Smuzhiyun return ptr;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun return NULL;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
adf_cfg_sec_find(struct adf_accel_dev * accel_dev,const char * sec_name)170*4882a593Smuzhiyun static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
171*4882a593Smuzhiyun const char *sec_name)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct adf_cfg_device_data *cfg = accel_dev->cfg;
174*4882a593Smuzhiyun struct list_head *list;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun list_for_each(list, &cfg->sec_list) {
177*4882a593Smuzhiyun struct adf_cfg_section *ptr =
178*4882a593Smuzhiyun list_entry(list, struct adf_cfg_section, list);
179*4882a593Smuzhiyun if (!strcmp(ptr->name, sec_name))
180*4882a593Smuzhiyun return ptr;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun return NULL;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
adf_cfg_key_val_get(struct adf_accel_dev * accel_dev,const char * sec_name,const char * key_name,char * val)185*4882a593Smuzhiyun static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
186*4882a593Smuzhiyun const char *sec_name,
187*4882a593Smuzhiyun const char *key_name,
188*4882a593Smuzhiyun char *val)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
191*4882a593Smuzhiyun struct adf_cfg_key_val *keyval = NULL;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun if (sec)
194*4882a593Smuzhiyun keyval = adf_cfg_key_value_find(sec, key_name);
195*4882a593Smuzhiyun if (keyval) {
196*4882a593Smuzhiyun memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
197*4882a593Smuzhiyun return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun return -1;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /**
203*4882a593Smuzhiyun * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
204*4882a593Smuzhiyun * @accel_dev: Pointer to acceleration device.
205*4882a593Smuzhiyun * @section_name: Name of the section where the param will be added
206*4882a593Smuzhiyun * @key: The key string
207*4882a593Smuzhiyun * @val: Value pain for the given @key
208*4882a593Smuzhiyun * @type: Type - string, int or address
209*4882a593Smuzhiyun *
210*4882a593Smuzhiyun * Function adds configuration key - value entry in the appropriate section
211*4882a593Smuzhiyun * in the given acceleration device
212*4882a593Smuzhiyun * To be used by QAT device specific drivers.
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * Return: 0 on success, error code otherwise.
215*4882a593Smuzhiyun */
adf_cfg_add_key_value_param(struct adf_accel_dev * accel_dev,const char * section_name,const char * key,const void * val,enum adf_cfg_val_type type)216*4882a593Smuzhiyun int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
217*4882a593Smuzhiyun const char *section_name,
218*4882a593Smuzhiyun const char *key, const void *val,
219*4882a593Smuzhiyun enum adf_cfg_val_type type)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun struct adf_cfg_device_data *cfg = accel_dev->cfg;
222*4882a593Smuzhiyun struct adf_cfg_key_val *key_val;
223*4882a593Smuzhiyun struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
224*4882a593Smuzhiyun section_name);
225*4882a593Smuzhiyun if (!section)
226*4882a593Smuzhiyun return -EFAULT;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
229*4882a593Smuzhiyun if (!key_val)
230*4882a593Smuzhiyun return -ENOMEM;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun INIT_LIST_HEAD(&key_val->list);
233*4882a593Smuzhiyun strlcpy(key_val->key, key, sizeof(key_val->key));
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (type == ADF_DEC) {
236*4882a593Smuzhiyun snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
237*4882a593Smuzhiyun "%ld", (*((long *)val)));
238*4882a593Smuzhiyun } else if (type == ADF_STR) {
239*4882a593Smuzhiyun strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
240*4882a593Smuzhiyun } else if (type == ADF_HEX) {
241*4882a593Smuzhiyun snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
242*4882a593Smuzhiyun "0x%lx", (unsigned long)val);
243*4882a593Smuzhiyun } else {
244*4882a593Smuzhiyun dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
245*4882a593Smuzhiyun kfree(key_val);
246*4882a593Smuzhiyun return -1;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun key_val->type = type;
249*4882a593Smuzhiyun down_write(&cfg->lock);
250*4882a593Smuzhiyun adf_cfg_keyval_add(key_val, section);
251*4882a593Smuzhiyun up_write(&cfg->lock);
252*4882a593Smuzhiyun return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /**
257*4882a593Smuzhiyun * adf_cfg_section_add() - Add config section entry to config table.
258*4882a593Smuzhiyun * @accel_dev: Pointer to acceleration device.
259*4882a593Smuzhiyun * @name: Name of the section
260*4882a593Smuzhiyun *
261*4882a593Smuzhiyun * Function adds configuration section where key - value entries
262*4882a593Smuzhiyun * will be stored.
263*4882a593Smuzhiyun * To be used by QAT device specific drivers.
264*4882a593Smuzhiyun *
265*4882a593Smuzhiyun * Return: 0 on success, error code otherwise.
266*4882a593Smuzhiyun */
adf_cfg_section_add(struct adf_accel_dev * accel_dev,const char * name)267*4882a593Smuzhiyun int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun struct adf_cfg_device_data *cfg = accel_dev->cfg;
270*4882a593Smuzhiyun struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (sec)
273*4882a593Smuzhiyun return 0;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun sec = kzalloc(sizeof(*sec), GFP_KERNEL);
276*4882a593Smuzhiyun if (!sec)
277*4882a593Smuzhiyun return -ENOMEM;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun strlcpy(sec->name, name, sizeof(sec->name));
280*4882a593Smuzhiyun INIT_LIST_HEAD(&sec->param_head);
281*4882a593Smuzhiyun down_write(&cfg->lock);
282*4882a593Smuzhiyun list_add_tail(&sec->list, &cfg->sec_list);
283*4882a593Smuzhiyun up_write(&cfg->lock);
284*4882a593Smuzhiyun return 0;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_cfg_section_add);
287*4882a593Smuzhiyun
adf_cfg_get_param_value(struct adf_accel_dev * accel_dev,const char * section,const char * name,char * value)288*4882a593Smuzhiyun int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
289*4882a593Smuzhiyun const char *section, const char *name,
290*4882a593Smuzhiyun char *value)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct adf_cfg_device_data *cfg = accel_dev->cfg;
293*4882a593Smuzhiyun int ret;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun down_read(&cfg->lock);
296*4882a593Smuzhiyun ret = adf_cfg_key_val_get(accel_dev, section, name, value);
297*4882a593Smuzhiyun up_read(&cfg->lock);
298*4882a593Smuzhiyun return ret;
299*4882a593Smuzhiyun }
300