diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index dc6d891a7b48..28913e540096 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -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)) { - 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); + weight = zdev->speed_rating[func_code]; + if (!pref_zdev) { + pref_zdev = zdev; + pref_weight = weight; + continue; } - else - rc = -EAGAIN; - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; + 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_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; + + 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 -ENODEV; + return rc; } 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)) { - 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); + + weight = zdev->speed_rating[func_code]; + if (!pref_zdev) { + pref_zdev = zdev; + pref_weight = weight; + continue; } - else - rc = -EAGAIN; - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; + 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_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; + 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 -ENODEV; + return rc; } 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,27 +568,42 @@ 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)) { - 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); + + weight = speed_idx_cca(func_code) * zdev->speed_rating[SECKEY]; + if (!pref_zdev) { + pref_zdev = zdev; + pref_weight = weight; + continue; } - else - rc = -EAGAIN; - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; + 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_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; + 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 -ENODEV; + return rc; } struct ep11_target_dev_list { @@ -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,58 +673,93 @@ 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)) { - spin_unlock_bh(&zcrypt_device_lock); - rc = zdev->ops->send_ep11_cprb(zdev, xcrb); - spin_lock_bh(&zcrypt_device_lock); - module_put(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); - spin_unlock_bh(&zcrypt_device_lock); - return rc; + 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 = pref_zdev->ops->send_ep11_cprb(pref_zdev, xcrb, &ap_msg); + spin_lock_bh(&zcrypt_device_lock); + module_put(pref_zdev->ap_dev->drv->driver.owner); + } else { + rc = -EAGAIN; + } + pref_zdev->request_count--; + put_device(&pref_zdev->ap_dev->device); + zcrypt_device_put(pref_zdev); spin_unlock_bh(&zcrypt_device_lock); - return -ENODEV; + return rc; } 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)) { - spin_unlock_bh(&zcrypt_device_lock); - rc = zdev->ops->rng(zdev, buffer); - spin_lock_bh(&zcrypt_device_lock); - module_put(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); - spin_unlock_bh(&zcrypt_device_lock); - return rc; + + 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); + 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(pref_zdev->ap_dev->drv->driver.owner); + } else + rc = -EAGAIN; + pref_zdev->request_count--; + put_device(&pref_zdev->ap_dev->device); + zcrypt_device_put(pref_zdev); spin_unlock_bh(&zcrypt_device_lock); - return -ENODEV; + return rc; } static void zcrypt_status_mask(char status[AP_DEVICES]) diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 326ecdc0417f..3d0d1e25d751 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -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. */ diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index d892cb539139..4bb13eadd0f1 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c @@ -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); diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index e98bdbe45d2c..ff28ad543c30 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -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); diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 7bafba83390a..fb97479af3f8 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -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. * diff --git a/drivers/s390/crypto/zcrypt_msgtype50.h b/drivers/s390/crypto/zcrypt_msgtype50.h index eeb41c0f34ae..5cc280318ee7 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.h +++ b/drivers/s390/crypto/zcrypt_msgtype50.h @@ -35,6 +35,9 @@ #define MSGTYPE_ADJUSTMENT 0x08 /*type04 extension (not needed in type50)*/ +unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *, int *); +unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *, int *); + void zcrypt_msgtype50_init(void); void zcrypt_msgtype50_exit(void); diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index f71949685ff5..957a88d5768b 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -149,6 +149,112 @@ static struct CPRBX static_cprbx = { .func_id = {0x54, 0x32}, }; +int speed_idx_cca(int req_type) +{ + switch (req_type) { + case 0x4142: + case 0x4149: + case 0x414D: + case 0x4341: + case 0x4344: + case 0x4354: + case 0x4358: + case 0x444B: + case 0x4558: + case 0x4643: + case 0x4651: + case 0x4C47: + case 0x4C4B: + case 0x4C51: + case 0x4F48: + case 0x504F: + case 0x5053: + case 0x5058: + case 0x5343: + case 0x5344: + case 0x5345: + case 0x5350: + return LOW; + case 0x414B: + case 0x4345: + case 0x4349: + case 0x434D: + case 0x4847: + case 0x4849: + case 0x484D: + case 0x4850: + case 0x4851: + case 0x4954: + case 0x4958: + case 0x4B43: + case 0x4B44: + case 0x4B45: + case 0x4B47: + case 0x4B48: + case 0x4B49: + case 0x4B4E: + case 0x4B50: + case 0x4B52: + case 0x4B54: + case 0x4B58: + case 0x4D50: + case 0x4D53: + case 0x4D56: + case 0x4D58: + case 0x5044: + case 0x5045: + case 0x5046: + case 0x5047: + case 0x5049: + case 0x504B: + case 0x504D: + case 0x5254: + case 0x5347: + case 0x5349: + case 0x534B: + case 0x534D: + case 0x5356: + case 0x5358: + case 0x5443: + case 0x544B: + case 0x5647: + return HIGH; + default: + return MEDIUM; + } +} + +int speed_idx_ep11(int req_type) +{ + switch (req_type) { + case 1: + case 2: + case 36: + case 37: + case 38: + case 39: + case 40: + return LOW; + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 26: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + return HIGH; + default: + return MEDIUM; + } +} + + /** * Convert a ICAMEX message to a type6 MEX message. * @@ -297,9 +403,9 @@ struct type86_fmt2_msg { struct type86_fmt2_ext fmt2; } __packed; -static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_xcRB *xcRB) +static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg, + struct ica_xcRB *xcRB, + unsigned int *fcode) { static struct type6_hdr static_type6_hdrX = { .type = 0x06, @@ -379,6 +485,8 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code)); + *fcode = (msg->hdr.function_code[0] << 8) | msg->hdr.function_code[1]; + if (memcmp(function_code, "US", 2) == 0) ap_msg->special = 1; else @@ -392,12 +500,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, return 0; } -static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ep11_urb *xcRB) +static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message *ap_msg, + struct ep11_urb *xcRB, + unsigned int *fcode) { - unsigned int lfmt; - static struct type6_hdr static_type6_ep11_hdr = { .type = 0x06, .rqid = {0x00, 0x01}, @@ -421,7 +527,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev, unsigned char dom_tag; /* fixed value 0x4 */ unsigned char dom_len; /* fixed value 0x4 */ unsigned int dom_val; /* domain id */ - } __packed * payload_hdr; + } __packed * payload_hdr = NULL; if (CEIL4(xcRB->req_len) < xcRB->req_len) return -EINVAL; /* overflow after alignment*/ @@ -450,36 +556,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev, return -EFAULT; } - /* - The target domain field within the cprb body/payload block will be - replaced by the usage domain for non-management commands only. - Therefore we check the first bit of the 'flags' parameter for - management command indication. - 0 - non management command - 1 - management command - */ - if (!((msg->cprbx.flags & 0x80) == 0x80)) { - msg->cprbx.target_id = (unsigned int) - AP_QID_QUEUE(zdev->ap_dev->qid); - - if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/ - switch (msg->pld_lenfmt & 0x03) { - case 1: - lfmt = 2; - break; - case 2: - lfmt = 3; - break; - default: - return -EINVAL; - } - } else { - lfmt = 1; /* length format #1 */ - } - payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt); - payload_hdr->dom_val = (unsigned int) - AP_QID_QUEUE(zdev->ap_dev->qid); - } + *fcode = speed_idx_ep11(payload_hdr->func_val & 0xFFFF); return 0; } @@ -989,6 +1066,36 @@ out_free: return rc; } +unsigned int get_cprb_fc(struct ica_xcRB *xcRB, + struct ap_message *ap_msg, + int *func_code) +{ + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_XCRB, + }; + int rc; + + ap_init_message(ap_msg); + ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); + if (!ap_msg->message) + return -ENOMEM; + ap_msg->receive = zcrypt_msgtype6_receive; + ap_msg->psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); + if (!ap_msg->private) { + kzfree(ap_msg->message); + return -ENOMEM; + } + memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); + rc = XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code); + if (rc) { + kzfree(ap_msg->message); + kzfree(ap_msg->private); + } + return rc; +} + /** * The request distributor calls this function if it picked the PCIXCC/CEX2C * device to handle a send_cprb request. @@ -997,37 +1104,55 @@ out_free: * @xcRB: pointer to the send_cprb request buffer */ static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev, - struct ica_xcRB *xcRB) + struct ica_xcRB *xcRB, + struct ap_message *ap_msg) +{ + int rc; + struct response_type *rtype = (struct response_type *)(ap_msg->private); + + init_completion(&rtype->work); + ap_queue_message(zdev->ap_dev, ap_msg); + rc = wait_for_completion_interruptible(&rtype->work); + if (rc == 0) { + rc = ap_msg->rc; + if (rc == 0) + rc = convert_response_xcrb(zdev, ap_msg, xcRB); + } else + /* Signal pending. */ + ap_cancel_message(zdev->ap_dev, ap_msg); + + kzfree(ap_msg->message); + kzfree(ap_msg->private); + return rc; +} + +unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, + struct ap_message *ap_msg, + int *func_code) { - struct ap_message ap_msg; struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_XCRB, + .type = PCIXCC_RESPONSE_TYPE_EP11, }; int rc; - ap_init_message(&ap_msg); - ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); - if (!ap_msg.message) + ap_init_message(ap_msg); + ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); + if (!ap_msg->message) return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + + ap_msg->receive = zcrypt_msgtype6_receive_ep11; + ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); - if (rc == 0) { - rc = ap_msg.rc; - if (rc == 0) - rc = convert_response_xcrb(zdev, &ap_msg, xcRB); - } else - /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); -out_free: - kzfree(ap_msg.message); + ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); + if (!ap_msg->private) { + kzfree(ap_msg->message); + return -ENOMEM; + } + memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); + rc = xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); + if (rc) { + kzfree(ap_msg->message); + kzfree(ap_msg->private); + } return rc; } @@ -1039,41 +1164,101 @@ out_free: * @xcRB: pointer to the ep11 user request block */ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev, - struct ep11_urb *xcrb) + struct ep11_urb *xcrb, + struct ap_message *ap_msg) { - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_EP11, - }; int rc; + unsigned int lfmt; + struct response_type *rtype = (struct response_type *)(ap_msg->private); + struct { + struct type6_hdr hdr; + struct ep11_cprb cprbx; + unsigned char pld_tag; /* fixed value 0x30 */ + unsigned char pld_lenfmt; /* payload length format */ + } __packed * msg = ap_msg->message; + struct pld_hdr { + unsigned char func_tag; /* fixed value 0x4 */ + unsigned char func_len; /* fixed value 0x4 */ + unsigned int func_val; /* function ID */ + unsigned char dom_tag; /* fixed value 0x4 */ + unsigned char dom_len; /* fixed value 0x4 */ + unsigned int dom_val; /* domain id */ + } __packed * payload_hdr = NULL; - ap_init_message(&ap_msg); - ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive_ep11; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); + + /** + * The target domain field within the cprb body/payload block will be + * replaced by the usage domain for non-management commands only. + * Therefore we check the first bit of the 'flags' parameter for + * management command indication. + * 0 - non management command + * 1 - management command + */ + if (!((msg->cprbx.flags & 0x80) == 0x80)) { + msg->cprbx.target_id = (unsigned int) + AP_QID_QUEUE(zdev->ap_dev->qid); + + if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/ + switch (msg->pld_lenfmt & 0x03) { + case 1: + lfmt = 2; + break; + case 2: + lfmt = 3; + break; + default: + return -EINVAL; + } + } else { + lfmt = 1; /* length format #1 */ + } + payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt); + payload_hdr->dom_val = (unsigned int) + AP_QID_QUEUE(zdev->ap_dev->qid); + } + + init_completion(&rtype->work); + ap_queue_message(zdev->ap_dev, ap_msg); + rc = wait_for_completion_interruptible(&rtype->work); if (rc == 0) { - rc = ap_msg.rc; + rc = ap_msg->rc; if (rc == 0) - rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb); + rc = convert_response_ep11_xcrb(zdev, ap_msg, xcrb); } else /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); + ap_cancel_message(zdev->ap_dev, ap_msg); -out_free: - kzfree(ap_msg.message); + kzfree(ap_msg->message); + kzfree(ap_msg->private); return rc; } +unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code) +{ + struct response_type resp_type = { + .type = PCIXCC_RESPONSE_TYPE_XCRB, + }; + + ap_init_message(ap_msg); + ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); + if (!ap_msg->message) + return -ENOMEM; + ap_msg->receive = zcrypt_msgtype6_receive; + ap_msg->psmid = (((unsigned long long) current->pid) << 32) + + atomic_inc_return(&zcrypt_step); + ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); + if (!ap_msg->private) { + kzfree(ap_msg->message); + return -ENOMEM; + } + memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); + + rng_type6CPRB_msgX(ap_msg, ZCRYPT_RNG_BUFFER_SIZE); + + *func_code = HWRNG; + return 0; +} + /** * The request distributor calls this function if it picked the PCIXCC/CEX2C * device to generate random data. @@ -1081,36 +1266,36 @@ out_free: * PCIXCC/CEX2C device to the request distributor * @buffer: pointer to a memory page to return random data */ - static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev, - char *buffer) + char *buffer, struct ap_message *ap_msg) { - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_XCRB, - }; + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + char function_code[2]; + short int rule_length; + char rule[8]; + short int verb_length; + short int key_length; + } __packed * msg = ap_msg->message; + struct response_type *rtype = (struct response_type *)(ap_msg->private); int rc; - ap_init_message(&ap_msg); - ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.receive = zcrypt_msgtype6_receive; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible(&resp_type.work); + msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); + + init_completion(&rtype->work); + ap_queue_message(zdev->ap_dev, ap_msg); + rc = wait_for_completion_interruptible(&rtype->work); if (rc == 0) { - rc = ap_msg.rc; + rc = ap_msg->rc; if (rc == 0) - rc = convert_response_rng(zdev, &ap_msg, buffer); + rc = convert_response_rng(zdev, ap_msg, buffer); } else /* Signal pending. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - kfree(ap_msg.message); + ap_cancel_message(zdev->ap_dev, ap_msg); + + kzfree(ap_msg->message); + kzfree(ap_msg->private); return rc; } diff --git a/drivers/s390/crypto/zcrypt_msgtype6.h b/drivers/s390/crypto/zcrypt_msgtype6.h index 5750c4377bfa..a360dbe3c7d2 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.h +++ b/drivers/s390/crypto/zcrypt_msgtype6.h @@ -116,15 +116,25 @@ struct type86_fmt2_ext { unsigned int offset4; /* 0x00000000 */ } __packed; +unsigned int get_cprb_fc(struct ica_xcRB *, struct ap_message *, int *); +unsigned int get_ep11cprb_fc(struct ep11_urb *, struct ap_message *, int *); +unsigned int get_rng_fc(struct ap_message *, int *); + +#define LOW 10 +#define MEDIUM 100 +#define HIGH 500 + +int speed_idx_cca(int); +int speed_idx_ep11(int); + /** * Prepare a type6 CPRB message for random number generation * * @ap_dev: AP device pointer * @ap_msg: pointer to AP message */ -static inline void rng_type6CPRB_msgX(struct ap_device *ap_dev, - struct ap_message *ap_msg, - unsigned random_number_length) +static inline void rng_type6CPRB_msgX(struct ap_message *ap_msg, + unsigned int random_number_length) { struct { struct type6_hdr hdr; @@ -156,7 +166,6 @@ static inline void rng_type6CPRB_msgX(struct ap_device *ap_dev, msg->hdr.FromCardLen2 = random_number_length, msg->cprbx = local_cprbx; msg->cprbx.rpl_datal = random_number_length, - msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); memcpy(msg->function_code, msg->hdr.function_code, 0x02); msg->rule_length = 0x0a; memcpy(msg->rule, "RANDOM ", 8); diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 8491541f72cf..43de39c74944 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c @@ -46,11 +46,6 @@ #define CEX3C_MIN_MOD_SIZE PCIXCC_MIN_MOD_SIZE #define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */ -#define PCIXCC_MCL2_SPEED_RATING 7870 -#define PCIXCC_MCL3_SPEED_RATING 7870 -#define CEX2C_SPEED_RATING 7000 -#define CEX3C_SPEED_RATING 6500 - #define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */ #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ @@ -220,6 +215,15 @@ static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev) struct type86_fmt2_ext fmt2; struct CPRBX cprbx; } __attribute__((packed)) *reply; + struct { + struct type6_hdr hdr; + struct CPRBX cprbx; + char function_code[2]; + short int rule_length; + char rule[8]; + short int verb_length; + short int key_length; + } __packed * msg; int rc, i; ap_init_message(&ap_msg); @@ -227,7 +231,11 @@ static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev) if (!ap_msg.message) return -ENOMEM; - rng_type6CPRB_msgX(ap_dev, &ap_msg, 4); + rng_type6CPRB_msgX(&ap_msg, 4); + + msg = ap_msg.message; + msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); + rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message, ap_msg.length); if (rc) @@ -267,6 +275,14 @@ out_free: static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) { struct zcrypt_device *zdev; + /* + * Normalized speed ratings per crypto adapter + * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY + */ + int PCIXCC_MCL2_SPEED_IDX[] = {10, 10, 10, 10, 10, 10, 10, 10}; + int PCIXCC_MCL3_SPEED_IDX[] = { 8, 8, 8, 8, 8, 8, 8, 8}; + int CEX2C_SPEED_IDX[] = {1000, 1400, 2400, 1100, 1500, 2600, 100, 12}; + int CEX3C_SPEED_IDX[] = { 500, 700, 1400, 550, 800, 1500, 80, 10}; int rc = 0; zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE); @@ -284,13 +300,15 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) zdev->user_space_type = rc; if (rc == ZCRYPT_PCIXCC_MCL2) { zdev->type_string = "PCIXCC_MCL2"; - zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING; + memcpy(zdev->speed_rating, PCIXCC_MCL2_SPEED_IDX, + sizeof(PCIXCC_MCL2_SPEED_IDX)); zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; } else { zdev->type_string = "PCIXCC_MCL3"; - zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING; + memcpy(zdev->speed_rating, PCIXCC_MCL3_SPEED_IDX, + sizeof(PCIXCC_MCL3_SPEED_IDX)); zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; @@ -299,7 +317,8 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) case AP_DEVICE_TYPE_CEX2C: zdev->user_space_type = ZCRYPT_CEX2C; zdev->type_string = "CEX2C"; - zdev->speed_rating = CEX2C_SPEED_RATING; + memcpy(zdev->speed_rating, CEX2C_SPEED_IDX, + sizeof(CEX2C_SPEED_IDX)); zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; @@ -307,7 +326,8 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) case AP_DEVICE_TYPE_CEX3C: zdev->user_space_type = ZCRYPT_CEX3C; zdev->type_string = "CEX3C"; - zdev->speed_rating = CEX3C_SPEED_RATING; + memcpy(zdev->speed_rating, CEX3C_SPEED_IDX, + sizeof(CEX3C_SPEED_IDX)); zdev->min_mod_size = CEX3C_MIN_MOD_SIZE; zdev->max_mod_size = CEX3C_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE; @@ -315,6 +335,7 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) default: goto out_free; } + zdev->load = zdev->speed_rating[0]; rc = zcrypt_pcixcc_rng_supported(ap_dev); if (rc < 0) {