diff options
author | Felix Beck <felix.beck@de.ibm.com> | 2011-01-05 12:47:44 +0100 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-01-05 12:47:27 +0100 |
commit | b1f933da570576d1f290ea4dc9b896404cbd285d (patch) | |
tree | f995659952ac3ccdfde34c13e7d484ced01b6777 /drivers | |
parent | [S390] hypfs: Move buffer allocation from open to read (diff) | |
download | linux-b1f933da570576d1f290ea4dc9b896404cbd285d.tar.xz linux-b1f933da570576d1f290ea4dc9b896404cbd285d.zip |
[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 <felix.beck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 63 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 2 |
2 files changed, 65 insertions, 0 deletions
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_ */ |