18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2001, 2018 48c2ecf20Sopenharmony_ci * Author(s): Robert Burroughs 58c2ecf20Sopenharmony_ci * Eric Rossman (edrossma@us.ibm.com) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) 88c2ecf20Sopenharmony_ci * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> 98c2ecf20Sopenharmony_ci * Ralph Wuerthner <rwuerthn@de.ibm.com> 108c2ecf20Sopenharmony_ci * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/err.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/atomic.h> 198c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 208c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "ap_bus.h" 238c2ecf20Sopenharmony_ci#include "zcrypt_api.h" 248c2ecf20Sopenharmony_ci#include "zcrypt_error.h" 258c2ecf20Sopenharmony_ci#include "zcrypt_msgtype6.h" 268c2ecf20Sopenharmony_ci#include "zcrypt_cex2c.h" 278c2ecf20Sopenharmony_ci#include "zcrypt_cca_key.h" 288c2ecf20Sopenharmony_ci#include "zcrypt_ccamisc.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define CEX2C_MIN_MOD_SIZE 16 /* 128 bits */ 318c2ecf20Sopenharmony_ci#define CEX2C_MAX_MOD_SIZE 256 /* 2048 bits */ 328c2ecf20Sopenharmony_ci#define CEX3C_MIN_MOD_SIZE 16 /* 128 bits */ 338c2ecf20Sopenharmony_ci#define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */ 348c2ecf20Sopenharmony_ci#define CEX2C_MAX_XCRB_MESSAGE_SIZE (12*1024) 358c2ecf20Sopenharmony_ci#define CEX2C_CLEANUP_TIME (15*HZ) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciMODULE_AUTHOR("IBM Corporation"); 388c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CEX2C/CEX3C Cryptographic Coprocessor device driver, " \ 398c2ecf20Sopenharmony_ci "Copyright IBM Corp. 2001, 2018"); 408c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic struct ap_device_id zcrypt_cex2c_card_ids[] = { 438c2ecf20Sopenharmony_ci { .dev_type = AP_DEVICE_TYPE_CEX2C, 448c2ecf20Sopenharmony_ci .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, 458c2ecf20Sopenharmony_ci { .dev_type = AP_DEVICE_TYPE_CEX3C, 468c2ecf20Sopenharmony_ci .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, 478c2ecf20Sopenharmony_ci { /* end of list */ }, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(ap, zcrypt_cex2c_card_ids); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic struct ap_device_id zcrypt_cex2c_queue_ids[] = { 538c2ecf20Sopenharmony_ci { .dev_type = AP_DEVICE_TYPE_CEX2C, 548c2ecf20Sopenharmony_ci .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 558c2ecf20Sopenharmony_ci { .dev_type = AP_DEVICE_TYPE_CEX3C, 568c2ecf20Sopenharmony_ci .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 578c2ecf20Sopenharmony_ci { /* end of list */ }, 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* 638c2ecf20Sopenharmony_ci * CCA card additional device attributes 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_cistatic ssize_t cca_serialnr_show(struct device *dev, 668c2ecf20Sopenharmony_ci struct device_attribute *attr, 678c2ecf20Sopenharmony_ci char *buf) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct cca_info ci; 708c2ecf20Sopenharmony_ci struct ap_card *ac = to_ap_card(dev); 718c2ecf20Sopenharmony_ci struct zcrypt_card *zc = ac->private; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci memset(&ci, 0, sizeof(ci)); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (ap_domain_index >= 0) 768c2ecf20Sopenharmony_ci cca_get_info(ac->id, ap_domain_index, &ci, zc->online); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", ci.serial); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_cca_serialnr = 828c2ecf20Sopenharmony_ci __ATTR(serialnr, 0444, cca_serialnr_show, NULL); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic struct attribute *cca_card_attrs[] = { 858c2ecf20Sopenharmony_ci &dev_attr_cca_serialnr.attr, 868c2ecf20Sopenharmony_ci NULL, 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic const struct attribute_group cca_card_attr_grp = { 908c2ecf20Sopenharmony_ci .attrs = cca_card_attrs, 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * CCA queue additional device attributes 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistatic ssize_t cca_mkvps_show(struct device *dev, 978c2ecf20Sopenharmony_ci struct device_attribute *attr, 988c2ecf20Sopenharmony_ci char *buf) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci int n = 0; 1018c2ecf20Sopenharmony_ci struct cca_info ci; 1028c2ecf20Sopenharmony_ci struct zcrypt_queue *zq = to_ap_queue(dev)->private; 1038c2ecf20Sopenharmony_ci static const char * const cao_state[] = { "invalid", "valid" }; 1048c2ecf20Sopenharmony_ci static const char * const new_state[] = { "empty", "partial", "full" }; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci memset(&ci, 0, sizeof(ci)); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci cca_get_info(AP_QID_CARD(zq->queue->qid), 1098c2ecf20Sopenharmony_ci AP_QID_QUEUE(zq->queue->qid), 1108c2ecf20Sopenharmony_ci &ci, zq->online); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') 1138c2ecf20Sopenharmony_ci n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n", 1148c2ecf20Sopenharmony_ci new_state[ci.new_aes_mk_state - '1'], 1158c2ecf20Sopenharmony_ci ci.new_aes_mkvp); 1168c2ecf20Sopenharmony_ci else 1178c2ecf20Sopenharmony_ci n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n"); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') 1208c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, 1218c2ecf20Sopenharmony_ci "AES CUR: %s 0x%016llx\n", 1228c2ecf20Sopenharmony_ci cao_state[ci.cur_aes_mk_state - '1'], 1238c2ecf20Sopenharmony_ci ci.cur_aes_mkvp); 1248c2ecf20Sopenharmony_ci else 1258c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n"); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') 1288c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, 1298c2ecf20Sopenharmony_ci "AES OLD: %s 0x%016llx\n", 1308c2ecf20Sopenharmony_ci cao_state[ci.old_aes_mk_state - '1'], 1318c2ecf20Sopenharmony_ci ci.old_aes_mkvp); 1328c2ecf20Sopenharmony_ci else 1338c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n"); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') 1368c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, 1378c2ecf20Sopenharmony_ci "APKA NEW: %s 0x%016llx\n", 1388c2ecf20Sopenharmony_ci new_state[ci.new_apka_mk_state - '1'], 1398c2ecf20Sopenharmony_ci ci.new_apka_mkvp); 1408c2ecf20Sopenharmony_ci else 1418c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n"); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') 1448c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, 1458c2ecf20Sopenharmony_ci "APKA CUR: %s 0x%016llx\n", 1468c2ecf20Sopenharmony_ci cao_state[ci.cur_apka_mk_state - '1'], 1478c2ecf20Sopenharmony_ci ci.cur_apka_mkvp); 1488c2ecf20Sopenharmony_ci else 1498c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n"); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') 1528c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, 1538c2ecf20Sopenharmony_ci "APKA OLD: %s 0x%016llx\n", 1548c2ecf20Sopenharmony_ci cao_state[ci.old_apka_mk_state - '1'], 1558c2ecf20Sopenharmony_ci ci.old_apka_mkvp); 1568c2ecf20Sopenharmony_ci else 1578c2ecf20Sopenharmony_ci n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n"); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return n; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_cca_mkvps = 1638c2ecf20Sopenharmony_ci __ATTR(mkvps, 0444, cca_mkvps_show, NULL); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic struct attribute *cca_queue_attrs[] = { 1668c2ecf20Sopenharmony_ci &dev_attr_cca_mkvps.attr, 1678c2ecf20Sopenharmony_ci NULL, 1688c2ecf20Sopenharmony_ci}; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic const struct attribute_group cca_queue_attr_grp = { 1718c2ecf20Sopenharmony_ci .attrs = cca_queue_attrs, 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/** 1758c2ecf20Sopenharmony_ci * Large random number detection function. Its sends a message to a CEX2C/CEX3C 1768c2ecf20Sopenharmony_ci * card to find out if large random numbers are supported. 1778c2ecf20Sopenharmony_ci * @ap_dev: pointer to the AP device. 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Returns 1 if large random numbers are supported, 0 if not and < 0 on error. 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_cistatic int zcrypt_cex2c_rng_supported(struct ap_queue *aq) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct ap_message ap_msg; 1848c2ecf20Sopenharmony_ci unsigned long long psmid; 1858c2ecf20Sopenharmony_ci unsigned int domain; 1868c2ecf20Sopenharmony_ci struct { 1878c2ecf20Sopenharmony_ci struct type86_hdr hdr; 1888c2ecf20Sopenharmony_ci struct type86_fmt2_ext fmt2; 1898c2ecf20Sopenharmony_ci struct CPRBX cprbx; 1908c2ecf20Sopenharmony_ci } __packed *reply; 1918c2ecf20Sopenharmony_ci struct { 1928c2ecf20Sopenharmony_ci struct type6_hdr hdr; 1938c2ecf20Sopenharmony_ci struct CPRBX cprbx; 1948c2ecf20Sopenharmony_ci char function_code[2]; 1958c2ecf20Sopenharmony_ci short int rule_length; 1968c2ecf20Sopenharmony_ci char rule[8]; 1978c2ecf20Sopenharmony_ci short int verb_length; 1988c2ecf20Sopenharmony_ci short int key_length; 1998c2ecf20Sopenharmony_ci } __packed *msg; 2008c2ecf20Sopenharmony_ci int rc, i; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci ap_init_message(&ap_msg); 2038c2ecf20Sopenharmony_ci ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); 2048c2ecf20Sopenharmony_ci if (!ap_msg.msg) 2058c2ecf20Sopenharmony_ci return -ENOMEM; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rng_type6CPRB_msgX(&ap_msg, 4, &domain); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci msg = ap_msg.msg; 2108c2ecf20Sopenharmony_ci msg->cprbx.domain = AP_QID_QUEUE(aq->qid); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.msg, ap_msg.len); 2138c2ecf20Sopenharmony_ci if (rc) 2148c2ecf20Sopenharmony_ci goto out_free; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Wait for the test message to complete. */ 2178c2ecf20Sopenharmony_ci for (i = 0; i < 2 * HZ; i++) { 2188c2ecf20Sopenharmony_ci msleep(1000 / HZ); 2198c2ecf20Sopenharmony_ci rc = ap_recv(aq->qid, &psmid, ap_msg.msg, 4096); 2208c2ecf20Sopenharmony_ci if (rc == 0 && psmid == 0x0102030405060708ULL) 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (i >= 2 * HZ) { 2258c2ecf20Sopenharmony_ci /* Got no answer. */ 2268c2ecf20Sopenharmony_ci rc = -ENODEV; 2278c2ecf20Sopenharmony_ci goto out_free; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci reply = ap_msg.msg; 2318c2ecf20Sopenharmony_ci if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) 2328c2ecf20Sopenharmony_ci rc = 1; 2338c2ecf20Sopenharmony_ci else 2348c2ecf20Sopenharmony_ci rc = 0; 2358c2ecf20Sopenharmony_ciout_free: 2368c2ecf20Sopenharmony_ci free_page((unsigned long) ap_msg.msg); 2378c2ecf20Sopenharmony_ci return rc; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/** 2418c2ecf20Sopenharmony_ci * Probe function for CEX2C/CEX3C card devices. It always accepts the 2428c2ecf20Sopenharmony_ci * AP device since the bus_match already checked the hardware type. 2438c2ecf20Sopenharmony_ci * @ap_dev: pointer to the AP card device. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_cistatic int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci /* 2488c2ecf20Sopenharmony_ci * Normalized speed ratings per crypto adapter 2498c2ecf20Sopenharmony_ci * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci static const int CEX2C_SPEED_IDX[] = { 2528c2ecf20Sopenharmony_ci 1000, 1400, 2400, 1100, 1500, 2600, 100, 12}; 2538c2ecf20Sopenharmony_ci static const int CEX3C_SPEED_IDX[] = { 2548c2ecf20Sopenharmony_ci 500, 700, 1400, 550, 800, 1500, 80, 10}; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci struct ap_card *ac = to_ap_card(&ap_dev->device); 2578c2ecf20Sopenharmony_ci struct zcrypt_card *zc; 2588c2ecf20Sopenharmony_ci int rc = 0; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci zc = zcrypt_card_alloc(); 2618c2ecf20Sopenharmony_ci if (!zc) 2628c2ecf20Sopenharmony_ci return -ENOMEM; 2638c2ecf20Sopenharmony_ci zc->card = ac; 2648c2ecf20Sopenharmony_ci ac->private = zc; 2658c2ecf20Sopenharmony_ci switch (ac->ap_dev.device_type) { 2668c2ecf20Sopenharmony_ci case AP_DEVICE_TYPE_CEX2C: 2678c2ecf20Sopenharmony_ci zc->user_space_type = ZCRYPT_CEX2C; 2688c2ecf20Sopenharmony_ci zc->type_string = "CEX2C"; 2698c2ecf20Sopenharmony_ci zc->speed_rating = CEX2C_SPEED_IDX; 2708c2ecf20Sopenharmony_ci zc->min_mod_size = CEX2C_MIN_MOD_SIZE; 2718c2ecf20Sopenharmony_ci zc->max_mod_size = CEX2C_MAX_MOD_SIZE; 2728c2ecf20Sopenharmony_ci zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE; 2738c2ecf20Sopenharmony_ci break; 2748c2ecf20Sopenharmony_ci case AP_DEVICE_TYPE_CEX3C: 2758c2ecf20Sopenharmony_ci zc->user_space_type = ZCRYPT_CEX3C; 2768c2ecf20Sopenharmony_ci zc->type_string = "CEX3C"; 2778c2ecf20Sopenharmony_ci zc->speed_rating = CEX3C_SPEED_IDX; 2788c2ecf20Sopenharmony_ci zc->min_mod_size = CEX3C_MIN_MOD_SIZE; 2798c2ecf20Sopenharmony_ci zc->max_mod_size = CEX3C_MAX_MOD_SIZE; 2808c2ecf20Sopenharmony_ci zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE; 2818c2ecf20Sopenharmony_ci break; 2828c2ecf20Sopenharmony_ci default: 2838c2ecf20Sopenharmony_ci zcrypt_card_free(zc); 2848c2ecf20Sopenharmony_ci return -ENODEV; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci zc->online = 1; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci rc = zcrypt_card_register(zc); 2898c2ecf20Sopenharmony_ci if (rc) { 2908c2ecf20Sopenharmony_ci ac->private = NULL; 2918c2ecf20Sopenharmony_ci zcrypt_card_free(zc); 2928c2ecf20Sopenharmony_ci return rc; 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { 2968c2ecf20Sopenharmony_ci rc = sysfs_create_group(&ap_dev->device.kobj, 2978c2ecf20Sopenharmony_ci &cca_card_attr_grp); 2988c2ecf20Sopenharmony_ci if (rc) { 2998c2ecf20Sopenharmony_ci zcrypt_card_unregister(zc); 3008c2ecf20Sopenharmony_ci ac->private = NULL; 3018c2ecf20Sopenharmony_ci zcrypt_card_free(zc); 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return rc; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/** 3098c2ecf20Sopenharmony_ci * This is called to remove the CEX2C/CEX3C card driver information 3108c2ecf20Sopenharmony_ci * if an AP card device is removed. 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_cistatic void zcrypt_cex2c_card_remove(struct ap_device *ap_dev) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci struct ap_card *ac = to_ap_card(&ap_dev->device); 3158c2ecf20Sopenharmony_ci struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) 3188c2ecf20Sopenharmony_ci sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp); 3198c2ecf20Sopenharmony_ci if (zc) 3208c2ecf20Sopenharmony_ci zcrypt_card_unregister(zc); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic struct ap_driver zcrypt_cex2c_card_driver = { 3248c2ecf20Sopenharmony_ci .probe = zcrypt_cex2c_card_probe, 3258c2ecf20Sopenharmony_ci .remove = zcrypt_cex2c_card_remove, 3268c2ecf20Sopenharmony_ci .ids = zcrypt_cex2c_card_ids, 3278c2ecf20Sopenharmony_ci .flags = AP_DRIVER_FLAG_DEFAULT, 3288c2ecf20Sopenharmony_ci}; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci/** 3318c2ecf20Sopenharmony_ci * Probe function for CEX2C/CEX3C queue devices. It always accepts the 3328c2ecf20Sopenharmony_ci * AP device since the bus_match already checked the hardware type. 3338c2ecf20Sopenharmony_ci * @ap_dev: pointer to the AP card device. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_cistatic int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct ap_queue *aq = to_ap_queue(&ap_dev->device); 3388c2ecf20Sopenharmony_ci struct zcrypt_queue *zq; 3398c2ecf20Sopenharmony_ci int rc; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci zq = zcrypt_queue_alloc(CEX2C_MAX_XCRB_MESSAGE_SIZE); 3428c2ecf20Sopenharmony_ci if (!zq) 3438c2ecf20Sopenharmony_ci return -ENOMEM; 3448c2ecf20Sopenharmony_ci zq->queue = aq; 3458c2ecf20Sopenharmony_ci zq->online = 1; 3468c2ecf20Sopenharmony_ci atomic_set(&zq->load, 0); 3478c2ecf20Sopenharmony_ci ap_rapq(aq->qid); 3488c2ecf20Sopenharmony_ci rc = zcrypt_cex2c_rng_supported(aq); 3498c2ecf20Sopenharmony_ci if (rc < 0) { 3508c2ecf20Sopenharmony_ci zcrypt_queue_free(zq); 3518c2ecf20Sopenharmony_ci return rc; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci if (rc) 3548c2ecf20Sopenharmony_ci zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, 3558c2ecf20Sopenharmony_ci MSGTYPE06_VARIANT_DEFAULT); 3568c2ecf20Sopenharmony_ci else 3578c2ecf20Sopenharmony_ci zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, 3588c2ecf20Sopenharmony_ci MSGTYPE06_VARIANT_NORNG); 3598c2ecf20Sopenharmony_ci ap_queue_init_state(aq); 3608c2ecf20Sopenharmony_ci ap_queue_init_reply(aq, &zq->reply); 3618c2ecf20Sopenharmony_ci aq->request_timeout = CEX2C_CLEANUP_TIME; 3628c2ecf20Sopenharmony_ci aq->private = zq; 3638c2ecf20Sopenharmony_ci rc = zcrypt_queue_register(zq); 3648c2ecf20Sopenharmony_ci if (rc) { 3658c2ecf20Sopenharmony_ci aq->private = NULL; 3668c2ecf20Sopenharmony_ci zcrypt_queue_free(zq); 3678c2ecf20Sopenharmony_ci return rc; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { 3718c2ecf20Sopenharmony_ci rc = sysfs_create_group(&ap_dev->device.kobj, 3728c2ecf20Sopenharmony_ci &cca_queue_attr_grp); 3738c2ecf20Sopenharmony_ci if (rc) { 3748c2ecf20Sopenharmony_ci zcrypt_queue_unregister(zq); 3758c2ecf20Sopenharmony_ci aq->private = NULL; 3768c2ecf20Sopenharmony_ci zcrypt_queue_free(zq); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci return rc; 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/** 3848c2ecf20Sopenharmony_ci * This is called to remove the CEX2C/CEX3C queue driver information 3858c2ecf20Sopenharmony_ci * if an AP queue device is removed. 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_cistatic void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct ap_queue *aq = to_ap_queue(&ap_dev->device); 3908c2ecf20Sopenharmony_ci struct zcrypt_queue *zq = aq->private; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) 3938c2ecf20Sopenharmony_ci sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp); 3948c2ecf20Sopenharmony_ci if (zq) 3958c2ecf20Sopenharmony_ci zcrypt_queue_unregister(zq); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic struct ap_driver zcrypt_cex2c_queue_driver = { 3998c2ecf20Sopenharmony_ci .probe = zcrypt_cex2c_queue_probe, 4008c2ecf20Sopenharmony_ci .remove = zcrypt_cex2c_queue_remove, 4018c2ecf20Sopenharmony_ci .ids = zcrypt_cex2c_queue_ids, 4028c2ecf20Sopenharmony_ci .flags = AP_DRIVER_FLAG_DEFAULT, 4038c2ecf20Sopenharmony_ci}; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ciint __init zcrypt_cex2c_init(void) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci int rc; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci rc = ap_driver_register(&zcrypt_cex2c_card_driver, 4108c2ecf20Sopenharmony_ci THIS_MODULE, "cex2card"); 4118c2ecf20Sopenharmony_ci if (rc) 4128c2ecf20Sopenharmony_ci return rc; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci rc = ap_driver_register(&zcrypt_cex2c_queue_driver, 4158c2ecf20Sopenharmony_ci THIS_MODULE, "cex2cqueue"); 4168c2ecf20Sopenharmony_ci if (rc) 4178c2ecf20Sopenharmony_ci ap_driver_unregister(&zcrypt_cex2c_card_driver); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return rc; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_civoid zcrypt_cex2c_exit(void) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci ap_driver_unregister(&zcrypt_cex2c_queue_driver); 4258c2ecf20Sopenharmony_ci ap_driver_unregister(&zcrypt_cex2c_card_driver); 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cimodule_init(zcrypt_cex2c_init); 4298c2ecf20Sopenharmony_cimodule_exit(zcrypt_cex2c_exit); 430