Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34a15167 authored by Ingo Tuchscherer's avatar Ingo Tuchscherer Committed by Martin Schwidefsky
Browse files

s390/zcrypt: Introduce workload balancing



Crypto requests are very different in complexity and thus runtime.
Also various crypto adapters are differ with regard to the execution
time. Crypto requests can be balanced much better when the request
type and eligible crypto adapters are rated in a more precise
granularity. Therefore, request weights and adapter speed rates for
dedicated requests will be introduced.

Signed-off-by: default avatarIngo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 9af3e04e
Loading
Loading
Loading
Loading
+204 −104
Original line number Diff line number Diff line
@@ -151,18 +151,16 @@ static inline int zcrypt_process_rescan(void)
 * Need to be called while holding the zcrypt device list lock.
 * Note: cards with speed_rating of 0 are kept at the end of the list.
 */
static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
static void __zcrypt_increase_preference(struct zcrypt_device *zdev,
				  unsigned int weight)
{
	struct zcrypt_device *tmp;
	struct list_head *l;

	if (zdev->speed_rating == 0)
		return;
	zdev->load -= weight;
	for (l = zdev->list.prev; l != &zcrypt_device_list; l = l->prev) {
		tmp = list_entry(l, struct zcrypt_device, list);
		if ((tmp->request_count + 1) * tmp->speed_rating <=
		    (zdev->request_count + 1) * zdev->speed_rating &&
		    tmp->speed_rating != 0)
		if (tmp->load <= zdev->load)
			break;
	}
	if (l == zdev->list.prev)
@@ -179,18 +177,16 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
 * Need to be called while holding the zcrypt device list lock.
 * Note: cards with speed_rating of 0 are kept at the end of the list.
 */
static void __zcrypt_decrease_preference(struct zcrypt_device *zdev)
static void __zcrypt_decrease_preference(struct zcrypt_device *zdev,
				  unsigned int weight)
{
	struct zcrypt_device *tmp;
	struct list_head *l;

	if (zdev->speed_rating == 0)
		return;
	zdev->load += weight;
	for (l = zdev->list.next; l != &zcrypt_device_list; l = l->next) {
		tmp = list_entry(l, struct zcrypt_device, list);
		if ((tmp->request_count + 1) * tmp->speed_rating >
		    (zdev->request_count + 1) * zdev->speed_rating ||
		    tmp->speed_rating == 0)
		if (tmp->load > zdev->load)
			break;
	}
	if (l == zdev->list.next)
@@ -270,7 +266,7 @@ int zcrypt_device_register(struct zcrypt_device *zdev)
	ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dreg", zdev->ap_dev->qid,
		       zdev->online);
	list_add_tail(&zdev->list, &zcrypt_device_list);
	__zcrypt_increase_preference(zdev);
	__zcrypt_increase_preference(zdev, 0); /* sort devices acc. weight */
	zcrypt_device_count++;
	spin_unlock_bh(&zcrypt_device_lock);
	if (zdev->ops->rng) {
@@ -386,8 +382,9 @@ static int zcrypt_release(struct inode *inode, struct file *filp)
 */
static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
{
	struct zcrypt_device *zdev;
	struct zcrypt_device *zdev, *pref_zdev = NULL;
	int rc;
	unsigned int weight, func_code, pref_weight = 0;

	if (mex->outputdatalength < mex->inputdatalength)
		return -EINVAL;
@@ -398,6 +395,10 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
	 */
	mex->outputdatalength = mex->inputdatalength;

	rc = get_rsa_modex_fc(mex, &func_code);
	if (rc)
		return rc;

	spin_lock_bh(&zcrypt_device_lock);
	list_for_each_entry(zdev, &zcrypt_device_list, list) {
		if (!zdev->online ||
@@ -405,34 +406,52 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
		    zdev->min_mod_size > mex->inputdatalength ||
		    zdev->max_mod_size < mex->inputdatalength)
			continue;
		zcrypt_device_get(zdev);
		get_device(&zdev->ap_dev->device);
		zdev->request_count++;
		__zcrypt_decrease_preference(zdev);
		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
		weight = zdev->speed_rating[func_code];
		if (!pref_zdev) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) > (zdev->load + weight)) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) <= zdev->load)
			break; /* Load on remaining devices too high - abort */
	}

	if (!pref_zdev) {
		spin_unlock_bh(&zcrypt_device_lock);
			rc = zdev->ops->rsa_modexpo(zdev, mex);
			spin_lock_bh(&zcrypt_device_lock);
			module_put(zdev->ap_dev->drv->driver.owner);
		return -ENODEV;
	}
		else
	__zcrypt_decrease_preference(pref_zdev, pref_weight);
	zcrypt_device_get(pref_zdev);
	get_device(&pref_zdev->ap_dev->device);
	pref_zdev->request_count++;
	if (try_module_get(pref_zdev->ap_dev->drv->driver.owner)) {
		spin_unlock_bh(&zcrypt_device_lock);
		rc = -ENODEV;
		rc = pref_zdev->ops->rsa_modexpo(pref_zdev, mex);
		spin_lock_bh(&zcrypt_device_lock);
		module_put(pref_zdev->ap_dev->drv->driver.owner);
	} else
		rc = -EAGAIN;
		zdev->request_count--;
		__zcrypt_increase_preference(zdev);
		put_device(&zdev->ap_dev->device);
		zcrypt_device_put(zdev);

	pref_zdev->request_count--;
	__zcrypt_increase_preference(pref_zdev, pref_weight);
	put_device(&pref_zdev->ap_dev->device);
	zcrypt_device_put(pref_zdev);
	spin_unlock_bh(&zcrypt_device_lock);
	return rc;
}
	spin_unlock_bh(&zcrypt_device_lock);
	return -ENODEV;
}

static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
{
	struct zcrypt_device *zdev;
	struct zcrypt_device *zdev, *pref_zdev = NULL;
	unsigned long long z1, z2, z3;
	int rc, copied;
	unsigned int weight, func_code, pref_weight = 0;

	if (crt->outputdatalength < crt->inputdatalength)
		return -EINVAL;
@@ -443,6 +462,10 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
	 */
	crt->outputdatalength = crt->inputdatalength;

	rc = get_rsa_crt_fc(crt, &func_code);
	if (rc)
		return rc;

	copied = 0;
 restart:
	spin_lock_bh(&zcrypt_device_lock);
@@ -489,33 +512,54 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
				/* The device can't handle this request. */
				continue;
		}
		zcrypt_device_get(zdev);
		get_device(&zdev->ap_dev->device);
		zdev->request_count++;
		__zcrypt_decrease_preference(zdev);
		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {

		weight = zdev->speed_rating[func_code];
		if (!pref_zdev) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) > (zdev->load + weight)) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) <= zdev->load)
			break; /* Load on remaining devices too high - abort */
	}
	if (!pref_zdev) {
		spin_unlock_bh(&zcrypt_device_lock);
			rc = zdev->ops->rsa_modexpo_crt(zdev, crt);
			spin_lock_bh(&zcrypt_device_lock);
			module_put(zdev->ap_dev->drv->driver.owner);
		return -ENODEV;
	}
		else
	__zcrypt_decrease_preference(pref_zdev, pref_weight);
	zcrypt_device_get(pref_zdev);
	get_device(&pref_zdev->ap_dev->device);
	pref_zdev->request_count++;
	if (try_module_get(pref_zdev->ap_dev->drv->driver.owner)) {
		spin_unlock_bh(&zcrypt_device_lock);
		rc = pref_zdev->ops->rsa_modexpo_crt(pref_zdev, crt);
		spin_lock_bh(&zcrypt_device_lock);
		module_put(pref_zdev->ap_dev->drv->driver.owner);
	} else
		rc = -EAGAIN;
		zdev->request_count--;
		__zcrypt_increase_preference(zdev);
		put_device(&zdev->ap_dev->device);
		zcrypt_device_put(zdev);
	pref_zdev->request_count--;
	__zcrypt_increase_preference(pref_zdev, pref_weight);
	put_device(&pref_zdev->ap_dev->device);
	zcrypt_device_put(pref_zdev);
	spin_unlock_bh(&zcrypt_device_lock);
	return rc;
}
	spin_unlock_bh(&zcrypt_device_lock);
	return -ENODEV;
}

static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
{
	struct zcrypt_device *zdev;
	struct zcrypt_device *zdev, *pref_zdev = NULL;
	unsigned int weight = 0, func_code = 0, pref_weight = 0;
	int rc;
	struct ap_message ap_msg;

	rc = get_cprb_fc(xcRB, &ap_msg, &func_code);
	if (rc)
		return rc;

	spin_lock_bh(&zcrypt_device_lock);
	list_for_each_entry(zdev, &zcrypt_device_list, list) {
@@ -524,28 +568,43 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
		   (xcRB->user_defined != AUTOSELECT &&
		    AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined))
			continue;
		zcrypt_device_get(zdev);
		get_device(&zdev->ap_dev->device);
		zdev->request_count++;
		__zcrypt_decrease_preference(zdev);
		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {

		weight = speed_idx_cca(func_code) * zdev->speed_rating[SECKEY];
		if (!pref_zdev) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) > (zdev->load + weight)) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) <= zdev->load)
			break; /* Load on remaining devices too high - abort */
	}
	if (!pref_zdev) {
		spin_unlock_bh(&zcrypt_device_lock);
			rc = zdev->ops->send_cprb(zdev, xcRB);
			spin_lock_bh(&zcrypt_device_lock);
			module_put(zdev->ap_dev->drv->driver.owner);
		return -ENODEV;
	}
		else
	__zcrypt_decrease_preference(pref_zdev, pref_weight);
	zcrypt_device_get(pref_zdev);
	get_device(&pref_zdev->ap_dev->device);
	pref_zdev->request_count++;
	if (try_module_get(pref_zdev->ap_dev->drv->driver.owner)) {
		spin_unlock_bh(&zcrypt_device_lock);
		rc = pref_zdev->ops->send_cprb(pref_zdev, xcRB, &ap_msg);
		spin_lock_bh(&zcrypt_device_lock);
		module_put(pref_zdev->ap_dev->drv->driver.owner);
	} else
		rc = -EAGAIN;
		zdev->request_count--;
		__zcrypt_increase_preference(zdev);
		put_device(&zdev->ap_dev->device);
		zcrypt_device_put(zdev);
	pref_zdev->request_count--;
	__zcrypt_increase_preference(pref_zdev, pref_weight);
	put_device(&pref_zdev->ap_dev->device);
	zcrypt_device_put(pref_zdev);
	spin_unlock_bh(&zcrypt_device_lock);
	return rc;
}
	spin_unlock_bh(&zcrypt_device_lock);
	return -ENODEV;
}

struct ep11_target_dev_list {
	unsigned short		targets_num;
@@ -568,7 +627,9 @@ static bool is_desired_ep11dev(unsigned int dev_qid,

static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
{
	struct zcrypt_device *zdev;
	struct zcrypt_device *zdev, *pref_zdev = NULL;
	struct ap_message ap_msg;
	unsigned int weight = 0, func_code = 0, pref_weight = 0;
	bool autoselect = false;
	int rc;
	struct ep11_target_dev_list ep11_dev_list = {
@@ -596,6 +657,10 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
			return -EFAULT;
	}

	rc = get_ep11cprb_fc(xcrb, &ap_msg, &func_code);
	if (rc)
		return rc;

	spin_lock_bh(&zcrypt_device_lock);
	list_for_each_entry(zdev, &zcrypt_device_list, list) {
		/* check if device is eligible */
@@ -608,59 +673,94 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
		    !autoselect)
			continue;

		zcrypt_device_get(zdev);
		get_device(&zdev->ap_dev->device);
		zdev->request_count++;
		__zcrypt_decrease_preference(zdev);
		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
		weight = speed_idx_ep11(func_code) * zdev->speed_rating[SECKEY];
		if (!pref_zdev) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) > (zdev->load + weight)) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) <= zdev->load)
			break; /* Load on remaining devices too high - abort */
	}
	if (!pref_zdev) {
		spin_unlock_bh(&zcrypt_device_lock);
		return -ENODEV;
	}

	zcrypt_device_get(pref_zdev);
	get_device(&pref_zdev->ap_dev->device);
	pref_zdev->request_count++;
	if (try_module_get(pref_zdev->ap_dev->drv->driver.owner)) {
		spin_unlock_bh(&zcrypt_device_lock);
			rc = zdev->ops->send_ep11_cprb(zdev, xcrb);
		rc = pref_zdev->ops->send_ep11_cprb(pref_zdev, xcrb, &ap_msg);
		spin_lock_bh(&zcrypt_device_lock);
			module_put(zdev->ap_dev->drv->driver.owner);
		module_put(pref_zdev->ap_dev->drv->driver.owner);
	} else {
		rc = -EAGAIN;
	}
		zdev->request_count--;
		__zcrypt_increase_preference(zdev);
		put_device(&zdev->ap_dev->device);
		zcrypt_device_put(zdev);
	pref_zdev->request_count--;
	put_device(&pref_zdev->ap_dev->device);
	zcrypt_device_put(pref_zdev);
	spin_unlock_bh(&zcrypt_device_lock);
	return rc;
}
	spin_unlock_bh(&zcrypt_device_lock);
	return -ENODEV;
}

static long zcrypt_rng(char *buffer)
{
	struct zcrypt_device *zdev;
	struct zcrypt_device *zdev, *pref_zdev = NULL;
	struct ap_message ap_msg;
	unsigned int weight = 0, func_code = 0, pref_weight = 0;
	int rc;

	rc = get_rng_fc(&ap_msg, &func_code);
	if (rc)
		return rc;

	spin_lock_bh(&zcrypt_device_lock);
	list_for_each_entry(zdev, &zcrypt_device_list, list) {
		if (!zdev->online || !zdev->ops->rng)
			continue;
		zcrypt_device_get(zdev);
		get_device(&zdev->ap_dev->device);
		zdev->request_count++;
		__zcrypt_decrease_preference(zdev);
		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {

		weight = zdev->speed_rating[func_code];
		if (!pref_zdev) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) > (zdev->load + weight)) {
			pref_zdev = zdev;
			pref_weight = weight;
			continue;
		}
		if ((pref_zdev->load + pref_weight) <= zdev->load)
			break; /* Load on remaining devices too high - abort */
	}
	if (!pref_zdev) {
		spin_unlock_bh(&zcrypt_device_lock);
			rc = zdev->ops->rng(zdev, buffer);
		return -ENODEV;
	}

	zcrypt_device_get(pref_zdev);
	get_device(&pref_zdev->ap_dev->device);
	pref_zdev->request_count++;
	if (try_module_get(pref_zdev->ap_dev->drv->driver.owner)) {
		spin_unlock_bh(&zcrypt_device_lock);
		rc = pref_zdev->ops->rng(pref_zdev, buffer, &ap_msg);
		spin_lock_bh(&zcrypt_device_lock);
			module_put(zdev->ap_dev->drv->driver.owner);
		module_put(pref_zdev->ap_dev->drv->driver.owner);
	} else
		rc = -EAGAIN;
		zdev->request_count--;
		__zcrypt_increase_preference(zdev);
		put_device(&zdev->ap_dev->device);
		zcrypt_device_put(zdev);
	pref_zdev->request_count--;
	put_device(&pref_zdev->ap_dev->device);
	zcrypt_device_put(pref_zdev);
	spin_unlock_bh(&zcrypt_device_lock);
	return rc;
}
	spin_unlock_bh(&zcrypt_device_lock);
	return -ENODEV;
}

static void zcrypt_status_mask(char status[AP_DEVICES])
{
+22 −4
Original line number Diff line number Diff line
@@ -84,15 +84,32 @@ struct ica_z90_status {
 */
#define ZCRYPT_RNG_BUFFER_SIZE	4096

/*
 * Identifier for Crypto Request Performance Index
 */
enum crypto_ops {
	MEX_1K = 0,
	MEX_2K,
	MEX_4K,
	CRT_1K,
	CRT_2K,
	CRT_4K,
	HWRNG,
	SECKEY,
	NUM_OPS
};

struct zcrypt_device;

struct zcrypt_ops {
	long (*rsa_modexpo)(struct zcrypt_device *, struct ica_rsa_modexpo *);
	long (*rsa_modexpo_crt)(struct zcrypt_device *,
				struct ica_rsa_modexpo_crt *);
	long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
	long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *);
	long (*rng)(struct zcrypt_device *, char *);
	long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *,
			  struct ap_message *);
	long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *,
			       struct ap_message *);
	long (*rng)(struct zcrypt_device *, char *, struct ap_message *);
	struct list_head list;		/* zcrypt ops list. */
	struct module *owner;
	int variant;
@@ -112,7 +129,8 @@ struct zcrypt_device {
	int min_mod_size;		/* Min number of bits. */
	int max_mod_size;		/* Max number of bits. */
	int short_crt;			/* Card has crt length restriction. */
	int speed_rating;		/* Speed of the crypto device. */
	int speed_rating[NUM_OPS];	/* Speed idx of crypto ops. */
	int load;			/* Utilization of the crypto device */

	int request_count;		/* # current requests. */

+7 −5
Original line number Diff line number Diff line
@@ -43,9 +43,6 @@
#define CEX3A_MIN_MOD_SIZE	CEX2A_MIN_MOD_SIZE
#define CEX3A_MAX_MOD_SIZE	512	/* 4096 bits	*/

#define CEX2A_SPEED_RATING	970
#define CEX3A_SPEED_RATING	900 /* Fixme: Needs finetuning */

#define CEX2A_MAX_MESSAGE_SIZE	0x390	/* sizeof(struct type50_crb2_msg)    */
#define CEX2A_MAX_RESPONSE_SIZE 0x110	/* max outputdatalength + type80_hdr */

@@ -87,6 +84,8 @@ static struct ap_driver zcrypt_cex2a_driver = {
static int zcrypt_cex2a_probe(struct ap_device *ap_dev)
{
	struct zcrypt_device *zdev = NULL;
	int CEX2A_SPEED_IDX[] = { 800, 1000, 2000,  900, 1200, 2400, 0};
	int CEX3A_SPEED_IDX[] = { 400,	500, 1000,  450,  550, 1200, 0};
	int rc = 0;

	switch (ap_dev->device_type) {
@@ -99,7 +98,8 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev)
		zdev->min_mod_size = CEX2A_MIN_MOD_SIZE;
		zdev->max_mod_size = CEX2A_MAX_MOD_SIZE;
		zdev->short_crt = 1;
		zdev->speed_rating = CEX2A_SPEED_RATING;
		memcpy(zdev->speed_rating, CEX2A_SPEED_IDX,
		       sizeof(CEX2A_SPEED_IDX));
		zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE;
		break;
	case AP_DEVICE_TYPE_CEX3A:
@@ -117,7 +117,8 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev)
			zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE;
		}
		zdev->short_crt = 1;
		zdev->speed_rating = CEX3A_SPEED_RATING;
		memcpy(zdev->speed_rating, CEX3A_SPEED_IDX,
		       sizeof(CEX3A_SPEED_IDX));
		break;
	}
	if (!zdev)
@@ -125,6 +126,7 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev)
	zdev->ops = zcrypt_msgtype(MSGTYPE50_NAME, MSGTYPE50_VARIANT_DEFAULT);
	zdev->ap_dev = ap_dev;
	zdev->online = 1;
	zdev->load = zdev->speed_rating[0];
	ap_device_init_reply(ap_dev, &zdev->reply);
	ap_dev->private = zdev;
	rc = zcrypt_device_register(zdev);
+23 −13
Original line number Diff line number Diff line
@@ -24,13 +24,6 @@
#define CEX4C_MIN_MOD_SIZE	 16	/*  256 bits	*/
#define CEX4C_MAX_MOD_SIZE	512	/* 4096 bits	*/

#define CEX4A_SPEED_RATING	900	 /* TODO new card, new speed rating */
#define CEX4C_SPEED_RATING	6500	 /* TODO new card, new speed rating */
#define CEX4P_SPEED_RATING	7000	 /* TODO new card, new speed rating */
#define CEX5A_SPEED_RATING	450	 /* TODO new card, new speed rating */
#define CEX5C_SPEED_RATING	3250	 /* TODO new card, new speed rating */
#define CEX5P_SPEED_RATING	3500	 /* TODO new card, new speed rating */

#define CEX4A_MAX_MESSAGE_SIZE	MSGTYPE50_CRB3_MAX_MSG_SIZE
#define CEX4C_MAX_MESSAGE_SIZE	MSGTYPE06_MAX_MSG_SIZE

@@ -71,6 +64,16 @@ static struct ap_driver zcrypt_cex4_driver = {
static int zcrypt_cex4_probe(struct ap_device *ap_dev)
{
	struct zcrypt_device *zdev = NULL;
	/*
	 * Normalized speed ratings per crypto adapter
	 * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
	 */
	int CEX4A_SPEED_IDX[] = {  5,  6,    59,  20, 115,  581,  0,  0};
	int CEX5A_SPEED_IDX[] = {  3,  3,     6,   8,  32,  218,  0,  0};
	int CEX4C_SPEED_IDX[] = { 24,  25,   82,  41, 138, 1111, 79,  8};
	int CEX5C_SPEED_IDX[] = { 10,  14,   23,  17,  45,  242, 63,  4};
	int CEX4P_SPEED_IDX[] = {142, 198, 1852, 203, 331, 1563,  0,  8};
	int CEX5P_SPEED_IDX[] = { 49,  67,  131,  52,  85,  287,  0,  4};
	int rc = 0;

	switch (ap_dev->device_type) {
@@ -82,10 +85,12 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
				return -ENOMEM;
			if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) {
				zdev->type_string = "CEX4A";
				zdev->speed_rating = CEX4A_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX4A_SPEED_IDX,
				       sizeof(CEX4A_SPEED_IDX));
			} else {
				zdev->type_string = "CEX5A";
				zdev->speed_rating = CEX5A_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX5A_SPEED_IDX,
				       sizeof(CEX5A_SPEED_IDX));
			}
			zdev->user_space_type = ZCRYPT_CEX3A;
			zdev->min_mod_size = CEX4A_MIN_MOD_SIZE;
@@ -110,10 +115,12 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
				return -ENOMEM;
			if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) {
				zdev->type_string = "CEX4C";
				zdev->speed_rating = CEX4C_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX4C_SPEED_IDX,
				       sizeof(CEX4C_SPEED_IDX));
			} else {
				zdev->type_string = "CEX5C";
				zdev->speed_rating = CEX5C_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX5C_SPEED_IDX,
				       sizeof(CEX5C_SPEED_IDX));
			}
			zdev->user_space_type = ZCRYPT_CEX3C;
			zdev->min_mod_size = CEX4C_MIN_MOD_SIZE;
@@ -128,10 +135,12 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
				return -ENOMEM;
			if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) {
				zdev->type_string = "CEX4P";
				zdev->speed_rating = CEX4P_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX4P_SPEED_IDX,
				       sizeof(CEX4P_SPEED_IDX));
			} else {
				zdev->type_string = "CEX5P";
				zdev->speed_rating = CEX5P_SPEED_RATING;
				memcpy(zdev->speed_rating, CEX5P_SPEED_IDX,
				       sizeof(CEX5P_SPEED_IDX));
			}
			zdev->user_space_type = ZCRYPT_CEX4;
			zdev->min_mod_size = CEX4C_MIN_MOD_SIZE;
@@ -147,6 +156,7 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
		return -ENODEV;
	zdev->ap_dev = ap_dev;
	zdev->online = 1;
	zdev->load = zdev->speed_rating[0];
	ap_device_init_reply(ap_dev, &zdev->reply);
	ap_dev->private = zdev;
	rc = zcrypt_device_register(zdev);
+32 −0
Original line number Diff line number Diff line
@@ -173,6 +173,38 @@ struct type80_hdr {
	unsigned char	reserved3[8];
} __packed;

unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fcode)
{

	if (!mex->inputdatalength)
		return -EINVAL;

	if (mex->inputdatalength <= 128)	/* 1024 bit */
		*fcode = MEX_1K;
	else if (mex->inputdatalength <= 256)	/* 2048 bit */
		*fcode = MEX_2K;
	else					/* 4096 bit */
		*fcode = MEX_4K;

	return 0;
}

unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fcode)
{

	if (!crt->inputdatalength)
		return -EINVAL;

	if (crt->inputdatalength <= 128)	/* 1024 bit */
		*fcode = CRT_1K;
	else if (crt->inputdatalength <= 256)	/* 2048 bit */
		*fcode = CRT_2K;
	else					/* 4096 bit */
		*fcode = CRT_4K;

	return 0;
}

/**
 * Convert a ICAMEX message to a type50 MEX message.
 *
Loading