aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorHolger Dengler <hd@linux.vnet.ibm.com>2012-09-10 15:34:26 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:45:17 -0400
commitdabecb2933f7ae901c88cb10c71ab38ca7dfc38f (patch)
tree04d0094b077eddcf47c3c692dfc0eeda2de727d6 /drivers/s390
parent745e967a49b26725cc9f30105ff67c8fee8926d6 (diff)
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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/ap_bus.c14
-rw-r--r--drivers/s390/crypto/ap_bus.h1
-rw-r--r--drivers/s390/crypto/zcrypt_api.c114
-rw-r--r--drivers/s390/crypto/zcrypt_api.h9
-rw-r--r--drivers/s390/crypto/zcrypt_debug.h59
-rw-r--r--drivers/s390/crypto/zcrypt_error.h13
6 files changed, 201 insertions, 9 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 39e5eb263e4b..cf5d9dc51c94 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -950,6 +950,20 @@ void ap_driver_unregister(struct ap_driver *ap_drv)
950} 950}
951EXPORT_SYMBOL(ap_driver_unregister); 951EXPORT_SYMBOL(ap_driver_unregister);
952 952
953void 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}
965EXPORT_SYMBOL(ap_bus_force_rescan);
966
953/* 967/*
954 * AP bus attributes. 968 * AP bus attributes.
955 */ 969 */
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index e9b963e7d59d..685f6cc022f9 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -231,6 +231,7 @@ int ap_recv(ap_qid_t, unsigned long long *, void *, size_t);
231void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); 231void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg);
232void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); 232void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg);
233void ap_flush_queue(struct ap_device *ap_dev); 233void ap_flush_queue(struct ap_device *ap_dev);
234void ap_bus_force_rescan(void);
234 235
235int ap_module_init(void); 236int ap_module_init(void);
236void ap_module_exit(void); 237void ap_module_exit(void);
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index f1f026e0b189..31cfaa556072 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -38,7 +38,10 @@
38#include <linux/atomic.h> 38#include <linux/atomic.h>
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
40#include <linux/hw_random.h> 40#include <linux/hw_random.h>
41#include <linux/debugfs.h>
42#include <asm/debug.h>
41 43
44#include "zcrypt_debug.h"
42#include "zcrypt_api.h" 45#include "zcrypt_api.h"
43 46
44/* 47/*
@@ -53,6 +56,10 @@ static DEFINE_SPINLOCK(zcrypt_device_lock);
53static LIST_HEAD(zcrypt_device_list); 56static LIST_HEAD(zcrypt_device_list);
54static int zcrypt_device_count = 0; 57static int zcrypt_device_count = 0;
55static atomic_t zcrypt_open_count = ATOMIC_INIT(0); 58static atomic_t zcrypt_open_count = ATOMIC_INIT(0);
59static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0);
60
61atomic_t zcrypt_rescan_req = ATOMIC_INIT(0);
62EXPORT_SYMBOL(zcrypt_rescan_req);
56 63
57static int zcrypt_rng_device_add(void); 64static int zcrypt_rng_device_add(void);
58static void zcrypt_rng_device_remove(void); 65static void zcrypt_rng_device_remove(void);
@@ -60,6 +67,10 @@ static void zcrypt_rng_device_remove(void);
60static DEFINE_SPINLOCK(zcrypt_ops_list_lock); 67static DEFINE_SPINLOCK(zcrypt_ops_list_lock);
61static LIST_HEAD(zcrypt_ops_list); 68static LIST_HEAD(zcrypt_ops_list);
62 69
70static debug_info_t *zcrypt_dbf_common;
71static debug_info_t *zcrypt_dbf_devices;
72static struct dentry *debugfs_root;
73
63/* 74/*
64 * Device attributes common for all crypto devices. 75 * Device attributes common for all crypto devices.
65 */ 76 */
@@ -89,6 +100,8 @@ static ssize_t zcrypt_online_store(struct device *dev,
89 if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) 100 if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
90 return -EINVAL; 101 return -EINVAL;
91 zdev->online = online; 102 zdev->online = online;
103 ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dman", zdev->ap_dev->qid,
104 zdev->online);
92 if (!online) 105 if (!online)
93 ap_flush_queue(zdev->ap_dev); 106 ap_flush_queue(zdev->ap_dev);
94 return count; 107 return count;
@@ -107,6 +120,24 @@ static struct attribute_group zcrypt_device_attr_group = {
107}; 120};
108 121
109/** 122/**
123 * Process a rescan of the transport layer.
124 *
125 * Returns 1, if the rescan has been processed, otherwise 0.
126 */
127static inline int zcrypt_process_rescan(void)
128{
129 if (atomic_read(&zcrypt_rescan_req)) {
130 atomic_set(&zcrypt_rescan_req, 0);
131 atomic_inc(&zcrypt_rescan_count);
132 ap_bus_force_rescan();
133 ZCRYPT_DBF_COMMON(DBF_INFO, "rescan%07d",
134 atomic_inc_return(&zcrypt_rescan_count));
135 return 1;
136 }
137 return 0;
138}
139
140/**
110 * __zcrypt_increase_preference(): Increase preference of a crypto device. 141 * __zcrypt_increase_preference(): Increase preference of a crypto device.
111 * @zdev: Pointer the crypto device 142 * @zdev: Pointer the crypto device
112 * 143 *
@@ -194,6 +225,7 @@ struct zcrypt_device *zcrypt_device_alloc(size_t max_response_size)
194 zdev->reply.length = max_response_size; 225 zdev->reply.length = max_response_size;
195 spin_lock_init(&zdev->lock); 226 spin_lock_init(&zdev->lock);
196 INIT_LIST_HEAD(&zdev->list); 227 INIT_LIST_HEAD(&zdev->list);
228 zdev->dbf_area = zcrypt_dbf_devices;
197 return zdev; 229 return zdev;
198 230
199out_free: 231out_free:
@@ -229,6 +261,8 @@ int zcrypt_device_register(struct zcrypt_device *zdev)
229 kref_init(&zdev->refcount); 261 kref_init(&zdev->refcount);
230 spin_lock_bh(&zcrypt_device_lock); 262 spin_lock_bh(&zcrypt_device_lock);
231 zdev->online = 1; /* New devices are online by default. */ 263 zdev->online = 1; /* New devices are online by default. */
264 ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dreg", zdev->ap_dev->qid,
265 zdev->online);
232 list_add_tail(&zdev->list, &zcrypt_device_list); 266 list_add_tail(&zdev->list, &zcrypt_device_list);
233 __zcrypt_increase_preference(zdev); 267 __zcrypt_increase_preference(zdev);
234 zcrypt_device_count++; 268 zcrypt_device_count++;
@@ -707,6 +741,11 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
707 do { 741 do {
708 rc = zcrypt_rsa_modexpo(&mex); 742 rc = zcrypt_rsa_modexpo(&mex);
709 } while (rc == -EAGAIN); 743 } while (rc == -EAGAIN);
744 /* on failure: retry once again after a requested rescan */
745 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
746 do {
747 rc = zcrypt_rsa_modexpo(&mex);
748 } while (rc == -EAGAIN);
710 if (rc) 749 if (rc)
711 return rc; 750 return rc;
712 return put_user(mex.outputdatalength, &umex->outputdatalength); 751 return put_user(mex.outputdatalength, &umex->outputdatalength);
@@ -719,6 +758,11 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
719 do { 758 do {
720 rc = zcrypt_rsa_crt(&crt); 759 rc = zcrypt_rsa_crt(&crt);
721 } while (rc == -EAGAIN); 760 } while (rc == -EAGAIN);
761 /* on failure: retry once again after a requested rescan */
762 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
763 do {
764 rc = zcrypt_rsa_crt(&crt);
765 } while (rc == -EAGAIN);
722 if (rc) 766 if (rc)
723 return rc; 767 return rc;
724 return put_user(crt.outputdatalength, &ucrt->outputdatalength); 768 return put_user(crt.outputdatalength, &ucrt->outputdatalength);
@@ -731,6 +775,11 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
731 do { 775 do {
732 rc = zcrypt_send_cprb(&xcRB); 776 rc = zcrypt_send_cprb(&xcRB);
733 } while (rc == -EAGAIN); 777 } while (rc == -EAGAIN);
778 /* on failure: retry once again after a requested rescan */
779 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
780 do {
781 rc = zcrypt_send_cprb(&xcRB);
782 } while (rc == -EAGAIN);
734 if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) 783 if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
735 return -EFAULT; 784 return -EFAULT;
736 return rc; 785 return rc;
@@ -837,10 +886,15 @@ static long trans_modexpo32(struct file *filp, unsigned int cmd,
837 do { 886 do {
838 rc = zcrypt_rsa_modexpo(&mex64); 887 rc = zcrypt_rsa_modexpo(&mex64);
839 } while (rc == -EAGAIN); 888 } while (rc == -EAGAIN);
840 if (!rc) 889 /* on failure: retry once again after a requested rescan */
841 rc = put_user(mex64.outputdatalength, 890 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
842 &umex32->outputdatalength); 891 do {
843 return rc; 892 rc = zcrypt_rsa_modexpo(&mex64);
893 } while (rc == -EAGAIN);
894 if (rc)
895 return rc;
896 return put_user(mex64.outputdatalength,
897 &umex32->outputdatalength);
844} 898}
845 899
846struct compat_ica_rsa_modexpo_crt { 900struct compat_ica_rsa_modexpo_crt {
@@ -877,10 +931,15 @@ static long trans_modexpo_crt32(struct file *filp, unsigned int cmd,
877 do { 931 do {
878 rc = zcrypt_rsa_crt(&crt64); 932 rc = zcrypt_rsa_crt(&crt64);
879 } while (rc == -EAGAIN); 933 } while (rc == -EAGAIN);
880 if (!rc) 934 /* on failure: retry once again after a requested rescan */
881 rc = put_user(crt64.outputdatalength, 935 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
882 &ucrt32->outputdatalength); 936 do {
883 return rc; 937 rc = zcrypt_rsa_crt(&crt64);
938 } while (rc == -EAGAIN);
939 if (rc)
940 return rc;
941 return put_user(crt64.outputdatalength,
942 &ucrt32->outputdatalength);
884} 943}
885 944
886struct compat_ica_xcRB { 945struct compat_ica_xcRB {
@@ -936,6 +995,11 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd,
936 do { 995 do {
937 rc = zcrypt_send_cprb(&xcRB64); 996 rc = zcrypt_send_cprb(&xcRB64);
938 } while (rc == -EAGAIN); 997 } while (rc == -EAGAIN);
998 /* on failure: retry once again after a requested rescan */
999 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
1000 do {
1001 rc = zcrypt_send_cprb(&xcRB64);
1002 } while (rc == -EAGAIN);
939 xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; 1003 xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length;
940 xcRB32.reply_data_length = xcRB64.reply_data_length; 1004 xcRB32.reply_data_length = xcRB64.reply_data_length;
941 xcRB32.status = xcRB64.status; 1005 xcRB32.status = xcRB64.status;
@@ -1193,6 +1257,9 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
1193 */ 1257 */
1194 if (zcrypt_rng_buffer_index == 0) { 1258 if (zcrypt_rng_buffer_index == 0) {
1195 rc = zcrypt_rng((char *) zcrypt_rng_buffer); 1259 rc = zcrypt_rng((char *) zcrypt_rng_buffer);
1260 /* on failure: retry once again after a requested rescan */
1261 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
1262 rc = zcrypt_rng((char *) zcrypt_rng_buffer);
1196 if (rc < 0) 1263 if (rc < 0)
1197 return -EIO; 1264 return -EIO;
1198 zcrypt_rng_buffer_index = rc / sizeof *data; 1265 zcrypt_rng_buffer_index = rc / sizeof *data;
@@ -1245,6 +1312,30 @@ static void zcrypt_rng_device_remove(void)
1245 mutex_unlock(&zcrypt_rng_mutex); 1312 mutex_unlock(&zcrypt_rng_mutex);
1246} 1313}
1247 1314
1315int __init zcrypt_debug_init(void)
1316{
1317 debugfs_root = debugfs_create_dir("zcrypt", NULL);
1318
1319 zcrypt_dbf_common = debug_register("zcrypt_common", 1, 1, 16);
1320 debug_register_view(zcrypt_dbf_common, &debug_hex_ascii_view);
1321 debug_set_level(zcrypt_dbf_common, DBF_ERR);
1322
1323 zcrypt_dbf_devices = debug_register("zcrypt_devices", 1, 1, 16);
1324 debug_register_view(zcrypt_dbf_devices, &debug_hex_ascii_view);
1325 debug_set_level(zcrypt_dbf_devices, DBF_ERR);
1326
1327 return 0;
1328}
1329
1330void zcrypt_debug_exit(void)
1331{
1332 debugfs_remove(debugfs_root);
1333 if (zcrypt_dbf_common)
1334 debug_unregister(zcrypt_dbf_common);
1335 if (zcrypt_dbf_devices)
1336 debug_unregister(zcrypt_dbf_devices);
1337}
1338
1248/** 1339/**
1249 * zcrypt_api_init(): Module initialization. 1340 * zcrypt_api_init(): Module initialization.
1250 * 1341 *
@@ -1254,6 +1345,12 @@ int __init zcrypt_api_init(void)
1254{ 1345{
1255 int rc; 1346 int rc;
1256 1347
1348 rc = zcrypt_debug_init();
1349 if (rc)
1350 goto out;
1351
1352 atomic_set(&zcrypt_rescan_req, 0);
1353
1257 /* Register the request sprayer. */ 1354 /* Register the request sprayer. */
1258 rc = misc_register(&zcrypt_misc_device); 1355 rc = misc_register(&zcrypt_misc_device);
1259 if (rc < 0) 1356 if (rc < 0)
@@ -1283,6 +1380,7 @@ void zcrypt_api_exit(void)
1283{ 1380{
1284 remove_proc_entry("driver/z90crypt", NULL); 1381 remove_proc_entry("driver/z90crypt", NULL);
1285 misc_deregister(&zcrypt_misc_device); 1382 misc_deregister(&zcrypt_misc_device);
1383 zcrypt_debug_exit();
1286} 1384}
1287 1385
1288module_init(zcrypt_api_init); 1386module_init(zcrypt_api_init);
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 02b2d35de1a7..89632919c993 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -29,8 +29,10 @@
29#ifndef _ZCRYPT_API_H_ 29#ifndef _ZCRYPT_API_H_
30#define _ZCRYPT_API_H_ 30#define _ZCRYPT_API_H_
31 31
32#include "ap_bus.h" 32#include <linux/atomic.h>
33#include <asm/debug.h>
33#include <asm/zcrypt.h> 34#include <asm/zcrypt.h>
35#include "ap_bus.h"
34 36
35/* deprecated status calls */ 37/* deprecated status calls */
36#define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) 38#define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status)
@@ -112,8 +114,13 @@ struct zcrypt_device {
112 114
113 struct ap_message reply; /* Per-device reply structure. */ 115 struct ap_message reply; /* Per-device reply structure. */
114 int max_exp_bit_length; 116 int max_exp_bit_length;
117
118 debug_info_t *dbf_area; /* debugging */
115}; 119};
116 120
121/* transport layer rescanning */
122extern atomic_t zcrypt_rescan_req;
123
117struct zcrypt_device *zcrypt_device_alloc(size_t); 124struct zcrypt_device *zcrypt_device_alloc(size_t);
118void zcrypt_device_free(struct zcrypt_device *); 125void zcrypt_device_free(struct zcrypt_device *);
119void zcrypt_device_get(struct zcrypt_device *); 126void zcrypt_device_get(struct zcrypt_device *);
diff --git a/drivers/s390/crypto/zcrypt_debug.h b/drivers/s390/crypto/zcrypt_debug.h
new file mode 100644
index 000000000000..841ea72e4a4e
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_debug.h
@@ -0,0 +1,59 @@
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 */
15static 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
56int zcrypt_debug_init(void);
57void zcrypt_debug_exit(void);
58
59#endif /* ZCRYPT_DEBUG_H */
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
index 0965e2626d18..0079b6617211 100644
--- a/drivers/s390/crypto/zcrypt_error.h
+++ b/drivers/s390/crypto/zcrypt_error.h
@@ -26,6 +26,8 @@
26#ifndef _ZCRYPT_ERROR_H_ 26#ifndef _ZCRYPT_ERROR_H_
27#define _ZCRYPT_ERROR_H_ 27#define _ZCRYPT_ERROR_H_
28 28
29#include <linux/atomic.h>
30#include "zcrypt_debug.h"
29#include "zcrypt_api.h" 31#include "zcrypt_api.h"
30 32
31/** 33/**
@@ -108,16 +110,27 @@ static inline int convert_error(struct zcrypt_device *zdev,
108 * and then repeat the request. 110 * and then repeat the request.
109 */ 111 */
110 WARN_ON(1); 112 WARN_ON(1);
113 atomic_set(&zcrypt_rescan_req, 1);
111 zdev->online = 0; 114 zdev->online = 0;
115 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
116 zdev->ap_dev->qid,
117 zdev->online, ehdr->reply_code);
112 return -EAGAIN; 118 return -EAGAIN;
113 case REP82_ERROR_TRANSPORT_FAIL: 119 case REP82_ERROR_TRANSPORT_FAIL:
114 case REP82_ERROR_MACHINE_FAILURE: 120 case REP82_ERROR_MACHINE_FAILURE:
115 // REP88_ERROR_MODULE_FAILURE // '10' CEX2A 121 // REP88_ERROR_MODULE_FAILURE // '10' CEX2A
116 /* If a card fails disable it and repeat the request. */ 122 /* If a card fails disable it and repeat the request. */
123 atomic_set(&zcrypt_rescan_req, 1);
117 zdev->online = 0; 124 zdev->online = 0;
125 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
126 zdev->ap_dev->qid,
127 zdev->online, ehdr->reply_code);
118 return -EAGAIN; 128 return -EAGAIN;
119 default: 129 default:
120 zdev->online = 0; 130 zdev->online = 0;
131 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
132 zdev->ap_dev->qid,
133 zdev->online, ehdr->reply_code);
121 return -EAGAIN; /* repeat the request on a different device. */ 134 return -EAGAIN; /* repeat the request on a different device. */
122 } 135 }
123} 136}