summaryrefslogtreecommitdiff
path: root/drivers/s390/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r--drivers/s390/crypto/ap_bus.c144
-rw-r--r--drivers/s390/crypto/ap_bus.h1
-rw-r--r--drivers/s390/crypto/zcrypt_api.h1
-rw-r--r--drivers/s390/crypto/zcrypt_cex4.c33
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);
}