diff options
author | Ralph Wuerthner <rwuerthn@de.ibm.com> | 2008-04-17 01:46:15 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-04-17 01:47:02 -0400 |
commit | 2f7c8bd6dc6540aa3275c0ad9f657401985c00e9 (patch) | |
tree | 12cb12d661424d332ad960113c8849b3579e7e6a /drivers/s390/crypto | |
parent | 893f11286644780fc7d6d415e537644da7bdaaf8 (diff) |
[S390] zcrypt: add support for large random numbers
This patch allows user space applications to access large amounts of
truly random data. The random data source is the build-in hardware
random number generator on the CEX2C cards.
Signed-off-by: Ralph Wuerthner <rwuerthn@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 120 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.h | 8 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_pcixcc.c | 199 |
3 files changed, 326 insertions, 1 deletions
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index e3625a47a596..b2740ff2e615 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/compat.h> | 36 | #include <linux/compat.h> |
37 | #include <asm/atomic.h> | 37 | #include <asm/atomic.h> |
38 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
39 | #include <linux/hw_random.h> | ||
39 | 40 | ||
40 | #include "zcrypt_api.h" | 41 | #include "zcrypt_api.h" |
41 | 42 | ||
@@ -52,6 +53,9 @@ static LIST_HEAD(zcrypt_device_list); | |||
52 | static int zcrypt_device_count = 0; | 53 | static int zcrypt_device_count = 0; |
53 | static atomic_t zcrypt_open_count = ATOMIC_INIT(0); | 54 | static atomic_t zcrypt_open_count = ATOMIC_INIT(0); |
54 | 55 | ||
56 | static int zcrypt_rng_device_add(void); | ||
57 | static void zcrypt_rng_device_remove(void); | ||
58 | |||
55 | /** | 59 | /** |
56 | * Device attributes common for all crypto devices. | 60 | * Device attributes common for all crypto devices. |
57 | */ | 61 | */ |
@@ -216,6 +220,22 @@ int zcrypt_device_register(struct zcrypt_device *zdev) | |||
216 | __zcrypt_increase_preference(zdev); | 220 | __zcrypt_increase_preference(zdev); |
217 | zcrypt_device_count++; | 221 | zcrypt_device_count++; |
218 | spin_unlock_bh(&zcrypt_device_lock); | 222 | spin_unlock_bh(&zcrypt_device_lock); |
223 | if (zdev->ops->rng) { | ||
224 | rc = zcrypt_rng_device_add(); | ||
225 | if (rc) | ||
226 | goto out_unregister; | ||
227 | } | ||
228 | return 0; | ||
229 | |||
230 | out_unregister: | ||
231 | spin_lock_bh(&zcrypt_device_lock); | ||
232 | zcrypt_device_count--; | ||
233 | list_del_init(&zdev->list); | ||
234 | spin_unlock_bh(&zcrypt_device_lock); | ||
235 | sysfs_remove_group(&zdev->ap_dev->device.kobj, | ||
236 | &zcrypt_device_attr_group); | ||
237 | put_device(&zdev->ap_dev->device); | ||
238 | zcrypt_device_put(zdev); | ||
219 | out: | 239 | out: |
220 | return rc; | 240 | return rc; |
221 | } | 241 | } |
@@ -226,6 +246,8 @@ EXPORT_SYMBOL(zcrypt_device_register); | |||
226 | */ | 246 | */ |
227 | void zcrypt_device_unregister(struct zcrypt_device *zdev) | 247 | void zcrypt_device_unregister(struct zcrypt_device *zdev) |
228 | { | 248 | { |
249 | if (zdev->ops->rng) | ||
250 | zcrypt_rng_device_remove(); | ||
229 | spin_lock_bh(&zcrypt_device_lock); | 251 | spin_lock_bh(&zcrypt_device_lock); |
230 | zcrypt_device_count--; | 252 | zcrypt_device_count--; |
231 | list_del_init(&zdev->list); | 253 | list_del_init(&zdev->list); |
@@ -427,6 +449,37 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
427 | return -ENODEV; | 449 | return -ENODEV; |
428 | } | 450 | } |
429 | 451 | ||
452 | static long zcrypt_rng(char *buffer) | ||
453 | { | ||
454 | struct zcrypt_device *zdev; | ||
455 | int rc; | ||
456 | |||
457 | spin_lock_bh(&zcrypt_device_lock); | ||
458 | list_for_each_entry(zdev, &zcrypt_device_list, list) { | ||
459 | if (!zdev->online || !zdev->ops->rng) | ||
460 | continue; | ||
461 | zcrypt_device_get(zdev); | ||
462 | get_device(&zdev->ap_dev->device); | ||
463 | zdev->request_count++; | ||
464 | __zcrypt_decrease_preference(zdev); | ||
465 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | ||
466 | spin_unlock_bh(&zcrypt_device_lock); | ||
467 | rc = zdev->ops->rng(zdev, buffer); | ||
468 | spin_lock_bh(&zcrypt_device_lock); | ||
469 | module_put(zdev->ap_dev->drv->driver.owner); | ||
470 | } else | ||
471 | rc = -EAGAIN; | ||
472 | zdev->request_count--; | ||
473 | __zcrypt_increase_preference(zdev); | ||
474 | put_device(&zdev->ap_dev->device); | ||
475 | zcrypt_device_put(zdev); | ||
476 | spin_unlock_bh(&zcrypt_device_lock); | ||
477 | return rc; | ||
478 | } | ||
479 | spin_unlock_bh(&zcrypt_device_lock); | ||
480 | return -ENODEV; | ||
481 | } | ||
482 | |||
430 | static void zcrypt_status_mask(char status[AP_DEVICES]) | 483 | static void zcrypt_status_mask(char status[AP_DEVICES]) |
431 | { | 484 | { |
432 | struct zcrypt_device *zdev; | 485 | struct zcrypt_device *zdev; |
@@ -1041,6 +1094,73 @@ out: | |||
1041 | return count; | 1094 | return count; |
1042 | } | 1095 | } |
1043 | 1096 | ||
1097 | static int zcrypt_rng_device_count; | ||
1098 | static u32 *zcrypt_rng_buffer; | ||
1099 | static int zcrypt_rng_buffer_index; | ||
1100 | static DEFINE_MUTEX(zcrypt_rng_mutex); | ||
1101 | |||
1102 | static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data) | ||
1103 | { | ||
1104 | int rc; | ||
1105 | |||
1106 | /** | ||
1107 | * We don't need locking here because the RNG API guarantees serialized | ||
1108 | * read method calls. | ||
1109 | */ | ||
1110 | if (zcrypt_rng_buffer_index == 0) { | ||
1111 | rc = zcrypt_rng((char *) zcrypt_rng_buffer); | ||
1112 | if (rc < 0) | ||
1113 | return -EIO; | ||
1114 | zcrypt_rng_buffer_index = rc / sizeof *data; | ||
1115 | } | ||
1116 | *data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index]; | ||
1117 | return sizeof *data; | ||
1118 | } | ||
1119 | |||
1120 | static struct hwrng zcrypt_rng_dev = { | ||
1121 | .name = "zcrypt", | ||
1122 | .data_read = zcrypt_rng_data_read, | ||
1123 | }; | ||
1124 | |||
1125 | static int zcrypt_rng_device_add(void) | ||
1126 | { | ||
1127 | int rc = 0; | ||
1128 | |||
1129 | mutex_lock(&zcrypt_rng_mutex); | ||
1130 | if (zcrypt_rng_device_count == 0) { | ||
1131 | zcrypt_rng_buffer = (u32 *) get_zeroed_page(GFP_KERNEL); | ||
1132 | if (!zcrypt_rng_buffer) { | ||
1133 | rc = -ENOMEM; | ||
1134 | goto out; | ||
1135 | } | ||
1136 | zcrypt_rng_buffer_index = 0; | ||
1137 | rc = hwrng_register(&zcrypt_rng_dev); | ||
1138 | if (rc) | ||
1139 | goto out_free; | ||
1140 | zcrypt_rng_device_count = 1; | ||
1141 | } else | ||
1142 | zcrypt_rng_device_count++; | ||
1143 | mutex_unlock(&zcrypt_rng_mutex); | ||
1144 | return 0; | ||
1145 | |||
1146 | out_free: | ||
1147 | free_page((unsigned long) zcrypt_rng_buffer); | ||
1148 | out: | ||
1149 | mutex_unlock(&zcrypt_rng_mutex); | ||
1150 | return rc; | ||
1151 | } | ||
1152 | |||
1153 | static void zcrypt_rng_device_remove(void) | ||
1154 | { | ||
1155 | mutex_lock(&zcrypt_rng_mutex); | ||
1156 | zcrypt_rng_device_count--; | ||
1157 | if (zcrypt_rng_device_count == 0) { | ||
1158 | hwrng_unregister(&zcrypt_rng_dev); | ||
1159 | free_page((unsigned long) zcrypt_rng_buffer); | ||
1160 | } | ||
1161 | mutex_unlock(&zcrypt_rng_mutex); | ||
1162 | } | ||
1163 | |||
1044 | /** | 1164 | /** |
1045 | * The module initialization code. | 1165 | * The module initialization code. |
1046 | */ | 1166 | */ |
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index de4877ee618f..0e948528a73a 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h | |||
@@ -100,6 +100,13 @@ struct ica_z90_status { | |||
100 | #define ZCRYPT_CEX2C 5 | 100 | #define ZCRYPT_CEX2C 5 |
101 | #define ZCRYPT_CEX2A 6 | 101 | #define ZCRYPT_CEX2A 6 |
102 | 102 | ||
103 | /** | ||
104 | * Large random numbers are pulled in 4096 byte chunks from the crypto cards | ||
105 | * and stored in a page. Be carefull when increasing this buffer due to size | ||
106 | * limitations for AP requests. | ||
107 | */ | ||
108 | #define ZCRYPT_RNG_BUFFER_SIZE 4096 | ||
109 | |||
103 | struct zcrypt_device; | 110 | struct zcrypt_device; |
104 | 111 | ||
105 | struct zcrypt_ops { | 112 | struct zcrypt_ops { |
@@ -107,6 +114,7 @@ struct zcrypt_ops { | |||
107 | long (*rsa_modexpo_crt)(struct zcrypt_device *, | 114 | long (*rsa_modexpo_crt)(struct zcrypt_device *, |
108 | struct ica_rsa_modexpo_crt *); | 115 | struct ica_rsa_modexpo_crt *); |
109 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); | 116 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); |
117 | long (*rng)(struct zcrypt_device *, char *); | ||
110 | }; | 118 | }; |
111 | 119 | ||
112 | struct zcrypt_device { | 120 | struct zcrypt_device { |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 70b9ddc8cf9d..3674bfa82b65 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -356,6 +356,55 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | |||
356 | } | 356 | } |
357 | 357 | ||
358 | /** | 358 | /** |
359 | * Prepare a type6 CPRB message for random number generation | ||
360 | * | ||
361 | * @ap_dev: AP device pointer | ||
362 | * @ap_msg: pointer to AP message | ||
363 | */ | ||
364 | static void rng_type6CPRB_msgX(struct ap_device *ap_dev, | ||
365 | struct ap_message *ap_msg, | ||
366 | unsigned random_number_length) | ||
367 | { | ||
368 | struct { | ||
369 | struct type6_hdr hdr; | ||
370 | struct CPRBX cprbx; | ||
371 | char function_code[2]; | ||
372 | short int rule_length; | ||
373 | char rule[8]; | ||
374 | short int verb_length; | ||
375 | short int key_length; | ||
376 | } __attribute__((packed)) *msg = ap_msg->message; | ||
377 | static struct type6_hdr static_type6_hdrX = { | ||
378 | .type = 0x06, | ||
379 | .offset1 = 0x00000058, | ||
380 | .agent_id = {'C', 'A'}, | ||
381 | .function_code = {'R', 'L'}, | ||
382 | .ToCardLen1 = sizeof *msg - sizeof(msg->hdr), | ||
383 | .FromCardLen1 = sizeof *msg - sizeof(msg->hdr), | ||
384 | }; | ||
385 | static struct CPRBX static_cprbx = { | ||
386 | .cprb_len = 0x00dc, | ||
387 | .cprb_ver_id = 0x02, | ||
388 | .func_id = {0x54, 0x32}, | ||
389 | .req_parml = sizeof *msg - sizeof(msg->hdr) - | ||
390 | sizeof(msg->cprbx), | ||
391 | .rpl_msgbl = sizeof *msg - sizeof(msg->hdr), | ||
392 | }; | ||
393 | |||
394 | msg->hdr = static_type6_hdrX; | ||
395 | msg->hdr.FromCardLen2 = random_number_length, | ||
396 | msg->cprbx = static_cprbx; | ||
397 | msg->cprbx.rpl_datal = random_number_length, | ||
398 | msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); | ||
399 | memcpy(msg->function_code, msg->hdr.function_code, 0x02); | ||
400 | msg->rule_length = 0x0a; | ||
401 | memcpy(msg->rule, "RANDOM ", 8); | ||
402 | msg->verb_length = 0x02; | ||
403 | msg->key_length = 0x02; | ||
404 | ap_msg->length = sizeof *msg; | ||
405 | } | ||
406 | |||
407 | /** | ||
359 | * Copy results from a type 86 ICA reply message back to user space. | 408 | * Copy results from a type 86 ICA reply message back to user space. |
360 | * | 409 | * |
361 | * @zdev: crypto device pointer | 410 | * @zdev: crypto device pointer |
@@ -509,6 +558,26 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev, | |||
509 | return 0; | 558 | return 0; |
510 | } | 559 | } |
511 | 560 | ||
561 | static int convert_type86_rng(struct zcrypt_device *zdev, | ||
562 | struct ap_message *reply, | ||
563 | char *buffer) | ||
564 | { | ||
565 | struct { | ||
566 | struct type86_hdr hdr; | ||
567 | struct type86_fmt2_ext fmt2; | ||
568 | struct CPRBX cprbx; | ||
569 | } __attribute__((packed)) *msg = reply->message; | ||
570 | char *data = reply->message; | ||
571 | |||
572 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) { | ||
573 | PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n", | ||
574 | rc, rs); | ||
575 | return -EINVAL; | ||
576 | } | ||
577 | memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2); | ||
578 | return msg->fmt2.count2; | ||
579 | } | ||
580 | |||
512 | static int convert_response_ica(struct zcrypt_device *zdev, | 581 | static int convert_response_ica(struct zcrypt_device *zdev, |
513 | struct ap_message *reply, | 582 | struct ap_message *reply, |
514 | char __user *outputdata, | 583 | char __user *outputdata, |
@@ -567,6 +636,31 @@ static int convert_response_xcrb(struct zcrypt_device *zdev, | |||
567 | } | 636 | } |
568 | } | 637 | } |
569 | 638 | ||
639 | static int convert_response_rng(struct zcrypt_device *zdev, | ||
640 | struct ap_message *reply, | ||
641 | char *data) | ||
642 | { | ||
643 | struct type86x_reply *msg = reply->message; | ||
644 | |||
645 | switch (msg->hdr.type) { | ||
646 | case TYPE82_RSP_CODE: | ||
647 | case TYPE88_RSP_CODE: | ||
648 | return -EINVAL; | ||
649 | case TYPE86_RSP_CODE: | ||
650 | if (msg->hdr.reply_code) | ||
651 | return -EINVAL; | ||
652 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
653 | return convert_type86_rng(zdev, reply, data); | ||
654 | /* no break, incorrect cprb version is an unknown response */ | ||
655 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
656 | PRINTK("Unrecognized Message Header: %08x%08x\n", | ||
657 | *(unsigned int *) reply->message, | ||
658 | *(unsigned int *) (reply->message+4)); | ||
659 | zdev->online = 0; | ||
660 | return -EAGAIN; /* repeat the request on a different device. */ | ||
661 | } | ||
662 | } | ||
663 | |||
570 | /** | 664 | /** |
571 | * This function is called from the AP bus code after a crypto request | 665 | * This function is called from the AP bus code after a crypto request |
572 | * "msg" has finished with the reply message "reply". | 666 | * "msg" has finished with the reply message "reply". |
@@ -736,6 +830,42 @@ out_free: | |||
736 | } | 830 | } |
737 | 831 | ||
738 | /** | 832 | /** |
833 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
834 | * device to generate random data. | ||
835 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
836 | * PCIXCC/CEX2C device to the request distributor | ||
837 | * @buffer: pointer to a memory page to return random data | ||
838 | */ | ||
839 | |||
840 | static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev, | ||
841 | char *buffer) | ||
842 | { | ||
843 | struct ap_message ap_msg; | ||
844 | struct response_type resp_type = { | ||
845 | .type = PCIXCC_RESPONSE_TYPE_XCRB, | ||
846 | }; | ||
847 | int rc; | ||
848 | |||
849 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); | ||
850 | if (!ap_msg.message) | ||
851 | return -ENOMEM; | ||
852 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
853 | atomic_inc_return(&zcrypt_step); | ||
854 | ap_msg.private = &resp_type; | ||
855 | rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); | ||
856 | init_completion(&resp_type.work); | ||
857 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
858 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
859 | if (rc == 0) | ||
860 | rc = convert_response_rng(zdev, &ap_msg, buffer); | ||
861 | else | ||
862 | /* Signal pending. */ | ||
863 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
864 | kfree(ap_msg.message); | ||
865 | return rc; | ||
866 | } | ||
867 | |||
868 | /** | ||
739 | * The crypto operations for a PCIXCC/CEX2C card. | 869 | * The crypto operations for a PCIXCC/CEX2C card. |
740 | */ | 870 | */ |
741 | static struct zcrypt_ops zcrypt_pcixcc_ops = { | 871 | static struct zcrypt_ops zcrypt_pcixcc_ops = { |
@@ -744,6 +874,13 @@ static struct zcrypt_ops zcrypt_pcixcc_ops = { | |||
744 | .send_cprb = zcrypt_pcixcc_send_cprb, | 874 | .send_cprb = zcrypt_pcixcc_send_cprb, |
745 | }; | 875 | }; |
746 | 876 | ||
877 | static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = { | ||
878 | .rsa_modexpo = zcrypt_pcixcc_modexpo, | ||
879 | .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, | ||
880 | .send_cprb = zcrypt_pcixcc_send_cprb, | ||
881 | .rng = zcrypt_pcixcc_rng, | ||
882 | }; | ||
883 | |||
747 | /** | 884 | /** |
748 | * Micro-code detection function. Its sends a message to a pcixcc card | 885 | * Micro-code detection function. Its sends a message to a pcixcc card |
749 | * to find out the microcode level. | 886 | * to find out the microcode level. |
@@ -859,6 +996,58 @@ out_free: | |||
859 | } | 996 | } |
860 | 997 | ||
861 | /** | 998 | /** |
999 | * Large random number detection function. Its sends a message to a pcixcc | ||
1000 | * card to find out if large random numbers are supported. | ||
1001 | * @ap_dev: pointer to the AP device. | ||
1002 | * | ||
1003 | * Returns 1 if large random numbers are supported, 0 if not and < 0 on error. | ||
1004 | */ | ||
1005 | static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev) | ||
1006 | { | ||
1007 | struct ap_message ap_msg; | ||
1008 | unsigned long long psmid; | ||
1009 | struct { | ||
1010 | struct type86_hdr hdr; | ||
1011 | struct type86_fmt2_ext fmt2; | ||
1012 | struct CPRBX cprbx; | ||
1013 | } __attribute__((packed)) *reply; | ||
1014 | int rc, i; | ||
1015 | |||
1016 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | ||
1017 | if (!ap_msg.message) | ||
1018 | return -ENOMEM; | ||
1019 | |||
1020 | rng_type6CPRB_msgX(ap_dev, &ap_msg, 4); | ||
1021 | rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message, | ||
1022 | ap_msg.length); | ||
1023 | if (rc) | ||
1024 | goto out_free; | ||
1025 | |||
1026 | /* Wait for the test message to complete. */ | ||
1027 | for (i = 0; i < 2 * HZ; i++) { | ||
1028 | msleep(1000 / HZ); | ||
1029 | rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096); | ||
1030 | if (rc == 0 && psmid == 0x0102030405060708ULL) | ||
1031 | break; | ||
1032 | } | ||
1033 | |||
1034 | if (i >= 2 * HZ) { | ||
1035 | /* Got no answer. */ | ||
1036 | rc = -ENODEV; | ||
1037 | goto out_free; | ||
1038 | } | ||
1039 | |||
1040 | reply = ap_msg.message; | ||
1041 | if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) | ||
1042 | rc = 1; | ||
1043 | else | ||
1044 | rc = 0; | ||
1045 | out_free: | ||
1046 | free_page((unsigned long) ap_msg.message); | ||
1047 | return rc; | ||
1048 | } | ||
1049 | |||
1050 | /** | ||
862 | * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device | 1051 | * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device |
863 | * since the bus_match already checked the hardware type. The PCIXCC | 1052 | * since the bus_match already checked the hardware type. The PCIXCC |
864 | * cards come in two flavours: micro code level 2 and micro code level 3. | 1053 | * cards come in two flavours: micro code level 2 and micro code level 3. |
@@ -874,7 +1063,6 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
874 | if (!zdev) | 1063 | if (!zdev) |
875 | return -ENOMEM; | 1064 | return -ENOMEM; |
876 | zdev->ap_dev = ap_dev; | 1065 | zdev->ap_dev = ap_dev; |
877 | zdev->ops = &zcrypt_pcixcc_ops; | ||
878 | zdev->online = 1; | 1066 | zdev->online = 1; |
879 | if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) { | 1067 | if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) { |
880 | rc = zcrypt_pcixcc_mcl(ap_dev); | 1068 | rc = zcrypt_pcixcc_mcl(ap_dev); |
@@ -901,6 +1089,15 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
901 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; | 1089 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; |
902 | zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; | 1090 | zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; |
903 | } | 1091 | } |
1092 | rc = zcrypt_pcixcc_rng_supported(ap_dev); | ||
1093 | if (rc < 0) { | ||
1094 | zcrypt_device_free(zdev); | ||
1095 | return rc; | ||
1096 | } | ||
1097 | if (rc) | ||
1098 | zdev->ops = &zcrypt_pcixcc_with_rng_ops; | ||
1099 | else | ||
1100 | zdev->ops = &zcrypt_pcixcc_ops; | ||
904 | ap_dev->reply = &zdev->reply; | 1101 | ap_dev->reply = &zdev->reply; |
905 | ap_dev->private = zdev; | 1102 | ap_dev->private = zdev; |
906 | rc = zcrypt_device_register(zdev); | 1103 | rc = zcrypt_device_register(zdev); |