linux/drivers/s390/crypto/zcrypt_cex4.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Copyright IBM Corp. 2012
   4 *  Author(s): Holger Dengler <hd@linux.vnet.ibm.com>
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/slab.h>
   9#include <linux/init.h>
  10#include <linux/err.h>
  11#include <linux/atomic.h>
  12#include <linux/uaccess.h>
  13#include <linux/mod_devicetable.h>
  14
  15#include "ap_bus.h"
  16#include "zcrypt_api.h"
  17#include "zcrypt_msgtype6.h"
  18#include "zcrypt_msgtype50.h"
  19#include "zcrypt_error.h"
  20#include "zcrypt_cex4.h"
  21
  22#define CEX4A_MIN_MOD_SIZE        1     /*    8 bits    */
  23#define CEX4A_MAX_MOD_SIZE_2K   256     /* 2048 bits    */
  24#define CEX4A_MAX_MOD_SIZE_4K   512     /* 4096 bits    */
  25
  26#define CEX4C_MIN_MOD_SIZE       16     /*  256 bits    */
  27#define CEX4C_MAX_MOD_SIZE      512     /* 4096 bits    */
  28
  29#define CEX4A_MAX_MESSAGE_SIZE  MSGTYPE50_CRB3_MAX_MSG_SIZE
  30#define CEX4C_MAX_MESSAGE_SIZE  MSGTYPE06_MAX_MSG_SIZE
  31
  32/* Waiting time for requests to be processed.
  33 * Currently there are some types of request which are not deterministic.
  34 * But the maximum time limit managed by the stomper code is set to 60sec.
  35 * Hence we have to wait at least that time period.
  36 */
  37#define CEX4_CLEANUP_TIME       (900*HZ)
  38
  39MODULE_AUTHOR("IBM Corporation");
  40MODULE_DESCRIPTION("CEX4/CEX5/CEX6 Cryptographic Card device driver, " \
  41                   "Copyright IBM Corp. 2018");
  42MODULE_LICENSE("GPL");
  43
  44static struct ap_device_id zcrypt_cex4_card_ids[] = {
  45        { .dev_type = AP_DEVICE_TYPE_CEX4,
  46          .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
  47        { .dev_type = AP_DEVICE_TYPE_CEX5,
  48          .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
  49        { .dev_type = AP_DEVICE_TYPE_CEX6,
  50          .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
  51        { /* end of list */ },
  52};
  53
  54MODULE_DEVICE_TABLE(ap, zcrypt_cex4_card_ids);
  55
  56static struct ap_device_id zcrypt_cex4_queue_ids[] = {
  57        { .dev_type = AP_DEVICE_TYPE_CEX4,
  58          .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  59        { .dev_type = AP_DEVICE_TYPE_CEX5,
  60          .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  61        { .dev_type = AP_DEVICE_TYPE_CEX6,
  62          .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  63        { /* end of list */ },
  64};
  65
  66MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids);
  67
  68/**
  69 * Probe function for CEX4/CEX5/CEX6 card device. It always
  70 * accepts the AP device since the bus_match already checked
  71 * the hardware type.
  72 * @ap_dev: pointer to the AP device.
  73 */
  74static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
  75{
  76        /*
  77         * Normalized speed ratings per crypto adapter
  78         * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
  79         */
  80        static const int CEX4A_SPEED_IDX[] = {
  81                 14, 19, 249, 42, 228, 1458, 0, 0};
  82        static const int CEX5A_SPEED_IDX[] = {
  83                  8,  9,  20, 18,  66,  458, 0, 0};
  84        static const int CEX6A_SPEED_IDX[] = {
  85                  6,  9,  20, 17,  65,  438, 0, 0};
  86
  87        static const int CEX4C_SPEED_IDX[] = {
  88                 59,  69, 308, 83, 278, 2204, 209, 40};
  89        static const int CEX5C_SPEED_IDX[] = {
  90                 24,  31,  50, 37,  90,  479,  27, 10};
  91        static const int CEX6C_SPEED_IDX[] = {
  92                 16,  20,  32, 27,  77,  455,  23,  9};
  93
  94        static const int CEX4P_SPEED_IDX[] = {
  95                224, 313, 3560, 359, 605, 2827, 0, 50};
  96        static const int CEX5P_SPEED_IDX[] = {
  97                 63,  84,  156,  83, 142,  533, 0, 10};
  98        static const int CEX6P_SPEED_IDX[] = {
  99                 55,  70,  121,  73, 129,  522, 0,  9};
 100
 101        struct ap_card *ac = to_ap_card(&ap_dev->device);
 102        struct zcrypt_card *zc;
 103        int rc = 0;
 104
 105        zc = zcrypt_card_alloc();
 106        if (!zc)
 107                return -ENOMEM;
 108        zc->card = ac;
 109        ac->private = zc;
 110        if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) {
 111                if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
 112                        zc->type_string = "CEX4A";
 113                        zc->user_space_type = ZCRYPT_CEX4;
 114                        memcpy(zc->speed_rating, CEX4A_SPEED_IDX,
 115                               sizeof(CEX4A_SPEED_IDX));
 116                } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 117                        zc->type_string = "CEX5A";
 118                        zc->user_space_type = ZCRYPT_CEX5;
 119                        memcpy(zc->speed_rating, CEX5A_SPEED_IDX,
 120                               sizeof(CEX5A_SPEED_IDX));
 121                } else {
 122                        zc->type_string = "CEX6A";
 123                        zc->user_space_type = ZCRYPT_CEX6;
 124                        memcpy(zc->speed_rating, CEX6A_SPEED_IDX,
 125                               sizeof(CEX6A_SPEED_IDX));
 126                }
 127                zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
 128                if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
 129                    ap_test_bit(&ac->functions, AP_FUNC_CRT4K)) {
 130                        zc->max_mod_size = CEX4A_MAX_MOD_SIZE_4K;
 131                        zc->max_exp_bit_length =
 132                                CEX4A_MAX_MOD_SIZE_4K;
 133                } else {
 134                        zc->max_mod_size = CEX4A_MAX_MOD_SIZE_2K;
 135                        zc->max_exp_bit_length =
 136                                CEX4A_MAX_MOD_SIZE_2K;
 137                }
 138        } else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
 139                if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
 140                        zc->type_string = "CEX4C";
 141                        /* wrong user space type, must be CEX4
 142                         * just keep it for cca compatibility
 143                         */
 144                        zc->user_space_type = ZCRYPT_CEX3C;
 145                        memcpy(zc->speed_rating, CEX4C_SPEED_IDX,
 146                               sizeof(CEX4C_SPEED_IDX));
 147                } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 148                        zc->type_string = "CEX5C";
 149                        /* wrong user space type, must be CEX5
 150                         * just keep it for cca compatibility
 151                         */
 152                        zc->user_space_type = ZCRYPT_CEX3C;
 153                        memcpy(zc->speed_rating, CEX5C_SPEED_IDX,
 154                               sizeof(CEX5C_SPEED_IDX));
 155                } else {
 156                        zc->type_string = "CEX6C";
 157                        /* wrong user space type, must be CEX6
 158                         * just keep it for cca compatibility
 159                         */
 160                        zc->user_space_type = ZCRYPT_CEX3C;
 161                        memcpy(zc->speed_rating, CEX6C_SPEED_IDX,
 162                               sizeof(CEX6C_SPEED_IDX));
 163                }
 164                zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
 165                zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
 166                zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
 167        } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
 168                if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
 169                        zc->type_string = "CEX4P";
 170                        zc->user_space_type = ZCRYPT_CEX4;
 171                        memcpy(zc->speed_rating, CEX4P_SPEED_IDX,
 172                               sizeof(CEX4P_SPEED_IDX));
 173                } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 174                        zc->type_string = "CEX5P";
 175                        zc->user_space_type = ZCRYPT_CEX5;
 176                        memcpy(zc->speed_rating, CEX5P_SPEED_IDX,
 177                               sizeof(CEX5P_SPEED_IDX));
 178                } else {
 179                        zc->type_string = "CEX6P";
 180                        zc->user_space_type = ZCRYPT_CEX6;
 181                        memcpy(zc->speed_rating, CEX6P_SPEED_IDX,
 182                               sizeof(CEX6P_SPEED_IDX));
 183                }
 184                zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
 185                zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
 186                zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
 187        } else {
 188                zcrypt_card_free(zc);
 189                return -ENODEV;
 190        }
 191        zc->online = 1;
 192
 193        rc = zcrypt_card_register(zc);
 194        if (rc) {
 195                ac->private = NULL;
 196                zcrypt_card_free(zc);
 197        }
 198
 199        return rc;
 200}
 201
 202/**
 203 * This is called to remove the CEX4/CEX5/CEX6 card driver information
 204 * if an AP card device is removed.
 205 */
 206static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
 207{
 208        struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private;
 209
 210        if (zc)
 211                zcrypt_card_unregister(zc);
 212}
 213
 214static struct ap_driver zcrypt_cex4_card_driver = {
 215        .probe = zcrypt_cex4_card_probe,
 216        .remove = zcrypt_cex4_card_remove,
 217        .ids = zcrypt_cex4_card_ids,
 218        .flags = AP_DRIVER_FLAG_DEFAULT,
 219};
 220
 221/**
 222 * Probe function for CEX4/CEX5/CEX6 queue device. It always
 223 * accepts the AP device since the bus_match already checked
 224 * the hardware type.
 225 * @ap_dev: pointer to the AP device.
 226 */
 227static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
 228{
 229        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
 230        struct zcrypt_queue *zq;
 231        int rc;
 232
 233        if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) {
 234                zq = zcrypt_queue_alloc(CEX4A_MAX_MESSAGE_SIZE);
 235                if (!zq)
 236                        return -ENOMEM;
 237                zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
 238                                         MSGTYPE50_VARIANT_DEFAULT);
 239        } else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
 240                zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
 241                if (!zq)
 242                        return -ENOMEM;
 243                zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
 244                                         MSGTYPE06_VARIANT_DEFAULT);
 245        } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
 246                zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
 247                if (!zq)
 248                        return -ENOMEM;
 249                zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
 250                                         MSGTYPE06_VARIANT_EP11);
 251        } else {
 252                return -ENODEV;
 253        }
 254        zq->queue = aq;
 255        zq->online = 1;
 256        atomic_set(&zq->load, 0);
 257        ap_queue_init_reply(aq, &zq->reply);
 258        aq->request_timeout = CEX4_CLEANUP_TIME,
 259        aq->private = zq;
 260        rc = zcrypt_queue_register(zq);
 261        if (rc) {
 262                aq->private = NULL;
 263                zcrypt_queue_free(zq);
 264        }
 265
 266        return rc;
 267}
 268
 269/**
 270 * This is called to remove the CEX4/CEX5/CEX6 queue driver
 271 * information if an AP queue device is removed.
 272 */
 273static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
 274{
 275        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
 276        struct zcrypt_queue *zq = aq->private;
 277
 278        if (zq)
 279                zcrypt_queue_unregister(zq);
 280}
 281
 282static struct ap_driver zcrypt_cex4_queue_driver = {
 283        .probe = zcrypt_cex4_queue_probe,
 284        .remove = zcrypt_cex4_queue_remove,
 285        .suspend = ap_queue_suspend,
 286        .resume = ap_queue_resume,
 287        .ids = zcrypt_cex4_queue_ids,
 288        .flags = AP_DRIVER_FLAG_DEFAULT,
 289};
 290
 291int __init zcrypt_cex4_init(void)
 292{
 293        int rc;
 294
 295        rc = ap_driver_register(&zcrypt_cex4_card_driver,
 296                                THIS_MODULE, "cex4card");
 297        if (rc)
 298                return rc;
 299
 300        rc = ap_driver_register(&zcrypt_cex4_queue_driver,
 301                                THIS_MODULE, "cex4queue");
 302        if (rc)
 303                ap_driver_unregister(&zcrypt_cex4_card_driver);
 304
 305        return rc;
 306}
 307
 308void __exit zcrypt_cex4_exit(void)
 309{
 310        ap_driver_unregister(&zcrypt_cex4_queue_driver);
 311        ap_driver_unregister(&zcrypt_cex4_card_driver);
 312}
 313
 314module_init(zcrypt_cex4_init);
 315module_exit(zcrypt_cex4_exit);
 316