1 /* 2 * Copyright IBM Corp. 2012 3 * Author(s): Holger Dengler <hd@linux.vnet.ibm.com> 4 */ 5 6 #include <linux/module.h> 7 #include <linux/slab.h> 8 #include <linux/init.h> 9 #include <linux/err.h> 10 #include <linux/atomic.h> 11 #include <linux/uaccess.h> 12 13 #include "ap_bus.h" 14 #include "zcrypt_api.h" 15 #include "zcrypt_msgtype6.h" 16 #include "zcrypt_msgtype50.h" 17 #include "zcrypt_error.h" 18 #include "zcrypt_cex4.h" 19 20 #define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ 21 #define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ 22 #define CEX4A_MAX_MOD_SIZE_4K 512 /* 4096 bits */ 23 24 #define CEX4C_MIN_MOD_SIZE 16 /* 256 bits */ 25 #define CEX4C_MAX_MOD_SIZE 512 /* 4096 bits */ 26 27 #define CEX4A_SPEED_RATING 900 /* TODO new card, new speed rating */ 28 #define CEX4C_SPEED_RATING 6500 /* TODO new card, new speed rating */ 29 30 #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE 31 #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE 32 33 #define CEX4_CLEANUP_TIME (15*HZ) 34 35 static struct ap_device_id zcrypt_cex4_ids[] = { 36 { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, 37 { /* end of list */ }, 38 }; 39 40 MODULE_DEVICE_TABLE(ap, zcrypt_cex4_ids); 41 MODULE_AUTHOR("IBM Corporation"); 42 MODULE_DESCRIPTION("CEX4 Cryptographic Card device driver, " \ 43 "Copyright IBM Corp. 2012"); 44 MODULE_LICENSE("GPL"); 45 46 static int zcrypt_cex4_probe(struct ap_device *ap_dev); 47 static void zcrypt_cex4_remove(struct ap_device *ap_dev); 48 49 static struct ap_driver zcrypt_cex4_driver = { 50 .probe = zcrypt_cex4_probe, 51 .remove = zcrypt_cex4_remove, 52 .ids = zcrypt_cex4_ids, 53 .request_timeout = CEX4_CLEANUP_TIME, 54 }; 55 56 /** 57 * Probe function for CEX4 cards. It always accepts the AP device 58 * since the bus_match already checked the hardware type. 59 * @ap_dev: pointer to the AP device. 60 */ 61 static int zcrypt_cex4_probe(struct ap_device *ap_dev) 62 { 63 struct zcrypt_device *zdev = NULL; 64 int rc = 0; 65 66 switch (ap_dev->device_type) { 67 case AP_DEVICE_TYPE_CEX4: 68 if (ap_test_bit(&ap_dev->functions, AP_FUNC_ACCEL)) { 69 zdev = zcrypt_device_alloc(CEX4A_MAX_MESSAGE_SIZE); 70 if (!zdev) 71 return -ENOMEM; 72 zdev->type_string = "CEX4A"; 73 zdev->user_space_type = ZCRYPT_CEX3A; 74 zdev->min_mod_size = CEX4A_MIN_MOD_SIZE; 75 if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && 76 ap_test_bit(&ap_dev->functions, AP_FUNC_CRT4K)) { 77 zdev->max_mod_size = 78 CEX4A_MAX_MOD_SIZE_4K; 79 zdev->max_exp_bit_length = 80 CEX4A_MAX_MOD_SIZE_4K; 81 } else { 82 zdev->max_mod_size = 83 CEX4A_MAX_MOD_SIZE_2K; 84 zdev->max_exp_bit_length = 85 CEX4A_MAX_MOD_SIZE_2K; 86 } 87 zdev->short_crt = 1; 88 zdev->speed_rating = CEX4A_SPEED_RATING; 89 zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, 90 MSGTYPE50_VARIANT_DEFAULT); 91 } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_COPRO)) { 92 zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); 93 if (!zdev) 94 return -ENOMEM; 95 zdev->type_string = "CEX4C"; 96 zdev->user_space_type = ZCRYPT_CEX3C; 97 zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; 98 zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; 99 zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; 100 zdev->short_crt = 0; 101 zdev->speed_rating = CEX4C_SPEED_RATING; 102 zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, 103 MSGTYPE06_VARIANT_DEFAULT); 104 } 105 break; 106 } 107 if (!zdev) 108 return -ENODEV; 109 zdev->ap_dev = ap_dev; 110 zdev->online = 1; 111 ap_dev->reply = &zdev->reply; 112 ap_dev->private = zdev; 113 rc = zcrypt_device_register(zdev); 114 if (rc) { 115 zcrypt_msgtype_release(zdev->ops); 116 ap_dev->private = NULL; 117 zcrypt_device_free(zdev); 118 } 119 return rc; 120 } 121 122 /** 123 * This is called to remove the extended CEX4 driver information 124 * if an AP device is removed. 125 */ 126 static void zcrypt_cex4_remove(struct ap_device *ap_dev) 127 { 128 struct zcrypt_device *zdev = ap_dev->private; 129 struct zcrypt_ops *zops; 130 131 if (zdev) { 132 zops = zdev->ops; 133 zcrypt_device_unregister(zdev); 134 zcrypt_msgtype_release(zops); 135 } 136 } 137 138 int __init zcrypt_cex4_init(void) 139 { 140 return ap_driver_register(&zcrypt_cex4_driver, THIS_MODULE, "cex4"); 141 } 142 143 void __exit zcrypt_cex4_exit(void) 144 { 145 ap_driver_unregister(&zcrypt_cex4_driver); 146 } 147 148 module_init(zcrypt_cex4_init); 149 module_exit(zcrypt_cex4_exit); 150