From b1f933da570576d1f290ea4dc9b896404cbd285d Mon Sep 17 00:00:00 2001 From: Felix Beck Date: Wed, 5 Jan 2011 12:47:44 +0100 Subject: [PATCH] [S390] zcrypt: Introduce check for 4096 bit support. 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 Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 63 ++++++++++++++++++++++++++++++++++++ drivers/s390/crypto/ap_bus.h | 2 ++ 2 files changed, 65 insertions(+) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 4f37c45ee114..67302b944ab3 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -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 diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 4785d07cd447..08b9738285b4 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -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_ */ -- 2.20.1