linux/drivers/crypto/qat/qat_common/adf_cfg.c
<<
>>
Prefs
   1/*
   2  This file is provided under a dual BSD/GPLv2 license.  When using or
   3  redistributing this file, you may do so under either license.
   4
   5  GPL LICENSE SUMMARY
   6  Copyright(c) 2014 Intel Corporation.
   7  This program is free software; you can redistribute it and/or modify
   8  it under the terms of version 2 of the GNU General Public License as
   9  published by the Free Software Foundation.
  10
  11  This program is distributed in the hope that it will be useful, but
  12  WITHOUT ANY WARRANTY; without even the implied warranty of
  13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14  General Public License for more details.
  15
  16  Contact Information:
  17  qat-linux@intel.com
  18
  19  BSD LICENSE
  20  Copyright(c) 2014 Intel Corporation.
  21  Redistribution and use in source and binary forms, with or without
  22  modification, are permitted provided that the following conditions
  23  are met:
  24
  25    * Redistributions of source code must retain the above copyright
  26      notice, this list of conditions and the following disclaimer.
  27    * Redistributions in binary form must reproduce the above copyright
  28      notice, this list of conditions and the following disclaimer in
  29      the documentation and/or other materials provided with the
  30      distribution.
  31    * Neither the name of Intel Corporation nor the names of its
  32      contributors may be used to endorse or promote products derived
  33      from this software without specific prior written permission.
  34
  35  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46*/
  47#include <linux/mutex.h>
  48#include <linux/slab.h>
  49#include <linux/list.h>
  50#include <linux/seq_file.h>
  51#include "adf_accel_devices.h"
  52#include "adf_cfg.h"
  53#include "adf_common_drv.h"
  54
  55static DEFINE_MUTEX(qat_cfg_read_lock);
  56
  57static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
  58{
  59        struct adf_cfg_device_data *dev_cfg = sfile->private;
  60
  61        mutex_lock(&qat_cfg_read_lock);
  62        return seq_list_start(&dev_cfg->sec_list, *pos);
  63}
  64
  65static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
  66{
  67        struct list_head *list;
  68        struct adf_cfg_section *sec =
  69                                list_entry(v, struct adf_cfg_section, list);
  70
  71        seq_printf(sfile, "[%s]\n", sec->name);
  72        list_for_each(list, &sec->param_head) {
  73                struct adf_cfg_key_val *ptr =
  74                        list_entry(list, struct adf_cfg_key_val, list);
  75                seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
  76        }
  77        return 0;
  78}
  79
  80static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
  81{
  82        struct adf_cfg_device_data *dev_cfg = sfile->private;
  83
  84        return seq_list_next(v, &dev_cfg->sec_list, pos);
  85}
  86
  87static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
  88{
  89        mutex_unlock(&qat_cfg_read_lock);
  90}
  91
  92static const struct seq_operations qat_dev_cfg_sops = {
  93        .start = qat_dev_cfg_start,
  94        .next = qat_dev_cfg_next,
  95        .stop = qat_dev_cfg_stop,
  96        .show = qat_dev_cfg_show
  97};
  98
  99static int qat_dev_cfg_open(struct inode *inode, struct file *file)
 100{
 101        int ret = seq_open(file, &qat_dev_cfg_sops);
 102
 103        if (!ret) {
 104                struct seq_file *seq_f = file->private_data;
 105
 106                seq_f->private = inode->i_private;
 107        }
 108        return ret;
 109}
 110
 111static const struct file_operations qat_dev_cfg_fops = {
 112        .open = qat_dev_cfg_open,
 113        .read = seq_read,
 114        .llseek = seq_lseek,
 115        .release = seq_release
 116};
 117
 118/**
 119 * adf_cfg_dev_add() - Create an acceleration device configuration table.
 120 * @accel_dev:  Pointer to acceleration device.
 121 *
 122 * Function creates a configuration table for the given acceleration device.
 123 * The table stores device specific config values.
 124 * To be used by QAT device specific drivers.
 125 *
 126 * Return: 0 on success, error code otherwise.
 127 */
 128int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
 129{
 130        struct adf_cfg_device_data *dev_cfg_data;
 131
 132        dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
 133        if (!dev_cfg_data)
 134                return -ENOMEM;
 135        INIT_LIST_HEAD(&dev_cfg_data->sec_list);
 136        init_rwsem(&dev_cfg_data->lock);
 137        accel_dev->cfg = dev_cfg_data;
 138
 139        /* accel_dev->debugfs_dir should always be non-NULL here */
 140        dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
 141                                                  accel_dev->debugfs_dir,
 142                                                  dev_cfg_data,
 143                                                  &qat_dev_cfg_fops);
 144        if (!dev_cfg_data->debug) {
 145                dev_err(&GET_DEV(accel_dev),
 146                        "Failed to create qat cfg debugfs entry.\n");
 147                kfree(dev_cfg_data);
 148                accel_dev->cfg = NULL;
 149                return -EFAULT;
 150        }
 151        return 0;
 152}
 153EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
 154
 155static void adf_cfg_section_del_all(struct list_head *head);
 156
 157void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
 158{
 159        struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
 160
 161        down_write(&dev_cfg_data->lock);
 162        adf_cfg_section_del_all(&dev_cfg_data->sec_list);
 163        up_write(&dev_cfg_data->lock);
 164        clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
 165}
 166
 167/**
 168 * adf_cfg_dev_remove() - Clears acceleration device configuration table.
 169 * @accel_dev:  Pointer to acceleration device.
 170 *
 171 * Function removes configuration table from the given acceleration device
 172 * and frees all allocated memory.
 173 * To be used by QAT device specific drivers.
 174 *
 175 * Return: void
 176 */
 177void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
 178{
 179        struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
 180
 181        if (!dev_cfg_data)
 182                return;
 183
 184        down_write(&dev_cfg_data->lock);
 185        adf_cfg_section_del_all(&dev_cfg_data->sec_list);
 186        up_write(&dev_cfg_data->lock);
 187        debugfs_remove(dev_cfg_data->debug);
 188        kfree(dev_cfg_data);
 189        accel_dev->cfg = NULL;
 190}
 191EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
 192
 193static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
 194                               struct adf_cfg_section *sec)
 195{
 196        list_add_tail(&new->list, &sec->param_head);
 197}
 198
 199static void adf_cfg_keyval_del_all(struct list_head *head)
 200{
 201        struct list_head *list_ptr, *tmp;
 202
 203        list_for_each_prev_safe(list_ptr, tmp, head) {
 204                struct adf_cfg_key_val *ptr =
 205                        list_entry(list_ptr, struct adf_cfg_key_val, list);
 206                list_del(list_ptr);
 207                kfree(ptr);
 208        }
 209}
 210
 211static void adf_cfg_section_del_all(struct list_head *head)
 212{
 213        struct adf_cfg_section *ptr;
 214        struct list_head *list, *tmp;
 215
 216        list_for_each_prev_safe(list, tmp, head) {
 217                ptr = list_entry(list, struct adf_cfg_section, list);
 218                adf_cfg_keyval_del_all(&ptr->param_head);
 219                list_del(list);
 220                kfree(ptr);
 221        }
 222}
 223
 224static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
 225                                                      const char *key)
 226{
 227        struct list_head *list;
 228
 229        list_for_each(list, &s->param_head) {
 230                struct adf_cfg_key_val *ptr =
 231                        list_entry(list, struct adf_cfg_key_val, list);
 232                if (!strcmp(ptr->key, key))
 233                        return ptr;
 234        }
 235        return NULL;
 236}
 237
 238static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
 239                                                const char *sec_name)
 240{
 241        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 242        struct list_head *list;
 243
 244        list_for_each(list, &cfg->sec_list) {
 245                struct adf_cfg_section *ptr =
 246                        list_entry(list, struct adf_cfg_section, list);
 247                if (!strcmp(ptr->name, sec_name))
 248                        return ptr;
 249        }
 250        return NULL;
 251}
 252
 253static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
 254                               const char *sec_name,
 255                               const char *key_name,
 256                               char *val)
 257{
 258        struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
 259        struct adf_cfg_key_val *keyval = NULL;
 260
 261        if (sec)
 262                keyval = adf_cfg_key_value_find(sec, key_name);
 263        if (keyval) {
 264                memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
 265                return 0;
 266        }
 267        return -1;
 268}
 269
 270/**
 271 * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
 272 * @accel_dev:  Pointer to acceleration device.
 273 * @section_name: Name of the section where the param will be added
 274 * @key: The key string
 275 * @val: Value pain for the given @key
 276 * @type: Type - string, int or address
 277 *
 278 * Function adds configuration key - value entry in the appropriate section
 279 * in the given acceleration device
 280 * To be used by QAT device specific drivers.
 281 *
 282 * Return: 0 on success, error code otherwise.
 283 */
 284int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
 285                                const char *section_name,
 286                                const char *key, const void *val,
 287                                enum adf_cfg_val_type type)
 288{
 289        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 290        struct adf_cfg_key_val *key_val;
 291        struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
 292                                                           section_name);
 293        if (!section)
 294                return -EFAULT;
 295
 296        key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
 297        if (!key_val)
 298                return -ENOMEM;
 299
 300        INIT_LIST_HEAD(&key_val->list);
 301        strlcpy(key_val->key, key, sizeof(key_val->key));
 302
 303        if (type == ADF_DEC) {
 304                snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
 305                         "%ld", (*((long *)val)));
 306        } else if (type == ADF_STR) {
 307                strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
 308        } else if (type == ADF_HEX) {
 309                snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
 310                         "0x%lx", (unsigned long)val);
 311        } else {
 312                dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
 313                kfree(key_val);
 314                return -1;
 315        }
 316        key_val->type = type;
 317        down_write(&cfg->lock);
 318        adf_cfg_keyval_add(key_val, section);
 319        up_write(&cfg->lock);
 320        return 0;
 321}
 322EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
 323
 324/**
 325 * adf_cfg_section_add() - Add config section entry to config table.
 326 * @accel_dev:  Pointer to acceleration device.
 327 * @name: Name of the section
 328 *
 329 * Function adds configuration section where key - value entries
 330 * will be stored.
 331 * To be used by QAT device specific drivers.
 332 *
 333 * Return: 0 on success, error code otherwise.
 334 */
 335int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
 336{
 337        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 338        struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
 339
 340        if (sec)
 341                return 0;
 342
 343        sec = kzalloc(sizeof(*sec), GFP_KERNEL);
 344        if (!sec)
 345                return -ENOMEM;
 346
 347        strlcpy(sec->name, name, sizeof(sec->name));
 348        INIT_LIST_HEAD(&sec->param_head);
 349        down_write(&cfg->lock);
 350        list_add_tail(&sec->list, &cfg->sec_list);
 351        up_write(&cfg->lock);
 352        return 0;
 353}
 354EXPORT_SYMBOL_GPL(adf_cfg_section_add);
 355
 356int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
 357                            const char *section, const char *name,
 358                            char *value)
 359{
 360        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 361        int ret;
 362
 363        down_read(&cfg->lock);
 364        ret = adf_cfg_key_val_get(accel_dev, section, name, value);
 365        up_read(&cfg->lock);
 366        return ret;
 367}
 368