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 int adf_ctl_stop_devices(uint32_t id)
 274{
 275        struct adf_accel_dev *accel_dev;
 276        int ret = 0;
 277
 278        list_for_each_entry_reverse(accel_dev, adf_devmgr_get_head(), list) {
 279                if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
 280                        if (!adf_dev_started(accel_dev))
 281                                continue;
 282
 283                        if (adf_dev_stop(accel_dev)) {
 284                                dev_err(&GET_DEV(accel_dev),
 285                                        "Failed to stop qat_dev%d\n", id);
 286                                ret = -EFAULT;
 287                        } else {
 288                                adf_dev_shutdown(accel_dev);
 289                        }
 290                }
 291        }
 292        return ret;
 293}
 294
 295static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
 296                                  unsigned long arg)
 297{
 298        int ret;
 299        struct adf_user_cfg_ctl_data *ctl_data;
 300
 301        ret = adf_ctl_alloc_resources(&ctl_data, arg);
 302        if (ret)
 303                return ret;
 304
 305        if (adf_devmgr_verify_id(ctl_data->device_id)) {
 306                pr_err("QAT: Device %d not found\n", ctl_data->device_id);
 307                ret = -ENODEV;
 308                goto out;
 309        }
 310
 311        ret = adf_ctl_is_device_in_use(ctl_data->device_id);
 312        if (ret)
 313                goto out;
 314
 315        if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
 316                pr_info("QAT: Stopping all acceleration devices.\n");
 317        else
 318                pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
 319                        ctl_data->device_id);
 320
 321        ret = adf_ctl_stop_devices(ctl_data->device_id);
 322        if (ret)
 323                pr_err("QAT: failed to stop device.\n");
 324out:
 325        kfree(ctl_data);
 326        return ret;
 327}
 328
 329static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
 330                                   unsigned long arg)
 331{
 332        int ret;
 333        struct adf_user_cfg_ctl_data *ctl_data;
 334        struct adf_accel_dev *accel_dev;
 335
 336        ret = adf_ctl_alloc_resources(&ctl_data, arg);
 337        if (ret)
 338                return ret;
 339
 340        ret = -ENODEV;
 341        accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
 342        if (!accel_dev)
 343                goto out;
 344
 345        if (!adf_dev_started(accel_dev)) {
 346                dev_info(&GET_DEV(accel_dev),
 347                         "Starting acceleration device qat_dev%d.\n",
 348                         ctl_data->device_id);
 349                ret = adf_dev_init(accel_dev);
 350                if (!ret)
 351                        ret = adf_dev_start(accel_dev);
 352        } else {
 353                dev_info(&GET_DEV(accel_dev),
 354                         "Acceleration device qat_dev%d already started.\n",
 355                         ctl_data->device_id);
 356        }
 357        if (ret) {
 358                dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
 359                        ctl_data->device_id);
 360                adf_dev_stop(accel_dev);
 361                adf_dev_shutdown(accel_dev);
 362        }
 363out:
 364        kfree(ctl_data);
 365        return ret;
 366}
 367
 368static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
 369                                         unsigned long arg)
 370{
 371        uint32_t num_devices = 0;
 372
 373        adf_devmgr_get_num_dev(&num_devices);
 374        if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
 375                return -EFAULT;
 376
 377        return 0;
 378}
 379
 380static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
 381                                    unsigned long arg)
 382{
 383        struct adf_hw_device_data *hw_data;
 384        struct adf_dev_status_info dev_info;
 385        struct adf_accel_dev *accel_dev;
 386
 387        if (copy_from_user(&dev_info, (void __user *)arg,
 388                           sizeof(struct adf_dev_status_info))) {
 389                pr_err("QAT: failed to copy from user.\n");
 390                return -EFAULT;
 391        }
 392
 393        accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
 394        if (!accel_dev)
 395                return -ENODEV;
 396
 397        hw_data = accel_dev->hw_device;
 398        dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
 399        dev_info.num_ae = hw_data->get_num_aes(hw_data);
 400        dev_info.num_accel = hw_data->get_num_accels(hw_data);
 401        dev_info.num_logical_accel = hw_data->num_logical_accel;
 402        dev_info.banks_per_accel = hw_data->num_banks
 403                                        / hw_data->num_logical_accel;
 404        strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
 405        dev_info.instance_id = hw_data->instance_id;
 406        dev_info.type = hw_data->dev_class->type;
 407        dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
 408        dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
 409        dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
 410
 411        if (copy_to_user((void __user *)arg, &dev_info,
 412                         sizeof(struct adf_dev_status_info))) {
 413                dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
 414                return -EFAULT;
 415        }
 416        return 0;
 417}
 418
 419static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 420{
 421        int ret;
 422
 423        if (mutex_lock_interruptible(&adf_ctl_lock))
 424                return -EFAULT;
 425
 426        switch (cmd) {
 427        case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
 428                ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
 429                break;
 430
 431        case IOCTL_STOP_ACCEL_DEV:
 432                ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
 433                break;
 434
 435        case IOCTL_START_ACCEL_DEV:
 436                ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
 437                break;
 438
 439        case IOCTL_GET_NUM_DEVICES:
 440                ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
 441                break;
 442
 443        case IOCTL_STATUS_ACCEL_DEV:
 444                ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
 445                break;
 446        default:
 447                pr_err("QAT: Invalid ioctl\n");
 448                ret = -EFAULT;
 449                break;
 450        }
 451        mutex_unlock(&adf_ctl_lock);
 452        return ret;
 453}
 454
 455static int __init adf_register_ctl_device_driver(void)
 456{
 457        mutex_init(&adf_ctl_lock);
 458
 459        if (adf_chr_drv_create())
 460                goto err_chr_dev;
 461
 462        if (adf_init_aer())
 463                goto err_aer;
 464
 465        if (adf_init_pf_wq())
 466                goto err_pf_wq;
 467
 468        if (qat_crypto_register())
 469                goto err_crypto_register;
 470
 471        return 0;
 472
 473err_crypto_register:
 474        adf_exit_pf_wq();
 475err_pf_wq:
 476        adf_exit_aer();
 477err_aer:
 478        adf_chr_drv_destroy();
 479err_chr_dev:
 480        mutex_destroy(&adf_ctl_lock);
 481        return -EFAULT;
 482}
 483
 484static void __exit adf_unregister_ctl_device_driver(void)
 485{
 486        adf_chr_drv_destroy();
 487        adf_exit_aer();
 488        adf_exit_pf_wq();
 489        qat_crypto_unregister();
 490        adf_clean_vf_map(false);
 491        mutex_destroy(&adf_ctl_lock);
 492}
 493
 494module_init(adf_register_ctl_device_driver);
 495module_exit(adf_unregister_ctl_device_driver);
 496MODULE_LICENSE("Dual BSD/GPL");
 497MODULE_AUTHOR("Intel");
 498MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
 499MODULE_ALIAS_CRYPTO("intel_qat");
 500MODULE_VERSION(ADF_DRV_VERSION);
 501