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