cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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);