diff options
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 144 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_cex4.c | 33 |
4 files changed, 129 insertions, 50 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 4d41bf75c233..3d7f19fb9a4e 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -204,6 +204,24 @@ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type) } /** + * ap_query_facilities(): PQAP(TAPQ) query facilities. + * @qid: The AP queue number + * + * Returns content of general register 2 after the PQAP(TAPQ) + * instruction was called. + */ +static inline unsigned long ap_query_facilities(ap_qid_t qid) +{ + register unsigned long reg0 asm ("0") = qid | 0x00800000UL; + register unsigned long reg1 asm ("1"); + register unsigned long reg2 asm ("2") = 0UL; + + asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */ + : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc"); + return reg2; +} + +/** * ap_reset_queue(): Reset adjunct processor queue. * @qid: The AP queue number * @@ -1007,6 +1025,51 @@ void ap_bus_force_rescan(void) EXPORT_SYMBOL(ap_bus_force_rescan); /* + * ap_test_config(): helper function to extract the nrth bit + * within the unsigned int array field. + */ +static inline int ap_test_config(unsigned int *field, unsigned int nr) +{ + if (nr > 0xFFu) + return 0; + return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); +} + +/* + * ap_test_config_card_id(): Test, whether an AP card ID is configured. + * @id AP card ID + * + * Returns 0 if the card is not configured + * 1 if the card is configured or + * if the configuration information is not available + */ +static inline int ap_test_config_card_id(unsigned int id) +{ + if (!ap_configuration) + return 1; + return ap_test_config(ap_configuration->apm, id); +} + +/* + * ap_test_config_domain(): Test, whether an AP usage domain is configured. + * @domain AP usage domain ID + * + * Returns 0 if the usage domain is not configured + * 1 if the usage domain is configured or + * if the configuration information is not available + */ +static inline int ap_test_config_domain(unsigned int domain) +{ + if (!ap_configuration) /* QCI not supported */ + if (domain < 16) + return 1; /* then domains 0...15 are configured */ + else + return 0; + else + return ap_test_config(ap_configuration->aqm, domain); +} + +/* * AP bus attributes. */ static ssize_t ap_domain_show(struct bus_type *bus, char *buf) @@ -1121,6 +1184,42 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf, static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store); +static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) +{ + ap_qid_t qid; + int i, nd, max_domain_id = -1; + unsigned long fbits; + + if (ap_configuration) { + if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS) { + for (i = 0; i < AP_DEVICES; i++) { + if (!ap_test_config_card_id(i)) + continue; + qid = AP_MKQID(i, ap_domain_index); + fbits = ap_query_facilities(qid); + if (fbits & (1UL << 57)) { + /* the N bit is 0, Nd field is filled */ + nd = (int)((fbits & 0x00FF0000UL)>>16); + if (nd > 0) + max_domain_id = nd; + else + max_domain_id = 15; + } else { + /* N bit is 1, max 16 domains */ + max_domain_id = 15; + } + break; + } + } + } else { + /* no APXA support, older machines with max 16 domains */ + max_domain_id = 15; + } + return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id); +} + +static BUS_ATTR(ap_max_domain_id, 0444, ap_max_domain_id_show, NULL); + static struct bus_attribute *const ap_bus_attrs[] = { &bus_attr_ap_domain, &bus_attr_ap_control_domain_mask, @@ -1128,50 +1227,10 @@ static struct bus_attribute *const ap_bus_attrs[] = { &bus_attr_poll_thread, &bus_attr_ap_interrupts, &bus_attr_poll_timeout, + &bus_attr_ap_max_domain_id, NULL, }; -static inline int ap_test_config(unsigned int *field, unsigned int nr) -{ - if (nr > 0xFFu) - return 0; - return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); -} - -/* - * ap_test_config_card_id(): Test, whether an AP card ID is configured. - * @id AP card ID - * - * Returns 0 if the card is not configured - * 1 if the card is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_card_id(unsigned int id) -{ - if (!ap_configuration) - return 1; - return ap_test_config(ap_configuration->apm, id); -} - -/* - * ap_test_config_domain(): Test, whether an AP usage domain is configured. - * @domain AP usage domain ID - * - * Returns 0 if the usage domain is not configured - * 1 if the usage domain is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_domain(unsigned int domain) -{ - if (!ap_configuration) /* QCI not supported */ - if (domain < 16) - return 1; /* then domains 0...15 are configured */ - else - return 0; - else - return ap_test_config(ap_configuration->aqm, domain); -} - /** * ap_query_configuration(): Query AP configuration information. * @@ -1434,9 +1493,6 @@ static void ap_scan_bus(struct work_struct *unused) continue; } break; - case 11: - ap_dev->device_type = 10; - break; default: ap_dev->device_type = device_type; } diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 055a0f956d17..2737d261a324 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -117,6 +117,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) #define AP_DEVICE_TYPE_CEX3A 8 #define AP_DEVICE_TYPE_CEX3C 9 #define AP_DEVICE_TYPE_CEX4 10 +#define AP_DEVICE_TYPE_CEX5 11 /* * Known function facilities diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index b3d496bfaa7e..750876891931 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -75,6 +75,7 @@ struct ica_z90_status { #define ZCRYPT_CEX3C 7 #define ZCRYPT_CEX3A 8 #define ZCRYPT_CEX4 10 +#define ZCRYPT_CEX5 11 /** * Large random numbers are pulled in 4096 byte chunks from the crypto cards diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 569f8b1d86c0..71e698b85772 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -26,6 +26,10 @@ #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 @@ -39,6 +43,7 @@ static struct ap_device_id zcrypt_cex4_ids[] = { { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, + { AP_DEVICE(AP_DEVICE_TYPE_CEX5) }, { /* end of list */ }, }; @@ -70,11 +75,18 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) switch (ap_dev->device_type) { case AP_DEVICE_TYPE_CEX4: + case AP_DEVICE_TYPE_CEX5: if (ap_test_bit(&ap_dev->functions, AP_FUNC_ACCEL)) { zdev = zcrypt_device_alloc(CEX4A_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4A"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4A"; + zdev->speed_rating = CEX4A_SPEED_RATING; + } else { + zdev->type_string = "CEX5A"; + zdev->speed_rating = CEX5A_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX3A; zdev->min_mod_size = CEX4A_MIN_MOD_SIZE; if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && @@ -90,33 +102,42 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) CEX4A_MAX_MOD_SIZE_2K; } zdev->short_crt = 1; - zdev->speed_rating = CEX4A_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, MSGTYPE50_VARIANT_DEFAULT); } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_COPRO)) { zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4C"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4C"; + zdev->speed_rating = CEX4C_SPEED_RATING; + } else { + zdev->type_string = "CEX5C"; + zdev->speed_rating = CEX5C_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX3C; zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; zdev->short_crt = 0; - zdev->speed_rating = CEX4C_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, MSGTYPE06_VARIANT_DEFAULT); } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) { zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4P"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4P"; + zdev->speed_rating = CEX4P_SPEED_RATING; + } else { + zdev->type_string = "CEX5P"; + zdev->speed_rating = CEX5P_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX4; zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; zdev->short_crt = 0; - zdev->speed_rating = CEX4C_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, MSGTYPE06_VARIANT_EP11); } |