root/drivers/crypto/qat/qat_common/adf_ctl_drv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adf_chr_drv_destroy
  2. adf_chr_drv_create
  3. adf_ctl_alloc_resources
  4. adf_add_key_value_data
  5. adf_copy_key_value_data
  6. adf_ctl_ioctl_dev_config
  7. adf_ctl_is_device_in_use
  8. adf_ctl_stop_devices
  9. adf_ctl_ioctl_dev_stop
  10. adf_ctl_ioctl_dev_start
  11. adf_ctl_ioctl_get_num_devices
  12. adf_ctl_ioctl_get_status
  13. adf_ctl_ioctl
  14. adf_register_ctl_device_driver
  15. adf_unregister_ctl_device_driver

   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 
  65 static DEFINE_MUTEX(adf_ctl_lock);
  66 static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
  67 
  68 static 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 
  74 struct adf_ctl_drv_info {
  75         unsigned int major;
  76         struct cdev drv_cdev;
  77         struct class *drv_class;
  78 };
  79 
  80 static struct adf_ctl_drv_info adf_ctl_drv;
  81 
  82 static 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 
  90 static 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;
 120 err_cdev_del:
 121         cdev_del(&adf_ctl_drv.drv_cdev);
 122 err_class_destr:
 123         class_destroy(adf_ctl_drv.drv_class);
 124 err_chrdev_unreg:
 125         unregister_chrdev_region(dev_id, 1);
 126         return -EFAULT;
 127 }
 128 
 129 static 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 
 151 static 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 
 178 static 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;
 219 out_err:
 220         adf_cfg_del_all(accel_dev);
 221         return -EFAULT;
 222 }
 223 
 224 static 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);
 251 out:
 252         kfree(ctl_data);
 253         return ret;
 254 }
 255 
 256 static 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 
 273 static 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 
 302 static 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 
 330 out:
 331         kfree(ctl_data);
 332         return ret;
 333 }
 334 
 335 static 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         }
 369 out:
 370         kfree(ctl_data);
 371         return ret;
 372 }
 373 
 374 static 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 
 386 static 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 
 425 static 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 
 461 static 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 
 482 err_crypto_register:
 483         adf_exit_vf_wq();
 484 err_vf_wq:
 485         adf_exit_pf_wq();
 486 err_pf_wq:
 487         adf_exit_aer();
 488 err_aer:
 489         adf_chr_drv_destroy();
 490 err_chr_dev:
 491         mutex_destroy(&adf_ctl_lock);
 492         return -EFAULT;
 493 }
 494 
 495 static 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 
 506 module_init(adf_register_ctl_device_driver);
 507 module_exit(adf_unregister_ctl_device_driver);
 508 MODULE_LICENSE("Dual BSD/GPL");
 509 MODULE_AUTHOR("Intel");
 510 MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
 511 MODULE_ALIAS_CRYPTO("intel_qat");
 512 MODULE_VERSION(ADF_DRV_VERSION);

/* [<][>][^][v][top][bottom][index][help] */