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