zcrypt_cex4.c 19.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
 *  Copyright IBM Corp. 2012, 2019
4 5 6 7 8 9 10 11 12
 *  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

#include "ap_bus.h"
#include "zcrypt_api.h"
#include "zcrypt_msgtype6.h"
#include "zcrypt_msgtype50.h"
#include "zcrypt_error.h"
#include "zcrypt_cex4.h"
21
#include "zcrypt_ccamisc.h"
22
#include "zcrypt_ep11misc.h"
23 24 25 26 27 28 29 30

#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	*/

31 32 33 34 35
/* 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.
 */
36
#define CEX4_CLEANUP_TIME	(900*HZ)
37 38

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

43 44 45 46 47
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 },
48 49
	{ .dev_type = AP_DEVICE_TYPE_CEX6,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
50 51
	{ .dev_type = AP_DEVICE_TYPE_CEX7,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
52 53 54 55
	{ /* end of list */ },
};

MODULE_DEVICE_TABLE(ap, zcrypt_cex4_card_ids);
56

57 58 59 60 61
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 },
62 63
	{ .dev_type = AP_DEVICE_TYPE_CEX6,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
64 65
	{ .dev_type = AP_DEVICE_TYPE_CEX7,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
66
	{ /* end of list */ },
67 68
};

69 70
MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids);

71
/*
72
 * CCA card additional device attributes
73
 */
74 75 76
static ssize_t cca_serialnr_show(struct device *dev,
				 struct device_attribute *attr,
				 char *buf)
77 78 79 80 81 82 83 84 85 86
{
	struct cca_info ci;
	struct ap_card *ac = to_ap_card(dev);
	struct zcrypt_card *zc = ac->private;

	memset(&ci, 0, sizeof(ci));

	if (ap_domain_index >= 0)
		cca_get_info(ac->id, ap_domain_index, &ci, zc->online);

87
	return scnprintf(buf, PAGE_SIZE, "%s\n", ci.serial);
88
}
89 90 91

static struct device_attribute dev_attr_cca_serialnr =
	__ATTR(serialnr, 0444, cca_serialnr_show, NULL);
92 93

static struct attribute *cca_card_attrs[] = {
94
	&dev_attr_cca_serialnr.attr,
95 96 97
	NULL,
};

98
static const struct attribute_group cca_card_attr_grp = {
99 100 101
	.attrs = cca_card_attrs,
};

102 103 104 105 106 107
 /*
  * CCA queue additional device attributes
  */
static ssize_t cca_mkvps_show(struct device *dev,
			      struct device_attribute *attr,
			      char *buf)
108 109 110 111 112 113 114 115 116 117 118 119 120
{
	int n = 0;
	struct cca_info ci;
	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
	static const char * const cao_state[] = { "invalid", "valid" };
	static const char * const new_state[] = { "empty", "partial", "full" };

	memset(&ci, 0, sizeof(ci));

	cca_get_info(AP_QID_CARD(zq->queue->qid),
		     AP_QID_QUEUE(zq->queue->qid),
		     &ci, zq->online);

121
	if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3')
122
		n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n",
123 124
			      new_state[ci.new_aes_mk_state - '1'],
			      ci.new_aes_mkvp);
125
	else
126
		n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n");
127

128
	if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2')
129 130
		n += scnprintf(buf + n, PAGE_SIZE - n,
			       "AES CUR: %s 0x%016llx\n",
131 132
			       cao_state[ci.cur_aes_mk_state - '1'],
			       ci.cur_aes_mkvp);
133
	else
134
		n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n");
135

136
	if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2')
137 138
		n += scnprintf(buf + n, PAGE_SIZE - n,
			       "AES OLD: %s 0x%016llx\n",
139 140
			       cao_state[ci.old_aes_mk_state - '1'],
			       ci.old_aes_mkvp);
141
	else
142
		n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n");
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3')
		n += scnprintf(buf + n, PAGE_SIZE - n,
			       "APKA NEW: %s 0x%016llx\n",
			       new_state[ci.new_apka_mk_state - '1'],
			       ci.new_apka_mkvp);
	else
		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n");

	if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2')
		n += scnprintf(buf + n, PAGE_SIZE - n,
			       "APKA CUR: %s 0x%016llx\n",
			       cao_state[ci.cur_apka_mk_state - '1'],
			       ci.cur_apka_mkvp);
	else
		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n");

	if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2')
		n += scnprintf(buf + n, PAGE_SIZE - n,
			       "APKA OLD: %s 0x%016llx\n",
			       cao_state[ci.old_apka_mk_state - '1'],
			       ci.old_apka_mkvp);
	else
		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n");

168 169
	return n;
}
170 171 172

static struct device_attribute dev_attr_cca_mkvps =
	__ATTR(mkvps, 0444, cca_mkvps_show, NULL);
173 174

static struct attribute *cca_queue_attrs[] = {
175
	&dev_attr_cca_mkvps.attr,
176 177 178
	NULL,
};

179
static const struct attribute_group cca_queue_attr_grp = {
180 181 182
	.attrs = cca_queue_attrs,
};

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
/*
 * EP11 card additional device attributes
 */
static ssize_t ep11_api_ordinalnr_show(struct device *dev,
				       struct device_attribute *attr,
				       char *buf)
{
	struct ep11_card_info ci;
	struct ap_card *ac = to_ap_card(dev);
	struct zcrypt_card *zc = ac->private;

	memset(&ci, 0, sizeof(ci));

	ep11_get_card_info(ac->id, &ci, zc->online);

	if (ci.API_ord_nr > 0)
199
		return scnprintf(buf, PAGE_SIZE, "%u\n", ci.API_ord_nr);
200
	else
201
		return scnprintf(buf, PAGE_SIZE, "\n");
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
}

static struct device_attribute dev_attr_ep11_api_ordinalnr =
	__ATTR(API_ordinalnr, 0444, ep11_api_ordinalnr_show, NULL);

static ssize_t ep11_fw_version_show(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{
	struct ep11_card_info ci;
	struct ap_card *ac = to_ap_card(dev);
	struct zcrypt_card *zc = ac->private;

	memset(&ci, 0, sizeof(ci));

	ep11_get_card_info(ac->id, &ci, zc->online);

	if (ci.FW_version > 0)
220 221 222
		return scnprintf(buf, PAGE_SIZE, "%d.%d\n",
				 (int)(ci.FW_version >> 8),
				 (int)(ci.FW_version & 0xFF));
223
	else
224
		return scnprintf(buf, PAGE_SIZE, "\n");
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
}

static struct device_attribute dev_attr_ep11_fw_version =
	__ATTR(FW_version, 0444, ep11_fw_version_show, NULL);

static ssize_t ep11_serialnr_show(struct device *dev,
				  struct device_attribute *attr,
				  char *buf)
{
	struct ep11_card_info ci;
	struct ap_card *ac = to_ap_card(dev);
	struct zcrypt_card *zc = ac->private;

	memset(&ci, 0, sizeof(ci));

	ep11_get_card_info(ac->id, &ci, zc->online);

	if (ci.serial[0])
243
		return scnprintf(buf, PAGE_SIZE, "%16.16s\n", ci.serial);
244
	else
245
		return scnprintf(buf, PAGE_SIZE, "\n");
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}

static struct device_attribute dev_attr_ep11_serialnr =
	__ATTR(serialnr, 0444, ep11_serialnr_show, NULL);

static const struct {
	int	    mode_bit;
	const char *mode_txt;
} ep11_op_modes[] = {
	{ 0, "FIPS2009" },
	{ 1, "BSI2009" },
	{ 2, "FIPS2011" },
	{ 3, "BSI2011" },
	{ 6, "BSICC2017" },
	{ 0, NULL }
};

static ssize_t ep11_card_op_modes_show(struct device *dev,
				       struct device_attribute *attr,
				       char *buf)
{
	int i, n = 0;
	struct ep11_card_info ci;
	struct ap_card *ac = to_ap_card(dev);
	struct zcrypt_card *zc = ac->private;

	memset(&ci, 0, sizeof(ci));

	ep11_get_card_info(ac->id, &ci, zc->online);

	for (i = 0; ep11_op_modes[i].mode_txt; i++) {
277
		if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
278 279
			if (n > 0)
				buf[n++] = ' ';
280 281
			n += scnprintf(buf + n, PAGE_SIZE - n,
				       "%s", ep11_op_modes[i].mode_txt);
282 283
		}
	}
284
	n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326

	return n;
}

static struct device_attribute dev_attr_ep11_card_op_modes =
	__ATTR(op_modes, 0444, ep11_card_op_modes_show, NULL);

static struct attribute *ep11_card_attrs[] = {
	&dev_attr_ep11_api_ordinalnr.attr,
	&dev_attr_ep11_fw_version.attr,
	&dev_attr_ep11_serialnr.attr,
	&dev_attr_ep11_card_op_modes.attr,
	NULL,
};

static const struct attribute_group ep11_card_attr_grp = {
	.attrs = ep11_card_attrs,
};

/*
 * EP11 queue additional device attributes
 */

static ssize_t ep11_mkvps_show(struct device *dev,
			       struct device_attribute *attr,
			       char *buf)
{
	int n = 0;
	struct ep11_domain_info di;
	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
	static const char * const cwk_state[] = { "invalid", "valid" };
	static const char * const nwk_state[] = { "empty", "uncommitted",
						  "committed" };

	memset(&di, 0, sizeof(di));

	if (zq->online)
		ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
				     AP_QID_QUEUE(zq->queue->qid),
				     &di);

	if (di.cur_wk_state == '0') {
327 328
		n = scnprintf(buf, PAGE_SIZE, "WK CUR: %s -\n",
			      cwk_state[di.cur_wk_state - '0']);
329
	} else if (di.cur_wk_state == '1') {
330 331
		n = scnprintf(buf, PAGE_SIZE, "WK CUR: %s 0x",
			      cwk_state[di.cur_wk_state - '0']);
332 333
		bin2hex(buf + n, di.cur_wkvp, sizeof(di.cur_wkvp));
		n += 2 * sizeof(di.cur_wkvp);
334
		n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
335
	} else
336
		n = scnprintf(buf, PAGE_SIZE, "WK CUR: - -\n");
337 338

	if (di.new_wk_state == '0') {
339 340
		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s -\n",
			       nwk_state[di.new_wk_state - '0']);
341
	} else if (di.new_wk_state >= '1' && di.new_wk_state <= '2') {
342 343
		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s 0x",
			       nwk_state[di.new_wk_state - '0']);
344 345
		bin2hex(buf + n, di.new_wkvp, sizeof(di.new_wkvp));
		n += 2 * sizeof(di.new_wkvp);
346
		n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
347
	} else
348
		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: - -\n");
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

	return n;
}

static struct device_attribute dev_attr_ep11_mkvps =
	__ATTR(mkvps, 0444, ep11_mkvps_show, NULL);

static ssize_t ep11_queue_op_modes_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	int i, n = 0;
	struct ep11_domain_info di;
	struct zcrypt_queue *zq = to_ap_queue(dev)->private;

	memset(&di, 0, sizeof(di));

	if (zq->online)
		ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
				     AP_QID_QUEUE(zq->queue->qid),
				     &di);

	for (i = 0; ep11_op_modes[i].mode_txt; i++) {
372
		if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
373 374
			if (n > 0)
				buf[n++] = ' ';
375 376
			n += scnprintf(buf + n, PAGE_SIZE - n,
				       "%s", ep11_op_modes[i].mode_txt);
377 378
		}
	}
379
	n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396

	return n;
}

static struct device_attribute dev_attr_ep11_queue_op_modes =
	__ATTR(op_modes, 0444, ep11_queue_op_modes_show, NULL);

static struct attribute *ep11_queue_attrs[] = {
	&dev_attr_ep11_mkvps.attr,
	&dev_attr_ep11_queue_op_modes.attr,
	NULL,
};

static const struct attribute_group ep11_queue_attr_grp = {
	.attrs = ep11_queue_attrs,
};

397
/**
398
 * Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always
399 400
 * accepts the AP device since the bus_match already checked
 * the hardware type.
401 402
 * @ap_dev: pointer to the AP device.
 */
403
static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
404
{
405 406 407 408
	/*
	 * Normalized speed ratings per crypto adapter
	 * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
	 */
409
	static const int CEX4A_SPEED_IDX[NUM_OPS] = {
410
		 14,  19, 249, 42, 228, 1458, 0, 0};
411
	static const int CEX5A_SPEED_IDX[NUM_OPS] = {
412
		  8,   9,  20, 18,  66,	 458, 0, 0};
413
	static const int CEX6A_SPEED_IDX[NUM_OPS] = {
414
		  6,   9,  20, 17,  65,	 438, 0, 0};
415
	static const int CEX7A_SPEED_IDX[NUM_OPS] = {
416
		  6,   8,  17, 15,  54,	 362, 0, 0};
417

418
	static const int CEX4C_SPEED_IDX[NUM_OPS] = {
419
		 59,  69, 308, 83, 278, 2204, 209, 40};
420
	static const int CEX5C_SPEED_IDX[] = {
421
		 24,  31,  50, 37,  90,	 479,  27, 10};
422
	static const int CEX6C_SPEED_IDX[NUM_OPS] = {
423
		 16,  20,  32, 27,  77,	 455,  24,  9};
424
	static const int CEX7C_SPEED_IDX[NUM_OPS] = {
425
		 14,  16,  26, 23,  64,	 376,  23,  8};
426

427
	static const int CEX4P_SPEED_IDX[NUM_OPS] = {
428
		  0,   0,   0,	 0,   0,   0,	0,  50};
429
	static const int CEX5P_SPEED_IDX[NUM_OPS] = {
430
		  0,   0,   0,	 0,   0,   0,	0,  10};
431
	static const int CEX6P_SPEED_IDX[NUM_OPS] = {
432
		  0,   0,   0,	 0,   0,   0,	0,   9};
433
	static const int CEX7P_SPEED_IDX[NUM_OPS] = {
434
		  0,   0,   0,	 0,   0,   0,	0,   8};
435 436 437

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

440 441 442 443 444 445 446 447 448
	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;
449
			zc->speed_rating = CEX4A_SPEED_IDX;
450
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
451 452
			zc->type_string = "CEX5A";
			zc->user_space_type = ZCRYPT_CEX5;
453
			zc->speed_rating = CEX5A_SPEED_IDX;
454
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
455 456
			zc->type_string = "CEX6A";
			zc->user_space_type = ZCRYPT_CEX6;
457
			zc->speed_rating = CEX6A_SPEED_IDX;
458 459 460 461 462 463
		} else {
			zc->type_string = "CEX7A";
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
464
			zc->speed_rating = CEX7A_SPEED_IDX;
465
		}
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
		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;
484
			zc->speed_rating = CEX4C_SPEED_IDX;
485
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
486 487 488 489 490
			zc->type_string = "CEX5C";
			/* wrong user space type, must be CEX5
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
491
			zc->speed_rating = CEX5C_SPEED_IDX;
492
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
493 494 495 496 497
			zc->type_string = "CEX6C";
			/* wrong user space type, must be CEX6
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
498
			zc->speed_rating = CEX6C_SPEED_IDX;
499 500 501 502 503 504
		} else {
			zc->type_string = "CEX7C";
			/* wrong user space type, must be CEX7
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
505
			zc->speed_rating = CEX7C_SPEED_IDX;
506 507 508 509 510 511 512 513
		}
		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;
514
			zc->speed_rating = CEX4P_SPEED_IDX;
515
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
516 517
			zc->type_string = "CEX5P";
			zc->user_space_type = ZCRYPT_CEX5;
518
			zc->speed_rating = CEX5P_SPEED_IDX;
519
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
520 521
			zc->type_string = "CEX6P";
			zc->user_space_type = ZCRYPT_CEX6;
522
			zc->speed_rating = CEX6P_SPEED_IDX;
523 524 525 526 527 528
		} else {
			zc->type_string = "CEX7P";
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
529
			zc->speed_rating = CEX7P_SPEED_IDX;
530 531 532 533 534 535
		}
		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);
536
		return -ENODEV;
537 538 539 540
	}
	zc->online = 1;

	rc = zcrypt_card_register(zc);
541
	if (rc) {
542 543
		ac->private = NULL;
		zcrypt_card_free(zc);
544
		return rc;
545
	}
546

547 548
	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
		rc = sysfs_create_group(&ap_dev->device.kobj,
549
					&cca_card_attr_grp);
550
		if (rc) {
551
			zcrypt_card_unregister(zc);
552 553 554
			ac->private = NULL;
			zcrypt_card_free(zc);
		}
555 556 557
	} else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
		rc = sysfs_create_group(&ap_dev->device.kobj,
					&ep11_card_attr_grp);
558
		if (rc) {
559
			zcrypt_card_unregister(zc);
560 561 562
			ac->private = NULL;
			zcrypt_card_free(zc);
		}
563 564
	}

565 566 567 568
	return rc;
}

/**
569 570
 * This is called to remove the CEX4/CEX5/CEX6/CEX7 card driver
 * information if an AP card device is removed.
571
 */
572
static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
573
{
574 575
	struct ap_card *ac = to_ap_card(&ap_dev->device);
	struct zcrypt_card *zc = ac->private;
576

577
	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
578 579 580
		sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp);
	else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
		sysfs_remove_group(&ap_dev->device.kobj, &ep11_card_attr_grp);
581 582 583 584 585 586 587 588
	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,
589
	.flags = AP_DRIVER_FLAG_DEFAULT,
590 591 592
};

/**
593
 * Probe function for CEX4/CEX5/CEX6/CEX7 queue device. It always
594 595
 * accepts the AP device since the bus_match already checked
 * the hardware type.
596 597 598 599 600 601 602 603 604
 * @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)) {
605
		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
606 607 608 609 610
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
					 MSGTYPE50_VARIANT_DEFAULT);
	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
611
		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
612 613 614 615 616
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_DEFAULT);
	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
617
		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
618 619 620 621 622 623
		if (!zq)
			return -ENOMEM;
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_EP11);
	} else {
		return -ENODEV;
624
	}
625

626 627 628
	zq->queue = aq;
	zq->online = 1;
	atomic_set(&zq->load, 0);
629
	ap_queue_init_state(aq);
630
	ap_queue_init_reply(aq, &zq->reply);
631
	aq->request_timeout = CEX4_CLEANUP_TIME;
632 633 634 635 636
	aq->private = zq;
	rc = zcrypt_queue_register(zq);
	if (rc) {
		aq->private = NULL;
		zcrypt_queue_free(zq);
637
		return rc;
638 639 640 641
	}

	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
		rc = sysfs_create_group(&ap_dev->device.kobj,
642
					&cca_queue_attr_grp);
643
		if (rc) {
644
			zcrypt_queue_unregister(zq);
645 646 647
			aq->private = NULL;
			zcrypt_queue_free(zq);
		}
648 649 650
	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
		rc = sysfs_create_group(&ap_dev->device.kobj,
					&ep11_queue_attr_grp);
651
		if (rc) {
652
			zcrypt_queue_unregister(zq);
653 654 655
			aq->private = NULL;
			zcrypt_queue_free(zq);
		}
656 657 658
	}

	return rc;
659 660
}

661
/**
662
 * This is called to remove the CEX4/CEX5/CEX6/CEX7 queue driver
663
 * information if an AP queue device is removed.
664 665 666 667 668 669
 */
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;

670
	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
671 672 673
		sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp);
	else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
		sysfs_remove_group(&ap_dev->device.kobj, &ep11_queue_attr_grp);
674 675 676 677 678 679 680 681
	if (zq)
		zcrypt_queue_unregister(zq);
}

static struct ap_driver zcrypt_cex4_queue_driver = {
	.probe = zcrypt_cex4_queue_probe,
	.remove = zcrypt_cex4_queue_remove,
	.ids = zcrypt_cex4_queue_ids,
682
	.flags = AP_DRIVER_FLAG_DEFAULT,
683 684
};

685 686
int __init zcrypt_cex4_init(void)
{
687 688 689 690 691 692 693 694 695 696 697 698 699
	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;
700 701 702 703
}

void __exit zcrypt_cex4_exit(void)
{
704 705
	ap_driver_unregister(&zcrypt_cex4_queue_driver);
	ap_driver_unregister(&zcrypt_cex4_card_driver);
706 707 708 709
}

module_init(zcrypt_cex4_init);
module_exit(zcrypt_cex4_exit);