linux/drivers/crypto/qat/qat_common/adf_ctl_drv.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/module.h>
  48#include <linux/mutex.h>
  49#include <linux/slab.h>
  50#include <linux/fs.h>
  51#include <linux/bitops.h>
  52#include <linux/pci.h>
  53#include <linux/cdev.h>
  54#include <linux/uaccess.h>
  55#include <linux/crypto.h>
  56
  57#include "adf_accel_devices.h"
  58#include "adf_common_drv.h"
  59#include "adf_cfg.h"
  60#include "adf_cfg_common.h"
  61#include "adf_cfg_user.h"
  62
  63#define DEVICE_NAME "qat_adf_ctl"
  64
  65static DEFINE_MUTEX(adf_ctl_lock);
  66static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
  67
  68static const struct file_operations adf_ctl_ops = {
  69        .owner = THIS_MODULE,
  70        .unlocked_ioctl = adf_ctl_ioctl,
  71        .compat_ioctl = adf_ctl_ioctl,
  72};
  73
  74struct adf_ctl_drv_info {
  75        unsigned int major;
  76        struct cdev drv_cdev;
  77        struct class *drv_class;
  78};
  79
  80static struct adf_ctl_drv_info adf_ctl_drv;
  81
  82static void adf_chr_drv_destroy(void)
  83{
  84        device_destroy(adf_ctl_drv.drv_class, MKDEV(adf_ctl_drv.major, 0));
  85        cdev_del(&adf_ctl_drv.drv_cdev);
  86        class_destroy(adf_ctl_drv.drv_class);
  87        unregister_chrdev_region(MKDEV(adf_ctl_drv.major, 0), 1);
  88}
  89
  90static int adf_chr_drv_create(void)
  91{
  92        dev_t dev_id;
  93        struct device *drv_device;
  94
  95        if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
  96                pr_err("QAT: unable to allocate chrdev region\n");
  97                return -EFAULT;
  98        }
  99
 100        adf_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
 101        if (IS_ERR(adf_ctl_drv.drv_class)) {
 102                pr_err("QAT: class_create failed for adf_ctl\n");
 103                goto err_chrdev_unreg;
 104        }
 105        adf_ctl_drv.major = MAJOR(dev_id);
 106        cdev_init(&adf_ctl_drv.drv_cdev, &adf_ctl_ops);
 107        if (cdev_add(&adf_ctl_drv.drv_cdev, dev_id, 1)) {
 108                pr_err("QAT: cdev add failed\n");
 109                goto err_class_destr;
 110        }
 111
 112        drv_device = device_create(adf_ctl_drv.drv_class, NULL,
 113                                   MKDEV(adf_ctl_drv.major, 0),
 114                                   NULL, DEVICE_NAME);
 115        if (IS_ERR(drv_device)) {
 116                pr_err("QAT: failed to create device\n");
 117                goto err_cdev_del;
 118        }
 119        return 0;
 120err_cdev_del:
 121        cdev_del(&adf_ctl_drv.drv_cdev);
 122err_class_destr:
 123        class_destroy(adf_ctl_drv.drv_class);
 124err_chrdev_unreg:
 125        unregister_chrdev_region(dev_id, 1);
 126        return -EFAULT;
 127}
 128
 129static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
 130                                   unsigned long arg)
 131{
 132        struct adf_user_cfg_ctl_data *cfg_data;
 133
 134        cfg_data = kzalloc(sizeof(*cfg_data), GFP_KERNEL);
 135        if (!cfg_data)
 136                return -ENOMEM;
 137
 138        /* Initialize device id to NO DEVICE as 0 is a valid device id */
 139        cfg_data->device_id = ADF_CFG_NO_DEVICE;
 140
 141        if (copy_from_user(cfg_data, (void __user *)arg, sizeof(*cfg_data))) {
 142                pr_err("QAT: failed to copy from user cfg_data.\n");
 143                kfree(cfg_data);
 144                return -EIO;
 145        }
 146
 147        *ctl_data = cfg_data;
 148        return 0;
 149}
 150
 151static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
 152                                  const char *section,
 153                                  const struct adf_user_cfg_key_val *key_val)
 154{
 155        if (key_val->type == ADF_HEX) {
 156                long *ptr = (long *)key_val->val;
 157                long val = *ptr;
 158
 159                if (adf_cfg_add_key_value_param(accel_dev, section,
 160                                                key_val->key, (void *)val,
 161                                                key_val->type)) {
 162                        dev_err(&GET_DEV(accel_dev),
 163                                "failed to add hex keyvalue.\n");
 164                        return -EFAULT;
 165                }
 166        } else {
 167                if (adf_cfg_add_key_value_param(accel_dev, section,
 168                                                key_val->key, key_val->val,
 169                                                key_val->type)) {
 170                        dev_err(&GET_DEV(accel_dev),
 171                                "failed to add keyvalue.\n");
 172                        return -EFAULT;
 173                }
 174        }
 175        return 0;
 176}
 177
 178static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
 179                                   struct adf_user_cfg_ctl_data *ctl_data)
 180{
 181        struct adf_user_cfg_key_val key_val;
 182        struct adf_user_cfg_key_val *params_head;
 183        struct adf_user_cfg_section section, *section_head;
 184
 185        section_head = ctl_data->config_section;
 186
 187        while (section_head) {
 188                if (copy_from_user(&section, (void __user *)section_head,
 189                                   sizeof(*section_head))) {
 190                        dev_err(&GET_DEV(accel_dev),
 191                                "failed to copy section info\n");
 192                        goto out_err;
 193                }
 194
 195                if (adf_cfg_section_add(accel_dev, section.name)) {
 196                        dev_err(&GET_DEV(accel_dev),
 197                                "failed to add section.\n");
 198                        goto out_err;
 199                }
 200
 201                params_head = section.params;
 202
 203                while (params_head) {
 204                        if (copy_from_user(&key_val, (void __user *)params_head,
 205                                           sizeof(key_val))) {
 206                                dev_err(&GET_DEV(accel_dev),
 207                                        "Failed to copy keyvalue.\n");
 208                                goto out_err;
 209                        }
 210                        if (adf_add_key_value_data(accel_dev, section.name,
 211                                                   &key_val)) {
 212                                goto out_err;
 213                        }
 214                        params_head = key_val.next;
 215                }
 216                section_head = section.next;
 217        }
 218        return 0;
 219out_err:
 220        adf_cfg_del_all(accel_dev);
 221        return -EFAULT;
 222}
 223
 224static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
 225                                    unsigned long arg)
 226{
 227        int ret;
 228        struct adf_user_cfg_ctl_data *ctl_data;
 229        struct adf_accel_dev *accel_dev;
 230
 231        ret = adf_ctl_alloc_resources(&ctl_data, arg);
 232        if (ret)
 233                return ret;
 234
 235        accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
 236        if (!accel_dev) {
 237                ret = -EFAULT;
 238                goto out;
 239        }
 240
 241        if (adf_dev_started(accel_dev)) {
 242                ret = -EFAULT;
 243                goto out;
 244        }
 245
 246        if (adf_copy_key_value_data(accel_dev, ctl_data)) {
 247                ret = -EFAULT;
 248                goto out;
 249        }
 250        set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
 251out:
 252        kfree(ctl_data);
 253        return ret;
 254}
 255
 256static int adf_ctl_is_device_in_use(int id)
 257{
 258        struct adf_accel_dev *dev;
 259
 260        list_for_each_entry(dev, adf_devmgr_get_head(), list) {
 261                if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
 262                        if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
 263                                dev_info(&GET_DEV(dev),
 264                                         "device qat_dev%d is busy\n",
 265                                         dev->accel_id);
 266                                return -EBUSY;
 267                        }
 268                }
 269        }
 270        return 0;
 271}
 272
 273static void adf_ctl_stop_devices(uint32_t id)
 274{
 275        struct adf_accel_dev *accel_dev;
 276
 277        list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
 278                if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
 279                        if (!adf_dev_started(accel_dev))
 280                                continue;
 281
 282                        /* First stop all VFs */
 283                        if (!accel_dev->is_vf)
 284                                continue;
 285
 286                        adf_dev_stop(accel_dev);
 287                        adf_dev_shutdown(accel_dev);
 288                }
 289        }
 290
 291        list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
 292                if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
 293                        if (!adf_dev_started(accel_dev))
 294                                continue;
 295
 296                        adf_dev_stop(accel_dev);
 297                        adf_dev_shutdown(accel_dev);
 298                }
 299        }
 300}
 301
 302static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
 303                                  unsigned long arg)
 304{
 305        int ret;
 306        struct adf_user_cfg_ctl_data *ctl_data;
 307
 308        ret = adf_ctl_alloc_resources(&ctl_data, arg);
 309        if (ret)
 310                return ret;
 311
 312        if (adf_devmgr_verify_id(ctl_data->device_id)) {
 313                pr_err("QAT: Device %d not found\n", ctl_data->device_id);
 314                ret = -ENODEV;
 315                goto out;
 316        }
 317
 318        ret = adf_ctl_is_device_in_use(ctl_data->device_id);
 319        if (ret)
 320                goto out;
 321
 322        if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
 323                pr_info("QAT: Stopping all acceleration devices.\n");
 324        else
 325                pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
 326                        ctl_data->device_id);
 327
 328        adf_ctl_stop_devices(ctl_data->device_id);
 329
 330out:
 331        kfree(ctl_data);
 332        return ret;
 333}
 334
 335static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
 336                                   unsigned long arg)
 337{
 338        int ret;
 339        struct adf_user_cfg_ctl_data *ctl_data;
 340        struct adf_accel_dev *accel_dev;
 341
 342        ret = adf_ctl_alloc_resources(&ctl_data, arg);
 343        if (ret)
 344                return ret;
 345
 346        ret = -ENODEV;
 347        accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
 348        if (!accel_dev)
 349                goto out;
 350
 351        if (!adf_dev_started(accel_dev)) {
 352                dev_info(&GET_DEV(accel_dev),
 353                         "Starting acceleration device qat_dev%d.\n",
 354                         ctl_data->device_id);
 355                ret = adf_dev_init(accel_dev);
 356                if (!ret)
 357                        ret = adf_dev_start(accel_dev);
 358        } else {
 359                dev_info(&GET_DEV(accel_dev),
 360                         "Acceleration device qat_dev%d already started.\n",
 361                         ctl_data->device_id);
 362        }
 363        if (ret) {
 364                dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
 365                        ctl_data->device_id);
 366                adf_dev_stop(accel_dev);
 367                adf_dev_shutdown(accel_dev);
 368        }
 369out:
 370        kfree(ctl_data);
 371        return ret;
 372}
 373
 374static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
 375                                         unsigned long arg)
 376{
 377        uint32_t num_devices = 0;
 378
 379        adf_devmgr_get_num_dev(&num_devices);
 380        if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
 381                return -EFAULT;
 382
 383        return 0;
 384}
 385
 386static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
 387                                    unsigned long arg)
 388{
 389        struct adf_hw_device_data *hw_data;
 390        struct adf_dev_status_info dev_info;
 391        struct adf_accel_dev *accel_dev;
 392
 393        if (copy_from_user(&dev_info, (void __user *)arg,
 394                           sizeof(struct adf_dev_status_info))) {
 395                pr_err("QAT: failed to copy from user.\n");
 396                return -EFAULT;
 397        }
 398
 399        accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
 400        if (!accel_dev)
 401                return -ENODEV;
 402
 403        hw_data = accel_dev->hw_device;
 404        dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
 405        dev_info.num_ae = hw_data->get_num_aes(hw_data);
 406        dev_info.num_accel = hw_data->get_num_accels(hw_data);
 407        dev_info.num_logical_accel = hw_data->num_logical_accel;
 408        dev_info.banks_per_accel = hw_data->num_banks
 409                                        / hw_data->num_logical_accel;
 410        strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
 411        dev_info.instance_id = hw_data->instance_id;
 412        dev_info.type = hw_data->dev_class->type;
 413        dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
 414        dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
 415        dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
 416
 417        if (copy_to_user((void __user *)arg, &dev_info,
 418                         sizeof(struct adf_dev_status_info))) {
 419                dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
 420                return -EFAULT;
 421        }
 422        return 0;
 423}
 424
 425static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 426{
 427        int ret;
 428
 429        if (mutex_lock_interruptible(&adf_ctl_lock))
 430                return -EFAULT;
 431
 432        switch (cmd) {
 433        case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
 434                ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
 435                break;
 436
 437        case IOCTL_STOP_ACCEL_DEV:
 438                ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
 439                break;
 440
 441        case IOCTL_START_ACCEL_DEV:
 442                ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
 443                break;
 444
 445        case IOCTL_GET_NUM_DEVICES:
 446                ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
 447                break;
 448
 449        case IOCTL_STATUS_ACCEL_DEV:
 450                ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
 451                break;
 452        default:
 453                pr_err("QAT: Invalid ioctl\n");
 454                ret = -EFAULT;
 455                break;
 456        }
 457        mutex_unlock(&adf_ctl_lock);
 458        return ret;
 459}
 460
 461static int __init adf_register_ctl_device_driver(void)
 462{
 463        mutex_init(&adf_ctl_lock);
 464
 465        if (adf_chr_drv_create())
 466                goto err_chr_dev;
 467
 468        if (adf_init_aer())
 469                goto err_aer;
 470
 471        if (adf_init_pf_wq())
 472                goto err_pf_wq;
 473
 474        if (adf_init_vf_wq())
 475                goto err_vf_wq;
 476
 477        if (qat_crypto_register())
 478                goto err_crypto_register;
 479
 480        return 0;
 481
 482err_crypto_register:
 483        adf_exit_vf_wq();
 484err_vf_wq:
 485        adf_exit_pf_wq();
 486err_pf_wq:
 487        adf_exit_aer();
 488err_aer:
 489        adf_chr_drv_destroy();
 490err_chr_dev:
 491        mutex_destroy(&adf_ctl_lock);
 492        return -EFAULT;
 493}
 494
 495static void __exit adf_unregister_ctl_device_driver(void)
 496{
 497        adf_chr_drv_destroy();
 498        adf_exit_aer();
 499        adf_exit_vf_wq();
 500        adf_exit_pf_wq();
 501        qat_crypto_unregister();
 502        adf_clean_vf_map(false);
 503        mutex_destroy(&adf_ctl_lock);
 504}
 505
 506module_init(adf_register_ctl_device_driver);
 507module_exit(adf_unregister_ctl_device_driver);
 508MODULE_LICENSE("Dual BSD/GPL");
 509MODULE_AUTHOR("Intel");
 510MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
 511MODULE_ALIAS_CRYPTO("intel_qat");
 512MODULE_VERSION(ADF_DRV_VERSION);
 513