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        return 0;
 145}
 146EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
 147
 148static void adf_cfg_section_del_all(struct list_head *head);
 149
 150void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
 151{
 152        struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
 153
 154        down_write(&dev_cfg_data->lock);
 155        adf_cfg_section_del_all(&dev_cfg_data->sec_list);
 156        up_write(&dev_cfg_data->lock);
 157        clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
 158}
 159
 160/**
 161 * adf_cfg_dev_remove() - Clears acceleration device configuration table.
 162 * @accel_dev:  Pointer to acceleration device.
 163 *
 164 * Function removes configuration table from the given acceleration device
 165 * and frees all allocated memory.
 166 * To be used by QAT device specific drivers.
 167 *
 168 * Return: void
 169 */
 170void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
 171{
 172        struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
 173
 174        if (!dev_cfg_data)
 175                return;
 176
 177        down_write(&dev_cfg_data->lock);
 178        adf_cfg_section_del_all(&dev_cfg_data->sec_list);
 179        up_write(&dev_cfg_data->lock);
 180        debugfs_remove(dev_cfg_data->debug);
 181        kfree(dev_cfg_data);
 182        accel_dev->cfg = NULL;
 183}
 184EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
 185
 186static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
 187                               struct adf_cfg_section *sec)
 188{
 189        list_add_tail(&new->list, &sec->param_head);
 190}
 191
 192static void adf_cfg_keyval_del_all(struct list_head *head)
 193{
 194        struct list_head *list_ptr, *tmp;
 195
 196        list_for_each_prev_safe(list_ptr, tmp, head) {
 197                struct adf_cfg_key_val *ptr =
 198                        list_entry(list_ptr, struct adf_cfg_key_val, list);
 199                list_del(list_ptr);
 200                kfree(ptr);
 201        }
 202}
 203
 204static void adf_cfg_section_del_all(struct list_head *head)
 205{
 206        struct adf_cfg_section *ptr;
 207        struct list_head *list, *tmp;
 208
 209        list_for_each_prev_safe(list, tmp, head) {
 210                ptr = list_entry(list, struct adf_cfg_section, list);
 211                adf_cfg_keyval_del_all(&ptr->param_head);
 212                list_del(list);
 213                kfree(ptr);
 214        }
 215}
 216
 217static 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
 231static 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
 246static 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 -1;
 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
 273 * To be used by QAT device specific drivers.
 274 *
 275 * Return: 0 on success, error code otherwise.
 276 */
 277int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
 278                                const char *section_name,
 279                                const char *key, const void *val,
 280                                enum adf_cfg_val_type type)
 281{
 282        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 283        struct adf_cfg_key_val *key_val;
 284        struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
 285                                                           section_name);
 286        if (!section)
 287                return -EFAULT;
 288
 289        key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
 290        if (!key_val)
 291                return -ENOMEM;
 292
 293        INIT_LIST_HEAD(&key_val->list);
 294        strlcpy(key_val->key, key, sizeof(key_val->key));
 295
 296        if (type == ADF_DEC) {
 297                snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
 298                         "%ld", (*((long *)val)));
 299        } else if (type == ADF_STR) {
 300                strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
 301        } else if (type == ADF_HEX) {
 302                snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
 303                         "0x%lx", (unsigned long)val);
 304        } else {
 305                dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
 306                kfree(key_val);
 307                return -1;
 308        }
 309        key_val->type = type;
 310        down_write(&cfg->lock);
 311        adf_cfg_keyval_add(key_val, section);
 312        up_write(&cfg->lock);
 313        return 0;
 314}
 315EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
 316
 317/**
 318 * adf_cfg_section_add() - Add config section entry to config table.
 319 * @accel_dev:  Pointer to acceleration device.
 320 * @name: Name of the section
 321 *
 322 * Function adds configuration section where key - value entries
 323 * will be stored.
 324 * To be used by QAT device specific drivers.
 325 *
 326 * Return: 0 on success, error code otherwise.
 327 */
 328int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
 329{
 330        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 331        struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
 332
 333        if (sec)
 334                return 0;
 335
 336        sec = kzalloc(sizeof(*sec), GFP_KERNEL);
 337        if (!sec)
 338                return -ENOMEM;
 339
 340        strlcpy(sec->name, name, sizeof(sec->name));
 341        INIT_LIST_HEAD(&sec->param_head);
 342        down_write(&cfg->lock);
 343        list_add_tail(&sec->list, &cfg->sec_list);
 344        up_write(&cfg->lock);
 345        return 0;
 346}
 347EXPORT_SYMBOL_GPL(adf_cfg_section_add);
 348
 349int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
 350                            const char *section, const char *name,
 351                            char *value)
 352{
 353        struct adf_cfg_device_data *cfg = accel_dev->cfg;
 354        int ret;
 355
 356        down_read(&cfg->lock);
 357        ret = adf_cfg_key_val_get(accel_dev, section, name, value);
 358        up_read(&cfg->lock);
 359        return ret;
 360}
 361