summary refs log tree commit diff
path: root/drivers/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2015-06-26 15:40:41 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-10-14 14:32:19 +0200
commit6acbe21f473f5cff8a11546f090967459b63ab3e (patch)
treeb4014950cbaa834720efebc2d5a720ebf9cd2687 /drivers/s390
parent29b0a8250ba63beffba4fe3a42fa75dddf4bd06a (diff)
downloadlinux-6acbe21f473f5cff8a11546f090967459b63ab3e.tar.gz
s390/zcrypt: remove duplicate low level functions
ap_test_queue, ap_query_facilities, __ap_query_functions all use
the same PQAP(TAPQ) command. Consolidate the three into a single
ap_test_queue function that returns the AP status and the 64-bit
result. The exception table entry for PQAP(TAPQ) can be avoided
if the T bit for the APFT facility is set only if test_facility(15)
indicated that the facility is present.

Integrate ap_query_function into ap_query queue to avoid calling
PQAP(TAPQ) twice.

Reviewed-by: Ingo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/ap_bus.c140
-rw-r--r--drivers/s390/crypto/ap_bus.h9
2 files changed, 32 insertions, 117 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index d78b3d629d78..613c92b22445 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -182,44 +182,27 @@ static int ap_configuration_available(void)
 /**
  * ap_test_queue(): Test adjunct processor queue.
  * @qid: The AP queue number
- * @queue_depth: Pointer to queue depth value
- * @device_type: Pointer to device type value
+ * @info: Pointer to queue descriptor
  *
  * Returns AP queue status structure.
  */
 static inline struct ap_queue_status
-ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ap_test_queue(ap_qid_t qid, unsigned long *info)
 {
 	register unsigned long reg0 asm ("0") = qid;
 	register struct ap_queue_status reg1 asm ("1");
 	register unsigned long reg2 asm ("2") = 0UL;
 
+	if (test_facility(15))
+		reg0 |= 1UL << 23;		/* set APFT T bit*/
 	asm volatile(".long 0xb2af0000"		/* PQAP(TAPQ) */
 		     : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
-	*device_type = (int) (reg2 >> 24);
-	*queue_depth = (int) (reg2 & 0xff);
+	if (info)
+		*info = reg2;
 	return reg1;
 }
 
 /**
- * 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
  *
@@ -259,25 +242,6 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
 	return reg1_out;
 }
 
-static inline struct ap_queue_status
-__ap_query_functions(ap_qid_t qid, unsigned int *functions)
-{
-	register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
-	register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
-	register unsigned long reg2 asm ("2");
-
-	asm volatile(
-		".long 0xb2af0000\n"		/* PQAP(TAPQ) */
-		"0:\n"
-		EX_TABLE(0b, 0b)
-		: "+d" (reg0), "+d" (reg1), "=d" (reg2)
-		:
-		: "cc");
-
-	*functions = (unsigned int)(reg2 >> 32);
-	return reg1;
-}
-
 static inline int __ap_query_configuration(struct ap_config_info *config)
 {
 	register unsigned long reg0 asm ("0") = 0x04000000UL;
@@ -297,42 +261,6 @@ static inline int __ap_query_configuration(struct ap_config_info *config)
 }
 
 /**
- * ap_query_functions(): Query supported functions.
- * @qid: The AP queue number
- * @functions: Pointer to functions field.
- *
- * Returns
- *   0	     on success.
- *   -ENODEV  if queue not valid.
- *   -EBUSY   if device busy.
- *   -EINVAL  if query function is not supported
- */
-static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
-{
-	struct ap_queue_status status;
-
-	status = __ap_query_functions(qid, functions);
-
-	if (ap_queue_status_invalid_test(&status))
-		return -ENODEV;
-
-	switch (status.response_code) {
-	case AP_RESPONSE_NORMAL:
-		return 0;
-	case AP_RESPONSE_Q_NOT_AVAIL:
-	case AP_RESPONSE_DECONFIGURED:
-	case AP_RESPONSE_CHECKSTOPPED:
-	case AP_RESPONSE_INVALID_ADDRESS:
-		return -ENODEV;
-	case AP_RESPONSE_RESET_IN_PROGRESS:
-	case AP_RESPONSE_BUSY:
-	case AP_RESPONSE_OTHERWISE_CHANGED:
-	default:
-		return -EBUSY;
-	}
-}
-
-/**
  * ap_queue_enable_interruption(): Enable interruption on an AP.
  * @qid: The AP queue number
  * @ind: the notification indicator byte
@@ -515,17 +443,20 @@ static inline void ap_schedule_poll_timer(void)
  * @qid: The AP queue number
  * @queue_depth: Pointer to queue depth value
  * @device_type: Pointer to device type value
+ * @facilities: Pointer to facility indicator
  */
-static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
+			  unsigned int *facilities)
 {
 	struct ap_queue_status status;
-	int t_depth, t_device_type;
+	unsigned long info;
 
-	status = ap_test_queue(qid, &t_depth, &t_device_type);
+	status = ap_test_queue(qid, &info);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
-		*queue_depth = t_depth + 1;
-		*device_type = t_device_type;
+		*queue_depth = (int)(info & 0xff);
+		*device_type = (int)((info >> 24) & 0xff);
+		*facilities = (unsigned int)(info >> 32);
 		return 0;
 	case AP_RESPONSE_Q_NOT_AVAIL:
 	case AP_RESPONSE_DECONFIGURED:
@@ -1184,6 +1115,7 @@ 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)
 {
+	struct ap_queue_status status;
 	ap_qid_t qid;
 	int i, nd, max_domain_id = -1;
 	unsigned long fbits;
@@ -1194,7 +1126,9 @@ static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
 				if (!ap_test_config_card_id(i))
 					continue;
 				qid = AP_MKQID(i, ap_domain_index);
-				fbits = ap_query_facilities(qid);
+				status = ap_test_queue(qid, &fbits);
+				if (status.response_code != AP_RESPONSE_NORMAL)
+					continue;
 				if (fbits & (1UL << 57)) {
 					/* the N bit is 0, Nd field is filled */
 					nd = (int)((fbits & 0x00FF0000UL)>>16);
@@ -1254,9 +1188,9 @@ static void ap_query_configuration(void)
  */
 static int ap_select_domain(void)
 {
-	int queue_depth, device_type, count, max_count, best_domain;
-	ap_qid_t qid;
-	int rc, i, j;
+	int count, max_count, best_domain;
+	struct ap_queue_status status;
+	int i, j;
 
 	/* IF APXA isn't installed, only 16 domains could be defined */
 	if (!ap_configuration->ap_extended && (ap_domain_index > 15))
@@ -1279,9 +1213,8 @@ static int ap_select_domain(void)
 		for (j = 0; j < AP_DEVICES; j++) {
 			if (!ap_test_config_card_id(j))
 				continue;
-			qid = AP_MKQID(j, i);
-			rc = ap_query_queue(qid, &queue_depth, &device_type);
-			if (rc)
+			status = ap_test_queue(AP_MKQID(j, i), NULL);
+			if (status.response_code != AP_RESPONSE_NORMAL)
 				continue;
 			count++;
 		}
@@ -1438,7 +1371,8 @@ static void ap_scan_bus(struct work_struct *unused)
 				      (void *)(unsigned long)qid,
 				      __ap_scan_bus);
 		if (ap_test_config_card_id(i))
-			rc = ap_query_queue(qid, &queue_depth, &device_type);
+			rc = ap_query_queue(qid, &queue_depth, &device_type,
+					    &device_functions);
 		else
 			rc = -ENODEV;
 		if (dev) {
@@ -1468,6 +1402,9 @@ static void ap_scan_bus(struct work_struct *unused)
 			continue;
 		}
 		ap_dev->queue_depth = queue_depth;
+		ap_dev->raw_hwtype = device_type;
+		ap_dev->device_type = device_type;
+		ap_dev->functions = device_functions;
 		ap_dev->unregistered = 1;
 		spin_lock_init(&ap_dev->lock);
 		INIT_LIST_HEAD(&ap_dev->pendingq);
@@ -1475,24 +1412,12 @@ static void ap_scan_bus(struct work_struct *unused)
 		INIT_LIST_HEAD(&ap_dev->list);
 		setup_timer(&ap_dev->timeout, ap_request_timeout,
 			    (unsigned long) ap_dev);
-		switch (device_type) {
-		case 0:
+		if (ap_dev->device_type == 0)
 			/* device type probing for old cards */
 			if (ap_probe_device_type(ap_dev)) {
 				kfree(ap_dev);
 				continue;
 			}
-			break;
-		default:
-			ap_dev->device_type = device_type;
-		}
-		ap_dev->raw_hwtype = device_type;
-
-		rc = ap_query_functions(qid, &device_functions);
-		if (!rc)
-			ap_dev->functions = device_functions;
-		else
-			ap_dev->functions = 0u;
 
 		ap_dev->device.bus = &ap_bus_type;
 		ap_dev->device.parent = ap_root_device;
@@ -1640,12 +1565,11 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
  */
 static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
 {
-	int rc, depth, type;
 	struct ap_queue_status status;
-
+	int rc;
 
 	if (ap_dev->reset == AP_RESET_IN_PROGRESS) {
-		status = ap_test_queue(ap_dev->qid, &depth, &type);
+		status = ap_test_queue(ap_dev->qid, NULL);
 		switch (status.response_code) {
 		case AP_RESPONSE_NORMAL:
 			ap_dev->reset = AP_RESET_IGNORE;
@@ -1676,7 +1600,7 @@ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
 
 	if ((ap_dev->reset != AP_RESET_IN_PROGRESS) &&
 		(ap_dev->interrupt == AP_INTR_IN_PROGRESS)) {
-		status = ap_test_queue(ap_dev->qid, &depth, &type);
+		status = ap_test_queue(ap_dev->qid, NULL);
 		if (ap_using_interrupts()) {
 			if (status.int_enabled == 1)
 				ap_dev->interrupt = AP_INTR_ENABLED;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 00468c8d0781..2e0a21f84f3d 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -75,15 +75,6 @@ struct ap_queue_status {
 	unsigned int pad2		: 16;
 } __packed;
 
-#define AP_QUEUE_STATUS_INVALID \
-		{ 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
-
-static inline
-int ap_queue_status_invalid_test(struct ap_queue_status *status)
-{
-	struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
-	return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
-}
 
 #define AP_MAX_BITS 31
 static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)