s390/zcrypt: Introduce QACT support for AP bus devices.

This patch introduces a new ap_qact() function which
exploits the PQAP(QACT) subfunction. QACT is a new
interface to Query the Ap Compatilibity Type based
on a given AP qid, type, mode and version.

Based on this new function the AP bus scan code is
slightly reworked to use this new interface for
querying the compatible type for each new AP queue
device detected. So new and unknown devices can
get automatically mapped to a compatible type and
handled without the need for toleration patches
for every new hardware.

The currently highest known hardware is CEX6S.
With this patch a possible successor can get
queried for a combatible type known by the device
driver without the need for an toleration patch.

Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/crypto/ap_asm.h b/drivers/s390/crypto/ap_asm.h
index cd35034..0c0c02f 100644
--- a/drivers/s390/crypto/ap_asm.h
+++ b/drivers/s390/crypto/ap_asm.h
@@ -116,6 +116,49 @@ static inline int ap_qci(void *config)
 	return reg1;
 }
 
+/*
+ * struct ap_qact_ap_info - used together with the
+ * ap_aqic() function to provide a convenient way
+ * to handle the ap info needed by the qact function.
+ */
+struct ap_qact_ap_info {
+	unsigned int _res1   : 3;
+	unsigned int mode    : 3;
+	unsigned int _res2   : 26;
+	unsigned int cat     : 8;
+	unsigned int _res3   : 8;
+	unsigned char ver[2];
+};
+
+/**
+ * ap_qact(): Query AP combatibility type.
+ * @qid: The AP queue number
+ * @apinfo: On input the info about the AP queue (content of GR1
+ *	    according to the AR). On output the alternate AP queue
+ *	    info provided by the qact function in GR2 is stored in.
+ *
+ * Returns AP queue status. Check response_code field for failures.
+ */
+static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
+					     struct ap_qact_ap_info *apinfo)
+{
+	register unsigned long reg0 asm ("0") = qid | (5UL << 24)
+		| ((ifbit & 0x01) << 22);
+	register struct ap_qact_ap_info reg1_in asm ("1") = *apinfo;
+	register struct ap_queue_status reg1_out asm ("1");
+	register unsigned long reg2_in asm ("2") = 0;
+	register struct ap_qact_ap_info reg2_out asm ("2");
+
+	asm volatile(
+		".long 0xb2af0000"		/* PQAP(QACT) */
+		: "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out),
+		  "+d" (reg2_in), "=d" (reg2_out)
+		:
+		: "cc");
+	*apinfo = reg2_out;
+	return reg1_out;
+}
+
 /**
  * ap_nqap(): Send message to adjunct processor queue.
  * @qid: The AP queue number