[S390] zcrypt: Introduce check for 4096 bit support.
Felix Beck [Wed, 5 Jan 2011 11:47:44 +0000 (12:47 +0100)]
Implemented an asm in the ap bus and made it accessible for the card
specific parts of the zcrypt driver. Thus when a cex3a is recognized
a check can be performed to dermine whether the card supports 4096 bit
RSA keys.

Signed-off-by: Felix Beck <felix.beck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h

index 4f37c45..67302b9 100644 (file)
@@ -222,6 +222,69 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
 }
 #endif
 
+static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
+                                                                 int *support)
+{
+       register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
+       register struct ap_queue_status reg1 asm ("1");
+       register unsigned long reg2 asm ("2") = 0UL;
+
+       asm volatile(
+               ".long 0xb2af0000\n"
+               "0: la    %1,0\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : "+d" (reg0), "=d" (reg1), "=d" (reg2)
+               :
+               : "cc");
+
+       if (reg2 & 0x6000000000000000ULL)
+               *support = 1;
+       else
+               *support = 0;
+
+       return reg1;
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+       struct ap_queue_status status;
+       int i, support = 0;
+       status = __ap_4096_commands_available(qid, &support);
+
+       for (i = 0; i < AP_MAX_RESET; i++) {
+               switch (status.response_code) {
+               case AP_RESPONSE_NORMAL:
+                       return support;
+               case AP_RESPONSE_RESET_IN_PROGRESS:
+               case AP_RESPONSE_BUSY:
+                       break;
+               case AP_RESPONSE_Q_NOT_AVAIL:
+               case AP_RESPONSE_DECONFIGURED:
+               case AP_RESPONSE_CHECKSTOPPED:
+               case AP_RESPONSE_INVALID_ADDRESS:
+                       return 0;
+               case AP_RESPONSE_OTHERWISE_CHANGED:
+                       break;
+               default:
+                       break;
+               }
+               if (i < AP_MAX_RESET - 1) {
+                       udelay(5);
+                       status = __ap_4096_commands_available(qid, &support);
+               }
+       }
+       return support;
+}
+EXPORT_SYMBOL(ap_4096_commands_available);
+
 /**
  * ap_queue_enable_interruption(): Enable interruption on an AP.
  * @qid: The AP queue number
index 4785d07..08b9738 100644 (file)
@@ -196,4 +196,6 @@ void ap_flush_queue(struct ap_device *ap_dev);
 int ap_module_init(void);
 void ap_module_exit(void);
 
+int ap_4096_commands_available(ap_qid_t qid);
+
 #endif /* _AP_BUS_H_ */