zcrypt_cex4.c 9.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2 3 4 5 6 7 8 9 10 11 12
/*
 *  Copyright IBM Corp. 2012
 *  Author(s): Holger Dengler <hd@linux.vnet.ibm.com>
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/atomic.h>
#include <linux/uaccess.h>
13
#include <linux/mod_devicetable.h>
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

#include "ap_bus.h"
#include "zcrypt_api.h"
#include "zcrypt_msgtype6.h"
#include "zcrypt_msgtype50.h"
#include "zcrypt_error.h"
#include "zcrypt_cex4.h"

#define CEX4A_MIN_MOD_SIZE	  1	/*    8 bits	*/
#define CEX4A_MAX_MOD_SIZE_2K	256	/* 2048 bits	*/
#define CEX4A_MAX_MOD_SIZE_4K	512	/* 4096 bits	*/

#define CEX4C_MIN_MOD_SIZE	 16	/*  256 bits	*/
#define CEX4C_MAX_MOD_SIZE	512	/* 4096 bits	*/

#define CEX4A_MAX_MESSAGE_SIZE	MSGTYPE50_CRB3_MAX_MSG_SIZE
#define CEX4C_MAX_MESSAGE_SIZE	MSGTYPE06_MAX_MSG_SIZE

32 33 34 35 36
/* Waiting time for requests to be processed.
 * Currently there are some types of request which are not deterministic.
 * But the maximum time limit managed by the stomper code is set to 60sec.
 * Hence we have to wait at least that time period.
 */
37
#define CEX4_CLEANUP_TIME	(900*HZ)
38 39

MODULE_AUTHOR("IBM Corporation");
40 41
MODULE_DESCRIPTION("CEX4/CEX5/CEX6 Cryptographic Card device driver, " \
		   "Copyright IBM Corp. 2018");
42 43
MODULE_LICENSE("GPL");

44 45 46 47 48
static struct ap_device_id zcrypt_cex4_card_ids[] = {
	{ .dev_type = AP_DEVICE_TYPE_CEX4,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX5,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
49 50
	{ .dev_type = AP_DEVICE_TYPE_CEX6,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
51 52 53 54
	{ /* end of list */ },
};

MODULE_DEVICE_TABLE(ap, zcrypt_cex4_card_ids);
55

56 57 58 59 60
static struct ap_device_id zcrypt_cex4_queue_ids[] = {
	{ .dev_type = AP_DEVICE_TYPE_CEX4,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX5,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
61 62
	{ .dev_type = AP_DEVICE_TYPE_CEX6,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
63
	{ /* end of list */ },
64 65
};

66 67
MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids);

68
/**
69 70 71
 * Probe function for CEX4/CEX5/CEX6 card device. It always
 * accepts the AP device since the bus_match already checked
 * the hardware type.
72 73
 * @ap_dev: pointer to the AP device.
 */
74
static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
75
{
76 77 78 79
	/*
	 * Normalized speed ratings per crypto adapter
	 * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
	 */
80
	static const int CEX4A_SPEED_IDX[] = {
81
		 14, 19, 249, 42, 228, 1458, 0, 0};
82
	static const int CEX5A_SPEED_IDX[] = {
83 84 85 86
		  8,  9,  20, 18,  66,	458, 0, 0};
	static const int CEX6A_SPEED_IDX[] = {
		  6,  9,  20, 17,  65,	438, 0, 0};

87
	static const int CEX4C_SPEED_IDX[] = {
88
		 59,  69, 308, 83, 278, 2204, 209, 40};
89
	static const int CEX5C_SPEED_IDX[] = {
90 91 92 93
		 24,  31,  50, 37,  90,  479,  27, 10};
	static const int CEX6C_SPEED_IDX[] = {
		 16,  20,  32, 27,  77,  455,  23,  9};

94
	static const int CEX4P_SPEED_IDX[] = {
95
		224, 313, 3560, 359, 605, 2827, 0, 50};
96
	static const int CEX5P_SPEED_IDX[] = {
97 98 99
		 63,  84,  156,  83, 142,  533, 0, 10};
	static const int CEX6P_SPEED_IDX[] = {
		 55,  70,  121,  73, 129,  522, 0,  9};
100 101 102

	struct ap_card *ac = to_ap_card(&ap_dev->device);
	struct zcrypt_card *zc;
103 104
	int rc = 0;

105 106 107 108 109 110 111 112 113 114 115
	zc = zcrypt_card_alloc();
	if (!zc)
		return -ENOMEM;
	zc->card = ac;
	ac->private = zc;
	if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) {
		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
			zc->type_string = "CEX4A";
			zc->user_space_type = ZCRYPT_CEX4;
			memcpy(zc->speed_rating, CEX4A_SPEED_IDX,
			       sizeof(CEX4A_SPEED_IDX));
116
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
117 118 119 120
			zc->type_string = "CEX5A";
			zc->user_space_type = ZCRYPT_CEX5;
			memcpy(zc->speed_rating, CEX5A_SPEED_IDX,
			       sizeof(CEX5A_SPEED_IDX));
121 122 123 124 125
		} else {
			zc->type_string = "CEX6A";
			zc->user_space_type = ZCRYPT_CEX6;
			memcpy(zc->speed_rating, CEX6A_SPEED_IDX,
			       sizeof(CEX6A_SPEED_IDX));
126
		}
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
		zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
		if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
		    ap_test_bit(&ac->functions, AP_FUNC_CRT4K)) {
			zc->max_mod_size = CEX4A_MAX_MOD_SIZE_4K;
			zc->max_exp_bit_length =
				CEX4A_MAX_MOD_SIZE_4K;
		} else {
			zc->max_mod_size = CEX4A_MAX_MOD_SIZE_2K;
			zc->max_exp_bit_length =
				CEX4A_MAX_MOD_SIZE_2K;
		}
	} else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
			zc->type_string = "CEX4C";
			/* wrong user space type, must be CEX4
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			memcpy(zc->speed_rating, CEX4C_SPEED_IDX,
			       sizeof(CEX4C_SPEED_IDX));
147
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
148 149 150 151 152 153 154
			zc->type_string = "CEX5C";
			/* wrong user space type, must be CEX5
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			memcpy(zc->speed_rating, CEX5C_SPEED_IDX,
			       sizeof(CEX5C_SPEED_IDX));
155 156 157 158 159 160 161 162
		} else {
			zc->type_string = "CEX6C";
			/* wrong user space type, must be CEX6
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			memcpy(zc->speed_rating, CEX6C_SPEED_IDX,
			       sizeof(CEX6C_SPEED_IDX));
163 164 165 166 167 168 169 170 171 172
		}
		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
		zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
	} else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
			zc->type_string = "CEX4P";
			zc->user_space_type = ZCRYPT_CEX4;
			memcpy(zc->speed_rating, CEX4P_SPEED_IDX,
			       sizeof(CEX4P_SPEED_IDX));
173
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
174 175 176 177
			zc->type_string = "CEX5P";
			zc->user_space_type = ZCRYPT_CEX5;
			memcpy(zc->speed_rating, CEX5P_SPEED_IDX,
			       sizeof(CEX5P_SPEED_IDX));
178 179 180 181 182
		} else {
			zc->type_string = "CEX6P";
			zc->user_space_type = ZCRYPT_CEX6;
			memcpy(zc->speed_rating, CEX6P_SPEED_IDX,
			       sizeof(CEX6P_SPEED_IDX));
183 184 185 186 187 188
		}
		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
		zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
	} else {
		zcrypt_card_free(zc);
189
		return -ENODEV;
190 191 192 193
	}
	zc->online = 1;

	rc = zcrypt_card_register(zc);
194
	if (rc) {
195 196
		ac->private = NULL;
		zcrypt_card_free(zc);
197
	}
198

199 200 201 202
	return rc;
}

/**
203
 * This is called to remove the CEX4/CEX5/CEX6 card driver information
204
 * if an AP card device is removed.
205
 */
206
static 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 211 212 213 214 215 216 217
	if (zc)
		zcrypt_card_unregister(zc);
}

static struct ap_driver zcrypt_cex4_card_driver = {
	.probe = zcrypt_cex4_card_probe,
	.remove = zcrypt_cex4_card_remove,
	.ids = zcrypt_cex4_card_ids,
218
	.flags = AP_DRIVER_FLAG_DEFAULT,
219 220 221
};

/**
222 223 224
 * Probe function for CEX4/CEX5/CEX6 queue device. It always
 * accepts the AP device since the bus_match already checked
 * the hardware type.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
 * @ap_dev: pointer to the AP device.
 */
static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
{
	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
	struct zcrypt_queue *zq;
	int rc;

	if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) {
		zq = zcrypt_queue_alloc(CEX4A_MAX_MESSAGE_SIZE);
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
					 MSGTYPE50_VARIANT_DEFAULT);
	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
		zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_DEFAULT);
	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
		zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_EP11);
	} else {
		return -ENODEV;
253
	}
254 255 256 257 258 259 260 261 262 263 264 265 266
	zq->queue = aq;
	zq->online = 1;
	atomic_set(&zq->load, 0);
	ap_queue_init_reply(aq, &zq->reply);
	aq->request_timeout = CEX4_CLEANUP_TIME,
	aq->private = zq;
	rc = zcrypt_queue_register(zq);
	if (rc) {
		aq->private = NULL;
		zcrypt_queue_free(zq);
	}

	return rc;
267 268
}

269
/**
270 271
 * This is called to remove the CEX4/CEX5/CEX6 queue driver
 * information if an AP queue device is removed.
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
 */
static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
{
	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
	struct zcrypt_queue *zq = aq->private;

	if (zq)
		zcrypt_queue_unregister(zq);
}

static struct ap_driver zcrypt_cex4_queue_driver = {
	.probe = zcrypt_cex4_queue_probe,
	.remove = zcrypt_cex4_queue_remove,
	.suspend = ap_queue_suspend,
	.resume = ap_queue_resume,
	.ids = zcrypt_cex4_queue_ids,
288
	.flags = AP_DRIVER_FLAG_DEFAULT,
289 290
};

291 292
int __init zcrypt_cex4_init(void)
{
293 294 295 296 297 298 299 300 301 302 303 304 305
	int rc;

	rc = ap_driver_register(&zcrypt_cex4_card_driver,
				THIS_MODULE, "cex4card");
	if (rc)
		return rc;

	rc = ap_driver_register(&zcrypt_cex4_queue_driver,
				THIS_MODULE, "cex4queue");
	if (rc)
		ap_driver_unregister(&zcrypt_cex4_card_driver);

	return rc;
306 307 308 309
}

void __exit zcrypt_cex4_exit(void)
{
310 311
	ap_driver_unregister(&zcrypt_cex4_queue_driver);
	ap_driver_unregister(&zcrypt_cex4_card_driver);
312 313 314 315
}

module_init(zcrypt_cex4_init);
module_exit(zcrypt_cex4_exit);