Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002  /* Management for virtio crypto devices (refer to adf_dev_mgr.c)
0003   *
0004   * Copyright 2016 HUAWEI TECHNOLOGIES CO., LTD.
0005   */
0006 
0007 #include <linux/mutex.h>
0008 #include <linux/list.h>
0009 #include <linux/module.h>
0010 
0011 #include <uapi/linux/virtio_crypto.h>
0012 #include "virtio_crypto_common.h"
0013 
0014 static LIST_HEAD(virtio_crypto_table);
0015 static uint32_t num_devices;
0016 
0017 /* The table_lock protects the above global list and num_devices */
0018 static DEFINE_MUTEX(table_lock);
0019 
0020 #define VIRTIO_CRYPTO_MAX_DEVICES 32
0021 
0022 
0023 /*
0024  * virtcrypto_devmgr_add_dev() - Add vcrypto_dev to the acceleration
0025  * framework.
0026  * @vcrypto_dev:  Pointer to virtio crypto device.
0027  *
0028  * Function adds virtio crypto device to the global list.
0029  * To be used by virtio crypto device specific drivers.
0030  *
0031  * Return: 0 on success, error code othewise.
0032  */
0033 int virtcrypto_devmgr_add_dev(struct virtio_crypto *vcrypto_dev)
0034 {
0035     struct list_head *itr;
0036 
0037     mutex_lock(&table_lock);
0038     if (num_devices == VIRTIO_CRYPTO_MAX_DEVICES) {
0039         pr_info("virtio_crypto: only support up to %d devices\n",
0040                 VIRTIO_CRYPTO_MAX_DEVICES);
0041         mutex_unlock(&table_lock);
0042         return -EFAULT;
0043     }
0044 
0045     list_for_each(itr, &virtio_crypto_table) {
0046         struct virtio_crypto *ptr =
0047                 list_entry(itr, struct virtio_crypto, list);
0048 
0049         if (ptr == vcrypto_dev) {
0050             mutex_unlock(&table_lock);
0051             return -EEXIST;
0052         }
0053     }
0054     atomic_set(&vcrypto_dev->ref_count, 0);
0055     list_add_tail(&vcrypto_dev->list, &virtio_crypto_table);
0056     vcrypto_dev->dev_id = num_devices++;
0057     mutex_unlock(&table_lock);
0058     return 0;
0059 }
0060 
0061 struct list_head *virtcrypto_devmgr_get_head(void)
0062 {
0063     return &virtio_crypto_table;
0064 }
0065 
0066 /*
0067  * virtcrypto_devmgr_rm_dev() - Remove vcrypto_dev from the acceleration
0068  * framework.
0069  * @vcrypto_dev:  Pointer to virtio crypto device.
0070  *
0071  * Function removes virtio crypto device from the acceleration framework.
0072  * To be used by virtio crypto device specific drivers.
0073  *
0074  * Return: void
0075  */
0076 void virtcrypto_devmgr_rm_dev(struct virtio_crypto *vcrypto_dev)
0077 {
0078     mutex_lock(&table_lock);
0079     list_del(&vcrypto_dev->list);
0080     num_devices--;
0081     mutex_unlock(&table_lock);
0082 }
0083 
0084 /*
0085  * virtcrypto_devmgr_get_first()
0086  *
0087  * Function returns the first virtio crypto device from the acceleration
0088  * framework.
0089  *
0090  * To be used by virtio crypto device specific drivers.
0091  *
0092  * Return: pointer to vcrypto_dev or NULL if not found.
0093  */
0094 struct virtio_crypto *virtcrypto_devmgr_get_first(void)
0095 {
0096     struct virtio_crypto *dev = NULL;
0097 
0098     mutex_lock(&table_lock);
0099     if (!list_empty(&virtio_crypto_table))
0100         dev = list_first_entry(&virtio_crypto_table,
0101                     struct virtio_crypto,
0102                     list);
0103     mutex_unlock(&table_lock);
0104     return dev;
0105 }
0106 
0107 /*
0108  * virtcrypto_dev_in_use() - Check whether vcrypto_dev is currently in use
0109  * @vcrypto_dev: Pointer to virtio crypto device.
0110  *
0111  * To be used by virtio crypto device specific drivers.
0112  *
0113  * Return: 1 when device is in use, 0 otherwise.
0114  */
0115 int virtcrypto_dev_in_use(struct virtio_crypto *vcrypto_dev)
0116 {
0117     return atomic_read(&vcrypto_dev->ref_count) != 0;
0118 }
0119 
0120 /*
0121  * virtcrypto_dev_get() - Increment vcrypto_dev reference count
0122  * @vcrypto_dev: Pointer to virtio crypto device.
0123  *
0124  * Increment the vcrypto_dev refcount and if this is the first time
0125  * incrementing it during this period the vcrypto_dev is in use,
0126  * increment the module refcount too.
0127  * To be used by virtio crypto device specific drivers.
0128  *
0129  * Return: 0 when successful, EFAULT when fail to bump module refcount
0130  */
0131 int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev)
0132 {
0133     if (atomic_add_return(1, &vcrypto_dev->ref_count) == 1)
0134         if (!try_module_get(vcrypto_dev->owner))
0135             return -EFAULT;
0136     return 0;
0137 }
0138 
0139 /*
0140  * virtcrypto_dev_put() - Decrement vcrypto_dev reference count
0141  * @vcrypto_dev: Pointer to virtio crypto device.
0142  *
0143  * Decrement the vcrypto_dev refcount and if this is the last time
0144  * decrementing it during this period the vcrypto_dev is in use,
0145  * decrement the module refcount too.
0146  * To be used by virtio crypto device specific drivers.
0147  *
0148  * Return: void
0149  */
0150 void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev)
0151 {
0152     if (atomic_sub_return(1, &vcrypto_dev->ref_count) == 0)
0153         module_put(vcrypto_dev->owner);
0154 }
0155 
0156 /*
0157  * virtcrypto_dev_started() - Check whether device has started
0158  * @vcrypto_dev: Pointer to virtio crypto device.
0159  *
0160  * To be used by virtio crypto device specific drivers.
0161  *
0162  * Return: 1 when the device has started, 0 otherwise
0163  */
0164 int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
0165 {
0166     return (vcrypto_dev->status & VIRTIO_CRYPTO_S_HW_READY);
0167 }
0168 
0169 /*
0170  * virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
0171  * @node:  Node id the driver works.
0172  * @service: Crypto service that needs to be supported by the
0173  *        dev
0174  * @algo: The algorithm number that needs to be supported by the
0175  *    dev
0176  *
0177  * Function returns the virtio crypto device used fewest on the node,
0178  * and supports the given crypto service and algorithm.
0179  *
0180  * To be used by virtio crypto device specific drivers.
0181  *
0182  * Return: pointer to vcrypto_dev or NULL if not found.
0183  */
0184 struct virtio_crypto *virtcrypto_get_dev_node(int node, uint32_t service,
0185                           uint32_t algo)
0186 {
0187     struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
0188     unsigned long best = ~0;
0189     unsigned long ctr;
0190 
0191     mutex_lock(&table_lock);
0192     list_for_each_entry(tmp_dev, virtcrypto_devmgr_get_head(), list) {
0193 
0194         if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
0195              dev_to_node(&tmp_dev->vdev->dev) < 0) &&
0196             virtcrypto_dev_started(tmp_dev) &&
0197             virtcrypto_algo_is_supported(tmp_dev, service, algo)) {
0198             ctr = atomic_read(&tmp_dev->ref_count);
0199             if (best > ctr) {
0200                 vcrypto_dev = tmp_dev;
0201                 best = ctr;
0202             }
0203         }
0204     }
0205 
0206     if (!vcrypto_dev) {
0207         pr_info("virtio_crypto: Could not find a device on node %d\n",
0208                 node);
0209         /* Get any started device */
0210         list_for_each_entry(tmp_dev,
0211                 virtcrypto_devmgr_get_head(), list) {
0212             if (virtcrypto_dev_started(tmp_dev) &&
0213                 virtcrypto_algo_is_supported(tmp_dev,
0214                 service, algo)) {
0215                 vcrypto_dev = tmp_dev;
0216                 break;
0217             }
0218         }
0219     }
0220     mutex_unlock(&table_lock);
0221     if (!vcrypto_dev)
0222         return NULL;
0223 
0224     virtcrypto_dev_get(vcrypto_dev);
0225     return vcrypto_dev;
0226 }
0227 
0228 /*
0229  * virtcrypto_dev_start() - Start virtio crypto device
0230  * @vcrypto:    Pointer to virtio crypto device.
0231  *
0232  * Function notifies all the registered services that the virtio crypto device
0233  * is ready to be used.
0234  * To be used by virtio crypto device specific drivers.
0235  *
0236  * Return: 0 on success, EFAULT when fail to register algorithms
0237  */
0238 int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
0239 {
0240     if (virtio_crypto_skcipher_algs_register(vcrypto)) {
0241         pr_err("virtio_crypto: Failed to register crypto skcipher algs\n");
0242         return -EFAULT;
0243     }
0244 
0245     if (virtio_crypto_akcipher_algs_register(vcrypto)) {
0246         pr_err("virtio_crypto: Failed to register crypto akcipher algs\n");
0247         virtio_crypto_skcipher_algs_unregister(vcrypto);
0248         return -EFAULT;
0249     }
0250 
0251     return 0;
0252 }
0253 
0254 /*
0255  * virtcrypto_dev_stop() - Stop virtio crypto device
0256  * @vcrypto:    Pointer to virtio crypto device.
0257  *
0258  * Function notifies all the registered services that the virtio crypto device
0259  * is ready to be used.
0260  * To be used by virtio crypto device specific drivers.
0261  *
0262  * Return: void
0263  */
0264 void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
0265 {
0266     virtio_crypto_skcipher_algs_unregister(vcrypto);
0267     virtio_crypto_akcipher_algs_unregister(vcrypto);
0268 }
0269 
0270 /*
0271  * vcrypto_algo_is_supported()
0272  * @vcrypto: Pointer to virtio crypto device.
0273  * @service: The bit number for service validate.
0274  *        See VIRTIO_CRYPTO_SERVICE_*
0275  * @algo : The bit number for the algorithm to validate.
0276  *
0277  *
0278  * Validate if the virtio crypto device supports a service and
0279  * algo.
0280  *
0281  * Return true if device supports a service and algo.
0282  */
0283 
0284 bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto,
0285                   uint32_t service,
0286                   uint32_t algo)
0287 {
0288     uint32_t service_mask = 1u << service;
0289     uint32_t algo_mask = 0;
0290     bool low = true;
0291 
0292     if (algo > 31) {
0293         algo -= 32;
0294         low = false;
0295     }
0296 
0297     if (!(vcrypto->crypto_services & service_mask))
0298         return false;
0299 
0300     switch (service) {
0301     case VIRTIO_CRYPTO_SERVICE_CIPHER:
0302         if (low)
0303             algo_mask = vcrypto->cipher_algo_l;
0304         else
0305             algo_mask = vcrypto->cipher_algo_h;
0306         break;
0307 
0308     case VIRTIO_CRYPTO_SERVICE_HASH:
0309         algo_mask = vcrypto->hash_algo;
0310         break;
0311 
0312     case VIRTIO_CRYPTO_SERVICE_MAC:
0313         if (low)
0314             algo_mask = vcrypto->mac_algo_l;
0315         else
0316             algo_mask = vcrypto->mac_algo_h;
0317         break;
0318 
0319     case VIRTIO_CRYPTO_SERVICE_AEAD:
0320         algo_mask = vcrypto->aead_algo;
0321         break;
0322 
0323     case VIRTIO_CRYPTO_SERVICE_AKCIPHER:
0324         algo_mask = vcrypto->akcipher_algo;
0325         break;
0326     }
0327 
0328     if (!(algo_mask & (1u << algo)))
0329         return false;
0330 
0331     return true;
0332 }