adf_cfg.c (8155B)
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 11static DEFINE_MUTEX(qat_cfg_read_lock); 12 13static 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 21static 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 36static 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 43static void qat_dev_cfg_stop(struct seq_file *sfile, void *v) 44{ 45 mutex_unlock(&qat_cfg_read_lock); 46} 47 48static 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 55DEFINE_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 */ 67int 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} 85EXPORT_SYMBOL_GPL(adf_cfg_dev_add); 86 87static void adf_cfg_section_del_all(struct list_head *head); 88 89void 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 */ 109void 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} 123EXPORT_SYMBOL_GPL(adf_cfg_dev_remove); 124 125static 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 131static 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 143static 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 156static 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 170static 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 185static 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 */ 216int 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} 254EXPORT_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 */ 267int 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} 286EXPORT_SYMBOL_GPL(adf_cfg_section_add); 287 288int 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} 300EXPORT_SYMBOL_GPL(adf_cfg_get_param_value);