aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto
diff options
context:
space:
mode:
authorHolger Dengler <hd@linux.vnet.ibm.com>2011-07-24 04:48:25 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-07-24 04:48:22 -0400
commit6bed05bcbc8e5932e06059f0c3be1acdf30a39d4 (patch)
tree57b2c17507127586cf8cfd46244be548c261d5d2 /drivers/s390/crypto
parentfdb204d1a7746a90b0d8a8665bf59af98c8c366a (diff)
[S390] ap: toleration support for ap device type 10
Add toleration support for ap devices with device type 10. Signed-off-by: Holger Dengler <hd@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r--drivers/s390/crypto/ap_bus.c96
-rw-r--r--drivers/s390/crypto/ap_bus.h22
2 files changed, 91 insertions, 27 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 16e4a25596e7..f8134a44cefa 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -6,6 +6,7 @@
6 * Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * Ralph Wuerthner <rwuerthn@de.ibm.com> 7 * Ralph Wuerthner <rwuerthn@de.ibm.com>
8 * Felix Beck <felix.beck@de.ibm.com> 8 * Felix Beck <felix.beck@de.ibm.com>
9 * Holger Dengler <hd@linux.vnet.ibm.com>
9 * 10 *
10 * Adjunct processor bus. 11 * Adjunct processor bus.
11 * 12 *
@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
222} 223}
223#endif 224#endif
224 225
225static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid, 226#ifdef CONFIG_64BIT
226 int *support) 227static inline struct ap_queue_status
228__ap_query_functions(ap_qid_t qid, unsigned int *functions)
227{ 229{
228 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23); 230 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
229 register struct ap_queue_status reg1 asm ("1"); 231 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
230 register unsigned long reg2 asm ("2") = 0UL; 232 register unsigned long reg2 asm ("2");
231 233
232 asm volatile( 234 asm volatile(
233 ".long 0xb2af0000\n" 235 ".long 0xb2af0000\n"
234 "0: la %1,0\n" 236 "0:\n"
235 "1:\n" 237 EX_TABLE(0b, 0b)
236 EX_TABLE(0b, 1b) 238 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
237 : "+d" (reg0), "=d" (reg1), "=d" (reg2)
238 : 239 :
239 : "cc"); 240 : "cc");
240 241
241 if (reg2 & 0x6000000000000000ULL) 242 *functions = (unsigned int)(reg2 >> 32);
242 *support = 1;
243 else
244 *support = 0;
245
246 return reg1; 243 return reg1;
247} 244}
245#endif
248 246
249/** 247/**
250 * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA 248 * ap_query_functions(): Query supported functions.
251 * support.
252 * @qid: The AP queue number 249 * @qid: The AP queue number
250 * @functions: Pointer to functions field.
253 * 251 *
254 * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not. 252 * Returns
253 * 0 on success.
254 * -ENODEV if queue not valid.
255 * -EBUSY if device busy.
256 * -EINVAL if query function is not supported
255 */ 257 */
256int ap_4096_commands_available(ap_qid_t qid) 258static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
257{ 259{
260#ifdef CONFIG_64BIT
258 struct ap_queue_status status; 261 struct ap_queue_status status;
259 int i, support = 0; 262 int i;
260 status = __ap_4096_commands_available(qid, &support); 263 status = __ap_query_functions(qid, functions);
261 264
262 for (i = 0; i < AP_MAX_RESET; i++) { 265 for (i = 0; i < AP_MAX_RESET; i++) {
266 if (ap_queue_status_invalid_test(&status))
267 return -ENODEV;
268
263 switch (status.response_code) { 269 switch (status.response_code) {
264 case AP_RESPONSE_NORMAL: 270 case AP_RESPONSE_NORMAL:
265 return support; 271 return 0;
266 case AP_RESPONSE_RESET_IN_PROGRESS: 272 case AP_RESPONSE_RESET_IN_PROGRESS:
267 case AP_RESPONSE_BUSY: 273 case AP_RESPONSE_BUSY:
268 break; 274 break;
@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
270 case AP_RESPONSE_DECONFIGURED: 276 case AP_RESPONSE_DECONFIGURED:
271 case AP_RESPONSE_CHECKSTOPPED: 277 case AP_RESPONSE_CHECKSTOPPED:
272 case AP_RESPONSE_INVALID_ADDRESS: 278 case AP_RESPONSE_INVALID_ADDRESS:
273 return 0; 279 return -ENODEV;
274 case AP_RESPONSE_OTHERWISE_CHANGED: 280 case AP_RESPONSE_OTHERWISE_CHANGED:
275 break; 281 break;
276 default: 282 default:
@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
278 } 284 }
279 if (i < AP_MAX_RESET - 1) { 285 if (i < AP_MAX_RESET - 1) {
280 udelay(5); 286 udelay(5);
281 status = __ap_4096_commands_available(qid, &support); 287 status = __ap_query_functions(qid, functions);
282 } 288 }
283 } 289 }
284 return support; 290 return -EBUSY;
291#else
292 return -EINVAL;
293#endif
294}
295
296/**
297 * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
298 * support.
299 * @qid: The AP queue number
300 *
301 * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
302 */
303int ap_4096_commands_available(ap_qid_t qid)
304{
305 unsigned int functions;
306
307 if (ap_query_functions(qid, &functions))
308 return 0;
309
310 return test_ap_facility(functions, 1) &&
311 test_ap_facility(functions, 2);
285} 312}
286EXPORT_SYMBOL(ap_4096_commands_available); 313EXPORT_SYMBOL(ap_4096_commands_available);
287 314
@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
1135 struct device *dev; 1162 struct device *dev;
1136 ap_qid_t qid; 1163 ap_qid_t qid;
1137 int queue_depth, device_type; 1164 int queue_depth, device_type;
1165 unsigned int device_functions;
1138 int rc, i; 1166 int rc, i;
1139 1167
1140 if (ap_select_domain() != 0) 1168 if (ap_select_domain() != 0)
@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
1183 INIT_LIST_HEAD(&ap_dev->list); 1211 INIT_LIST_HEAD(&ap_dev->list);
1184 setup_timer(&ap_dev->timeout, ap_request_timeout, 1212 setup_timer(&ap_dev->timeout, ap_request_timeout,
1185 (unsigned long) ap_dev); 1213 (unsigned long) ap_dev);
1186 if (device_type == 0) { 1214 switch (device_type) {
1215 case 0:
1187 if (ap_probe_device_type(ap_dev)) { 1216 if (ap_probe_device_type(ap_dev)) {
1188 kfree(ap_dev); 1217 kfree(ap_dev);
1189 continue; 1218 continue;
1190 } 1219 }
1191 } 1220 break;
1192 else 1221 case 10:
1222 if (ap_query_functions(qid, &device_functions)) {
1223 kfree(ap_dev);
1224 continue;
1225 }
1226 if (test_ap_facility(device_functions, 3))
1227 ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
1228 else if (test_ap_facility(device_functions, 4))
1229 ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
1230 else {
1231 kfree(ap_dev);
1232 continue;
1233 }
1234 break;
1235 default:
1193 ap_dev->device_type = device_type; 1236 ap_dev->device_type = device_type;
1237 }
1194 1238
1195 ap_dev->device.bus = &ap_bus_type; 1239 ap_dev->device.bus = &ap_bus_type;
1196 ap_dev->device.parent = ap_root_device; 1240 ap_dev->device.parent = ap_root_device;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 08b9738285b4..d960a6309eec 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -6,6 +6,7 @@
6 * Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * Ralph Wuerthner <rwuerthn@de.ibm.com> 7 * Ralph Wuerthner <rwuerthn@de.ibm.com>
8 * Felix Beck <felix.beck@de.ibm.com> 8 * Felix Beck <felix.beck@de.ibm.com>
9 * Holger Dengler <hd@linux.vnet.ibm.com>
9 * 10 *
10 * Adjunct processor bus header file. 11 * Adjunct processor bus header file.
11 * 12 *
@@ -72,7 +73,26 @@ struct ap_queue_status {
72 unsigned int int_enabled : 1; 73 unsigned int int_enabled : 1;
73 unsigned int response_code : 8; 74 unsigned int response_code : 8;
74 unsigned int pad2 : 16; 75 unsigned int pad2 : 16;
75}; 76} __packed;
77
78#define AP_QUEUE_STATUS_INVALID \
79 { 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
80
81static inline
82int ap_queue_status_invalid_test(struct ap_queue_status *status)
83{
84 struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
85 return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
86}
87
88#define MAX_AP_FACILITY 31
89
90static inline int test_ap_facility(unsigned int function, unsigned int nr)
91{
92 if (nr > MAX_AP_FACILITY)
93 return 0;
94 return function & (unsigned int)(0x80000000 >> nr);
95}
76 96
77#define AP_RESPONSE_NORMAL 0x00 97#define AP_RESPONSE_NORMAL 0x00
78#define AP_RESPONSE_Q_NOT_AVAIL 0x01 98#define AP_RESPONSE_Q_NOT_AVAIL 0x01