Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/zcryt: Handle AP configuration changes

Detect external AP bus configuration changes and request
an AP device rescan.

Signed-off-by: Holger Dengler <hd@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Holger Dengler and committed by
Martin Schwidefsky
dabecb29 745e967a

+201 -9
+14
drivers/s390/crypto/ap_bus.c
··· 950 950 } 951 951 EXPORT_SYMBOL(ap_driver_unregister); 952 952 953 + void ap_bus_force_rescan(void) 954 + { 955 + /* Delete the AP bus rescan timer. */ 956 + del_timer(&ap_config_timer); 957 + 958 + /* processing a synchonuous bus rescan */ 959 + ap_scan_bus(NULL); 960 + 961 + /* Setup the AP bus rescan timer again. */ 962 + ap_config_timer.expires = jiffies + ap_config_time * HZ; 963 + add_timer(&ap_config_timer); 964 + } 965 + EXPORT_SYMBOL(ap_bus_force_rescan); 966 + 953 967 /* 954 968 * AP bus attributes. 955 969 */
+1
drivers/s390/crypto/ap_bus.h
··· 231 231 void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); 232 232 void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); 233 233 void ap_flush_queue(struct ap_device *ap_dev); 234 + void ap_bus_force_rescan(void); 234 235 235 236 int ap_module_init(void); 236 237 void ap_module_exit(void);
+106 -8
drivers/s390/crypto/zcrypt_api.c
··· 38 38 #include <linux/atomic.h> 39 39 #include <asm/uaccess.h> 40 40 #include <linux/hw_random.h> 41 + #include <linux/debugfs.h> 42 + #include <asm/debug.h> 41 43 44 + #include "zcrypt_debug.h" 42 45 #include "zcrypt_api.h" 43 46 44 47 /* ··· 56 53 static LIST_HEAD(zcrypt_device_list); 57 54 static int zcrypt_device_count = 0; 58 55 static atomic_t zcrypt_open_count = ATOMIC_INIT(0); 56 + static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0); 57 + 58 + atomic_t zcrypt_rescan_req = ATOMIC_INIT(0); 59 + EXPORT_SYMBOL(zcrypt_rescan_req); 59 60 60 61 static int zcrypt_rng_device_add(void); 61 62 static void zcrypt_rng_device_remove(void); 62 63 63 64 static DEFINE_SPINLOCK(zcrypt_ops_list_lock); 64 65 static LIST_HEAD(zcrypt_ops_list); 66 + 67 + static debug_info_t *zcrypt_dbf_common; 68 + static debug_info_t *zcrypt_dbf_devices; 69 + static struct dentry *debugfs_root; 65 70 66 71 /* 67 72 * Device attributes common for all crypto devices. ··· 100 89 if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) 101 90 return -EINVAL; 102 91 zdev->online = online; 92 + ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dman", zdev->ap_dev->qid, 93 + zdev->online); 103 94 if (!online) 104 95 ap_flush_queue(zdev->ap_dev); 105 96 return count; ··· 118 105 static struct attribute_group zcrypt_device_attr_group = { 119 106 .attrs = zcrypt_device_attrs, 120 107 }; 108 + 109 + /** 110 + * Process a rescan of the transport layer. 111 + * 112 + * Returns 1, if the rescan has been processed, otherwise 0. 113 + */ 114 + static inline int zcrypt_process_rescan(void) 115 + { 116 + if (atomic_read(&zcrypt_rescan_req)) { 117 + atomic_set(&zcrypt_rescan_req, 0); 118 + atomic_inc(&zcrypt_rescan_count); 119 + ap_bus_force_rescan(); 120 + ZCRYPT_DBF_COMMON(DBF_INFO, "rescan%07d", 121 + atomic_inc_return(&zcrypt_rescan_count)); 122 + return 1; 123 + } 124 + return 0; 125 + } 121 126 122 127 /** 123 128 * __zcrypt_increase_preference(): Increase preference of a crypto device. ··· 225 194 zdev->reply.length = max_response_size; 226 195 spin_lock_init(&zdev->lock); 227 196 INIT_LIST_HEAD(&zdev->list); 197 + zdev->dbf_area = zcrypt_dbf_devices; 228 198 return zdev; 229 199 230 200 out_free: ··· 261 229 kref_init(&zdev->refcount); 262 230 spin_lock_bh(&zcrypt_device_lock); 263 231 zdev->online = 1; /* New devices are online by default. */ 232 + ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dreg", zdev->ap_dev->qid, 233 + zdev->online); 264 234 list_add_tail(&zdev->list, &zcrypt_device_list); 265 235 __zcrypt_increase_preference(zdev); 266 236 zcrypt_device_count++; ··· 741 707 do { 742 708 rc = zcrypt_rsa_modexpo(&mex); 743 709 } while (rc == -EAGAIN); 710 + /* on failure: retry once again after a requested rescan */ 711 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 712 + do { 713 + rc = zcrypt_rsa_modexpo(&mex); 714 + } while (rc == -EAGAIN); 744 715 if (rc) 745 716 return rc; 746 717 return put_user(mex.outputdatalength, &umex->outputdatalength); ··· 758 719 do { 759 720 rc = zcrypt_rsa_crt(&crt); 760 721 } while (rc == -EAGAIN); 722 + /* on failure: retry once again after a requested rescan */ 723 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 724 + do { 725 + rc = zcrypt_rsa_crt(&crt); 726 + } while (rc == -EAGAIN); 761 727 if (rc) 762 728 return rc; 763 729 return put_user(crt.outputdatalength, &ucrt->outputdatalength); ··· 775 731 do { 776 732 rc = zcrypt_send_cprb(&xcRB); 777 733 } while (rc == -EAGAIN); 734 + /* on failure: retry once again after a requested rescan */ 735 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 736 + do { 737 + rc = zcrypt_send_cprb(&xcRB); 738 + } while (rc == -EAGAIN); 778 739 if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) 779 740 return -EFAULT; 780 741 return rc; ··· 886 837 do { 887 838 rc = zcrypt_rsa_modexpo(&mex64); 888 839 } while (rc == -EAGAIN); 889 - if (!rc) 890 - rc = put_user(mex64.outputdatalength, 891 - &umex32->outputdatalength); 892 - return rc; 840 + /* on failure: retry once again after a requested rescan */ 841 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 842 + do { 843 + rc = zcrypt_rsa_modexpo(&mex64); 844 + } while (rc == -EAGAIN); 845 + if (rc) 846 + return rc; 847 + return put_user(mex64.outputdatalength, 848 + &umex32->outputdatalength); 893 849 } 894 850 895 851 struct compat_ica_rsa_modexpo_crt { ··· 931 877 do { 932 878 rc = zcrypt_rsa_crt(&crt64); 933 879 } while (rc == -EAGAIN); 934 - if (!rc) 935 - rc = put_user(crt64.outputdatalength, 936 - &ucrt32->outputdatalength); 937 - return rc; 880 + /* on failure: retry once again after a requested rescan */ 881 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 882 + do { 883 + rc = zcrypt_rsa_crt(&crt64); 884 + } while (rc == -EAGAIN); 885 + if (rc) 886 + return rc; 887 + return put_user(crt64.outputdatalength, 888 + &ucrt32->outputdatalength); 938 889 } 939 890 940 891 struct compat_ica_xcRB { ··· 995 936 do { 996 937 rc = zcrypt_send_cprb(&xcRB64); 997 938 } while (rc == -EAGAIN); 939 + /* on failure: retry once again after a requested rescan */ 940 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 941 + do { 942 + rc = zcrypt_send_cprb(&xcRB64); 943 + } while (rc == -EAGAIN); 998 944 xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; 999 945 xcRB32.reply_data_length = xcRB64.reply_data_length; 1000 946 xcRB32.status = xcRB64.status; ··· 1257 1193 */ 1258 1194 if (zcrypt_rng_buffer_index == 0) { 1259 1195 rc = zcrypt_rng((char *) zcrypt_rng_buffer); 1196 + /* on failure: retry once again after a requested rescan */ 1197 + if ((rc == -ENODEV) && (zcrypt_process_rescan())) 1198 + rc = zcrypt_rng((char *) zcrypt_rng_buffer); 1260 1199 if (rc < 0) 1261 1200 return -EIO; 1262 1201 zcrypt_rng_buffer_index = rc / sizeof *data; ··· 1312 1245 mutex_unlock(&zcrypt_rng_mutex); 1313 1246 } 1314 1247 1248 + int __init zcrypt_debug_init(void) 1249 + { 1250 + debugfs_root = debugfs_create_dir("zcrypt", NULL); 1251 + 1252 + zcrypt_dbf_common = debug_register("zcrypt_common", 1, 1, 16); 1253 + debug_register_view(zcrypt_dbf_common, &debug_hex_ascii_view); 1254 + debug_set_level(zcrypt_dbf_common, DBF_ERR); 1255 + 1256 + zcrypt_dbf_devices = debug_register("zcrypt_devices", 1, 1, 16); 1257 + debug_register_view(zcrypt_dbf_devices, &debug_hex_ascii_view); 1258 + debug_set_level(zcrypt_dbf_devices, DBF_ERR); 1259 + 1260 + return 0; 1261 + } 1262 + 1263 + void zcrypt_debug_exit(void) 1264 + { 1265 + debugfs_remove(debugfs_root); 1266 + if (zcrypt_dbf_common) 1267 + debug_unregister(zcrypt_dbf_common); 1268 + if (zcrypt_dbf_devices) 1269 + debug_unregister(zcrypt_dbf_devices); 1270 + } 1271 + 1315 1272 /** 1316 1273 * zcrypt_api_init(): Module initialization. 1317 1274 * ··· 1344 1253 int __init zcrypt_api_init(void) 1345 1254 { 1346 1255 int rc; 1256 + 1257 + rc = zcrypt_debug_init(); 1258 + if (rc) 1259 + goto out; 1260 + 1261 + atomic_set(&zcrypt_rescan_req, 0); 1347 1262 1348 1263 /* Register the request sprayer. */ 1349 1264 rc = misc_register(&zcrypt_misc_device); ··· 1380 1283 { 1381 1284 remove_proc_entry("driver/z90crypt", NULL); 1382 1285 misc_deregister(&zcrypt_misc_device); 1286 + zcrypt_debug_exit(); 1383 1287 } 1384 1288 1385 1289 module_init(zcrypt_api_init);
+8 -1
drivers/s390/crypto/zcrypt_api.h
··· 29 29 #ifndef _ZCRYPT_API_H_ 30 30 #define _ZCRYPT_API_H_ 31 31 32 - #include "ap_bus.h" 32 + #include <linux/atomic.h> 33 + #include <asm/debug.h> 33 34 #include <asm/zcrypt.h> 35 + #include "ap_bus.h" 34 36 35 37 /* deprecated status calls */ 36 38 #define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) ··· 114 112 115 113 struct ap_message reply; /* Per-device reply structure. */ 116 114 int max_exp_bit_length; 115 + 116 + debug_info_t *dbf_area; /* debugging */ 117 117 }; 118 + 119 + /* transport layer rescanning */ 120 + extern atomic_t zcrypt_rescan_req; 118 121 119 122 struct zcrypt_device *zcrypt_device_alloc(size_t); 120 123 void zcrypt_device_free(struct zcrypt_device *);
+59
drivers/s390/crypto/zcrypt_debug.h
··· 1 + /* 2 + * Copyright IBM Corp. 2012 3 + * Author(s): Holger Dengler (hd@linux.vnet.ibm.com) 4 + */ 5 + #ifndef ZCRYPT_DEBUG_H 6 + #define ZCRYPT_DEBUG_H 7 + 8 + #include <asm/debug.h> 9 + #include "zcrypt_api.h" 10 + 11 + /* that gives us 15 characters in the text event views */ 12 + #define ZCRYPT_DBF_LEN 16 13 + 14 + /* sort out low debug levels early to avoid wasted sprints */ 15 + static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level) 16 + { 17 + return (level <= dbf_grp->level); 18 + } 19 + 20 + #define DBF_ERR 3 /* error conditions */ 21 + #define DBF_WARN 4 /* warning conditions */ 22 + #define DBF_INFO 6 /* informational */ 23 + 24 + #define RC2WARN(rc) ((rc) ? DBF_WARN : DBF_INFO) 25 + 26 + #define ZCRYPT_DBF_COMMON(level, text...) \ 27 + do { \ 28 + if (zcrypt_dbf_passes(zcrypt_dbf_common, level)) { \ 29 + char debug_buffer[ZCRYPT_DBF_LEN]; \ 30 + snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ 31 + debug_text_event(zcrypt_dbf_common, level, \ 32 + debug_buffer); \ 33 + } \ 34 + } while (0) 35 + 36 + #define ZCRYPT_DBF_DEVICES(level, text...) \ 37 + do { \ 38 + if (zcrypt_dbf_passes(zcrypt_dbf_devices, level)) { \ 39 + char debug_buffer[ZCRYPT_DBF_LEN]; \ 40 + snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ 41 + debug_text_event(zcrypt_dbf_devices, level, \ 42 + debug_buffer); \ 43 + } \ 44 + } while (0) 45 + 46 + #define ZCRYPT_DBF_DEV(level, device, text...) \ 47 + do { \ 48 + if (zcrypt_dbf_passes(device->dbf_area, level)) { \ 49 + char debug_buffer[ZCRYPT_DBF_LEN]; \ 50 + snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ 51 + debug_text_event(device->dbf_area, level, \ 52 + debug_buffer); \ 53 + } \ 54 + } while (0) 55 + 56 + int zcrypt_debug_init(void); 57 + void zcrypt_debug_exit(void); 58 + 59 + #endif /* ZCRYPT_DEBUG_H */
+13
drivers/s390/crypto/zcrypt_error.h
··· 26 26 #ifndef _ZCRYPT_ERROR_H_ 27 27 #define _ZCRYPT_ERROR_H_ 28 28 29 + #include <linux/atomic.h> 30 + #include "zcrypt_debug.h" 29 31 #include "zcrypt_api.h" 30 32 31 33 /** ··· 110 108 * and then repeat the request. 111 109 */ 112 110 WARN_ON(1); 111 + atomic_set(&zcrypt_rescan_req, 1); 113 112 zdev->online = 0; 113 + ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", 114 + zdev->ap_dev->qid, 115 + zdev->online, ehdr->reply_code); 114 116 return -EAGAIN; 115 117 case REP82_ERROR_TRANSPORT_FAIL: 116 118 case REP82_ERROR_MACHINE_FAILURE: 117 119 // REP88_ERROR_MODULE_FAILURE // '10' CEX2A 118 120 /* If a card fails disable it and repeat the request. */ 121 + atomic_set(&zcrypt_rescan_req, 1); 119 122 zdev->online = 0; 123 + ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", 124 + zdev->ap_dev->qid, 125 + zdev->online, ehdr->reply_code); 120 126 return -EAGAIN; 121 127 default: 122 128 zdev->online = 0; 129 + ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", 130 + zdev->ap_dev->qid, 131 + zdev->online, ehdr->reply_code); 123 132 return -EAGAIN; /* repeat the request on a different device. */ 124 133 } 125 134 }