Commit 91ffc519 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/zcrypt: introduce msg tracking in zcrypt functions

Introduce a new internal struct zcrypt_track with an retry counter
field and a last return code field. Fill and update these fields at
certain points during processing of an request/reply. This tracking
info is then used to
- avoid trying to resend the message forever. Now each message is
  tried to be send TRACK_AGAIN_MAX (currently 10) times and then the
  ioctl returns to userspace with errno EAGAIN.
- avoid trying to resend the message on the very same card/domain. If
  possible (more than one APQN with same quality) don't use the very
  same qid as the previous attempt when again scheduling the request.
  This is done by adding penalty weight values when the dispatching
  takes place. There is a penalty TRACK_AGAIN_CARD_WEIGHT_PENALTY for
  using the same card as previously and another penalty define
  TRACK_AGAIN_QUEUE_WEIGHT_PENALTY to be considered when the same qid
  as the previous sent attempt is calculated. Both values make it
  harder to choose the very same card/domain but not impossible. For
  example when only one APQN is available a resend can only address the
  very same APQN.

There are some more ideas for the future to extend the use of this
tracking information. For example the last response code at NQAP and
DQAP could be stored there, giving the possibility to extended tracing
and debugging about requests failing to get processed properly.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 4ec95ed3
This diff is collapsed.
...@@ -55,6 +55,18 @@ enum crypto_ops { ...@@ -55,6 +55,18 @@ enum crypto_ops {
struct zcrypt_queue; struct zcrypt_queue;
/* struct to hold tracking information for a userspace request/response */
struct zcrypt_track {
int again_counter; /* retry attempts counter */
int last_qid; /* last qid used */
int last_rc; /* last return code */
};
/* defines related to message tracking */
#define TRACK_AGAIN_MAX 10
#define TRACK_AGAIN_CARD_WEIGHT_PENALTY 1000
#define TRACK_AGAIN_QUEUE_WEIGHT_PENALTY 10000
struct zcrypt_ops { struct zcrypt_ops {
long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *); long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *);
long (*rsa_modexpo_crt)(struct zcrypt_queue *, long (*rsa_modexpo_crt)(struct zcrypt_queue *,
...@@ -82,7 +94,7 @@ struct zcrypt_card { ...@@ -82,7 +94,7 @@ struct zcrypt_card {
int min_mod_size; /* Min number of bits. */ int min_mod_size; /* Min number of bits. */
int max_mod_size; /* Max number of bits. */ int max_mod_size; /* Max number of bits. */
int max_exp_bit_length; int max_exp_bit_length;
int speed_rating[NUM_OPS]; /* Speed idx of crypto ops. */ const int *speed_rating; /* Speed idx of crypto ops. */
atomic_t load; /* Utilization of the crypto device */ atomic_t load; /* Utilization of the crypto device */
int request_count; /* # current requests. */ int request_count; /* # current requests. */
......
...@@ -94,8 +94,7 @@ static int zcrypt_cex2a_card_probe(struct ap_device *ap_dev) ...@@ -94,8 +94,7 @@ static int zcrypt_cex2a_card_probe(struct ap_device *ap_dev)
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) { if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) {
zc->min_mod_size = CEX2A_MIN_MOD_SIZE; zc->min_mod_size = CEX2A_MIN_MOD_SIZE;
zc->max_mod_size = CEX2A_MAX_MOD_SIZE; zc->max_mod_size = CEX2A_MAX_MOD_SIZE;
memcpy(zc->speed_rating, CEX2A_SPEED_IDX, zc->speed_rating = CEX2A_SPEED_IDX;
sizeof(CEX2A_SPEED_IDX));
zc->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; zc->max_exp_bit_length = CEX2A_MAX_MOD_SIZE;
zc->type_string = "CEX2A"; zc->type_string = "CEX2A";
zc->user_space_type = ZCRYPT_CEX2A; zc->user_space_type = ZCRYPT_CEX2A;
...@@ -108,8 +107,7 @@ static int zcrypt_cex2a_card_probe(struct ap_device *ap_dev) ...@@ -108,8 +107,7 @@ static int zcrypt_cex2a_card_probe(struct ap_device *ap_dev)
zc->max_mod_size = CEX3A_MAX_MOD_SIZE; zc->max_mod_size = CEX3A_MAX_MOD_SIZE;
zc->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; zc->max_exp_bit_length = CEX3A_MAX_MOD_SIZE;
} }
memcpy(zc->speed_rating, CEX3A_SPEED_IDX, zc->speed_rating = CEX3A_SPEED_IDX;
sizeof(CEX3A_SPEED_IDX));
zc->type_string = "CEX3A"; zc->type_string = "CEX3A";
zc->user_space_type = ZCRYPT_CEX3A; zc->user_space_type = ZCRYPT_CEX3A;
} else { } else {
......
...@@ -266,8 +266,7 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) ...@@ -266,8 +266,7 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev)
case AP_DEVICE_TYPE_CEX2C: case AP_DEVICE_TYPE_CEX2C:
zc->user_space_type = ZCRYPT_CEX2C; zc->user_space_type = ZCRYPT_CEX2C;
zc->type_string = "CEX2C"; zc->type_string = "CEX2C";
memcpy(zc->speed_rating, CEX2C_SPEED_IDX, zc->speed_rating = CEX2C_SPEED_IDX;
sizeof(CEX2C_SPEED_IDX));
zc->min_mod_size = CEX2C_MIN_MOD_SIZE; zc->min_mod_size = CEX2C_MIN_MOD_SIZE;
zc->max_mod_size = CEX2C_MAX_MOD_SIZE; zc->max_mod_size = CEX2C_MAX_MOD_SIZE;
zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE; zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE;
...@@ -275,8 +274,7 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) ...@@ -275,8 +274,7 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev)
case AP_DEVICE_TYPE_CEX3C: case AP_DEVICE_TYPE_CEX3C:
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
zc->type_string = "CEX3C"; zc->type_string = "CEX3C";
memcpy(zc->speed_rating, CEX3C_SPEED_IDX, zc->speed_rating = CEX3C_SPEED_IDX;
sizeof(CEX3C_SPEED_IDX));
zc->min_mod_size = CEX3C_MIN_MOD_SIZE; zc->min_mod_size = CEX3C_MIN_MOD_SIZE;
zc->max_mod_size = CEX3C_MAX_MOD_SIZE; zc->max_mod_size = CEX3C_MAX_MOD_SIZE;
zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE; zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
......
...@@ -409,31 +409,31 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -409,31 +409,31 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
* Normalized speed ratings per crypto adapter * Normalized speed ratings per crypto adapter
* MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
*/ */
static const int CEX4A_SPEED_IDX[] = { static const int CEX4A_SPEED_IDX[NUM_OPS] = {
14, 19, 249, 42, 228, 1458, 0, 0}; 14, 19, 249, 42, 228, 1458, 0, 0};
static const int CEX5A_SPEED_IDX[] = { static const int CEX5A_SPEED_IDX[NUM_OPS] = {
8, 9, 20, 18, 66, 458, 0, 0}; 8, 9, 20, 18, 66, 458, 0, 0};
static const int CEX6A_SPEED_IDX[] = { static const int CEX6A_SPEED_IDX[NUM_OPS] = {
6, 9, 20, 17, 65, 438, 0, 0}; 6, 9, 20, 17, 65, 438, 0, 0};
static const int CEX7A_SPEED_IDX[] = { static const int CEX7A_SPEED_IDX[NUM_OPS] = {
6, 8, 17, 15, 54, 362, 0, 0}; 6, 8, 17, 15, 54, 362, 0, 0};
static const int CEX4C_SPEED_IDX[] = { static const int CEX4C_SPEED_IDX[NUM_OPS] = {
59, 69, 308, 83, 278, 2204, 209, 40}; 59, 69, 308, 83, 278, 2204, 209, 40};
static const int CEX5C_SPEED_IDX[] = { static const int CEX5C_SPEED_IDX[] = {
24, 31, 50, 37, 90, 479, 27, 10}; 24, 31, 50, 37, 90, 479, 27, 10};
static const int CEX6C_SPEED_IDX[] = { static const int CEX6C_SPEED_IDX[NUM_OPS] = {
16, 20, 32, 27, 77, 455, 24, 9}; 16, 20, 32, 27, 77, 455, 24, 9};
static const int CEX7C_SPEED_IDX[] = { static const int CEX7C_SPEED_IDX[NUM_OPS] = {
14, 16, 26, 23, 64, 376, 23, 8}; 14, 16, 26, 23, 64, 376, 23, 8};
static const int CEX4P_SPEED_IDX[] = { static const int CEX4P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 50}; 0, 0, 0, 0, 0, 0, 0, 50};
static const int CEX5P_SPEED_IDX[] = { static const int CEX5P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 10}; 0, 0, 0, 0, 0, 0, 0, 10};
static const int CEX6P_SPEED_IDX[] = { static const int CEX6P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 9}; 0, 0, 0, 0, 0, 0, 0, 9};
static const int CEX7P_SPEED_IDX[] = { static const int CEX7P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 8}; 0, 0, 0, 0, 0, 0, 0, 8};
struct ap_card *ac = to_ap_card(&ap_dev->device); struct ap_card *ac = to_ap_card(&ap_dev->device);
...@@ -449,26 +449,22 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -449,26 +449,22 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4A"; zc->type_string = "CEX4A";
zc->user_space_type = ZCRYPT_CEX4; zc->user_space_type = ZCRYPT_CEX4;
memcpy(zc->speed_rating, CEX4A_SPEED_IDX, zc->speed_rating = CEX4A_SPEED_IDX;
sizeof(CEX4A_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
zc->type_string = "CEX5A"; zc->type_string = "CEX5A";
zc->user_space_type = ZCRYPT_CEX5; zc->user_space_type = ZCRYPT_CEX5;
memcpy(zc->speed_rating, CEX5A_SPEED_IDX, zc->speed_rating = CEX5A_SPEED_IDX;
sizeof(CEX5A_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
zc->type_string = "CEX6A"; zc->type_string = "CEX6A";
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
memcpy(zc->speed_rating, CEX6A_SPEED_IDX, zc->speed_rating = CEX6A_SPEED_IDX;
sizeof(CEX6A_SPEED_IDX));
} else { } else {
zc->type_string = "CEX7A"; zc->type_string = "CEX7A";
/* wrong user space type, just for compatibility /* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl. * with the ZCRYPT_STATUS_MASK ioctl.
*/ */
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
memcpy(zc->speed_rating, CEX7A_SPEED_IDX, zc->speed_rating = CEX7A_SPEED_IDX;
sizeof(CEX7A_SPEED_IDX));
} }
zc->min_mod_size = CEX4A_MIN_MOD_SIZE; zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) && if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
...@@ -488,32 +484,28 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -488,32 +484,28 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
memcpy(zc->speed_rating, CEX4C_SPEED_IDX, zc->speed_rating = CEX4C_SPEED_IDX;
sizeof(CEX4C_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
zc->type_string = "CEX5C"; zc->type_string = "CEX5C";
/* wrong user space type, must be CEX5 /* wrong user space type, must be CEX5
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
memcpy(zc->speed_rating, CEX5C_SPEED_IDX, zc->speed_rating = CEX5C_SPEED_IDX;
sizeof(CEX5C_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
zc->type_string = "CEX6C"; zc->type_string = "CEX6C";
/* wrong user space type, must be CEX6 /* wrong user space type, must be CEX6
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
memcpy(zc->speed_rating, CEX6C_SPEED_IDX, zc->speed_rating = CEX6C_SPEED_IDX;
sizeof(CEX6C_SPEED_IDX));
} else { } else {
zc->type_string = "CEX7C"; zc->type_string = "CEX7C";
/* wrong user space type, must be CEX7 /* wrong user space type, must be CEX7
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
memcpy(zc->speed_rating, CEX7C_SPEED_IDX, zc->speed_rating = CEX7C_SPEED_IDX;
sizeof(CEX7C_SPEED_IDX));
} }
zc->min_mod_size = CEX4C_MIN_MOD_SIZE; zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE; zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
...@@ -522,26 +514,22 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -522,26 +514,22 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4P"; zc->type_string = "CEX4P";
zc->user_space_type = ZCRYPT_CEX4; zc->user_space_type = ZCRYPT_CEX4;
memcpy(zc->speed_rating, CEX4P_SPEED_IDX, zc->speed_rating = CEX4P_SPEED_IDX;
sizeof(CEX4P_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
zc->type_string = "CEX5P"; zc->type_string = "CEX5P";
zc->user_space_type = ZCRYPT_CEX5; zc->user_space_type = ZCRYPT_CEX5;
memcpy(zc->speed_rating, CEX5P_SPEED_IDX, zc->speed_rating = CEX5P_SPEED_IDX;
sizeof(CEX5P_SPEED_IDX));
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
zc->type_string = "CEX6P"; zc->type_string = "CEX6P";
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
memcpy(zc->speed_rating, CEX6P_SPEED_IDX, zc->speed_rating = CEX6P_SPEED_IDX;
sizeof(CEX6P_SPEED_IDX));
} else { } else {
zc->type_string = "CEX7P"; zc->type_string = "CEX7P";
/* wrong user space type, just for compatibility /* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl. * with the ZCRYPT_STATUS_MASK ioctl.
*/ */
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
memcpy(zc->speed_rating, CEX7P_SPEED_IDX, zc->speed_rating = CEX7P_SPEED_IDX;
sizeof(CEX7P_SPEED_IDX));
} }
zc->min_mod_size = CEX4C_MIN_MOD_SIZE; zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE; zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment