aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/crypto/ap_bus.c20
-rw-r--r--drivers/s390/crypto/ap_bus.h3
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c5
3 files changed, 23 insertions, 5 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 1294876bf7b4..21077f4b8c50 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -282,6 +282,7 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
282 * @psmid: The program supplied message identifier 282 * @psmid: The program supplied message identifier
283 * @msg: The message text 283 * @msg: The message text
284 * @length: The message length 284 * @length: The message length
285 * @special: Special Bit
285 * 286 *
286 * Returns AP queue status structure. 287 * Returns AP queue status structure.
287 * Condition code 1 on NQAP can't happen because the L bit is 1. 288 * Condition code 1 on NQAP can't happen because the L bit is 1.
@@ -289,7 +290,8 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
289 * because a segment boundary was reached. The NQAP is repeated. 290 * because a segment boundary was reached. The NQAP is repeated.
290 */ 291 */
291static inline struct ap_queue_status 292static inline struct ap_queue_status
292__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) 293__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
294 unsigned int special)
293{ 295{
294 typedef struct { char _[length]; } msgblock; 296 typedef struct { char _[length]; } msgblock;
295 register unsigned long reg0 asm ("0") = qid | 0x40000000UL; 297 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
@@ -299,6 +301,9 @@ __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
299 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32); 301 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
300 register unsigned long reg5 asm ("5") = (unsigned int) psmid; 302 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
301 303
304 if (special == 1)
305 reg0 |= 0x400000UL;
306
302 asm volatile ( 307 asm volatile (
303 "0: .long 0xb2ad0042\n" /* DQAP */ 308 "0: .long 0xb2ad0042\n" /* DQAP */
304 " brc 2,0b" 309 " brc 2,0b"
@@ -312,13 +317,15 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
312{ 317{
313 struct ap_queue_status status; 318 struct ap_queue_status status;
314 319
315 status = __ap_send(qid, psmid, msg, length); 320 status = __ap_send(qid, psmid, msg, length, 0);
316 switch (status.response_code) { 321 switch (status.response_code) {
317 case AP_RESPONSE_NORMAL: 322 case AP_RESPONSE_NORMAL:
318 return 0; 323 return 0;
319 case AP_RESPONSE_Q_FULL: 324 case AP_RESPONSE_Q_FULL:
320 case AP_RESPONSE_RESET_IN_PROGRESS: 325 case AP_RESPONSE_RESET_IN_PROGRESS:
321 return -EBUSY; 326 return -EBUSY;
327 case AP_RESPONSE_REQ_FAC_NOT_INST:
328 return -EINVAL;
322 default: /* Device is gone. */ 329 default: /* Device is gone. */
323 return -ENODEV; 330 return -ENODEV;
324 } 331 }
@@ -1008,7 +1015,7 @@ static int ap_probe_device_type(struct ap_device *ap_dev)
1008 } 1015 }
1009 1016
1010 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL, 1017 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
1011 msg, sizeof(msg)); 1018 msg, sizeof(msg), 0);
1012 if (status.response_code != AP_RESPONSE_NORMAL) { 1019 if (status.response_code != AP_RESPONSE_NORMAL) {
1013 rc = -ENODEV; 1020 rc = -ENODEV;
1014 goto out_free; 1021 goto out_free;
@@ -1243,7 +1250,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
1243 /* Start the next request on the queue. */ 1250 /* Start the next request on the queue. */
1244 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list); 1251 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1245 status = __ap_send(ap_dev->qid, ap_msg->psmid, 1252 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1246 ap_msg->message, ap_msg->length); 1253 ap_msg->message, ap_msg->length, ap_msg->special);
1247 switch (status.response_code) { 1254 switch (status.response_code) {
1248 case AP_RESPONSE_NORMAL: 1255 case AP_RESPONSE_NORMAL:
1249 atomic_inc(&ap_poll_requests); 1256 atomic_inc(&ap_poll_requests);
@@ -1261,6 +1268,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
1261 *flags |= 2; 1268 *flags |= 2;
1262 break; 1269 break;
1263 case AP_RESPONSE_MESSAGE_TOO_BIG: 1270 case AP_RESPONSE_MESSAGE_TOO_BIG:
1271 case AP_RESPONSE_REQ_FAC_NOT_INST:
1264 return -EINVAL; 1272 return -EINVAL;
1265 default: 1273 default:
1266 return -ENODEV; 1274 return -ENODEV;
@@ -1302,7 +1310,8 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
1302 if (list_empty(&ap_dev->requestq) && 1310 if (list_empty(&ap_dev->requestq) &&
1303 ap_dev->queue_count < ap_dev->queue_depth) { 1311 ap_dev->queue_count < ap_dev->queue_depth) {
1304 status = __ap_send(ap_dev->qid, ap_msg->psmid, 1312 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1305 ap_msg->message, ap_msg->length); 1313 ap_msg->message, ap_msg->length,
1314 ap_msg->special);
1306 switch (status.response_code) { 1315 switch (status.response_code) {
1307 case AP_RESPONSE_NORMAL: 1316 case AP_RESPONSE_NORMAL:
1308 list_add_tail(&ap_msg->list, &ap_dev->pendingq); 1317 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
@@ -1317,6 +1326,7 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
1317 ap_dev->requestq_count++; 1326 ap_dev->requestq_count++;
1318 ap_dev->total_request_count++; 1327 ap_dev->total_request_count++;
1319 return -EBUSY; 1328 return -EBUSY;
1329 case AP_RESPONSE_REQ_FAC_NOT_INST:
1320 case AP_RESPONSE_MESSAGE_TOO_BIG: 1330 case AP_RESPONSE_MESSAGE_TOO_BIG:
1321 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); 1331 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1322 return -EINVAL; 1332 return -EINVAL;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index fcf2497556dd..c37466713b32 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -87,6 +87,7 @@ struct ap_queue_status {
87#define AP_RESPONSE_INDEX_TOO_BIG 0x11 87#define AP_RESPONSE_INDEX_TOO_BIG 0x11
88#define AP_RESPONSE_NO_FIRST_PART 0x13 88#define AP_RESPONSE_NO_FIRST_PART 0x13
89#define AP_RESPONSE_MESSAGE_TOO_BIG 0x15 89#define AP_RESPONSE_MESSAGE_TOO_BIG 0x15
90#define AP_RESPONSE_REQ_FAC_NOT_INST 0x16
90 91
91/* 92/*
92 * Known device types 93 * Known device types
@@ -161,6 +162,7 @@ struct ap_message {
161 size_t length; /* Message length. */ 162 size_t length; /* Message length. */
162 163
163 void *private; /* ap driver private pointer. */ 164 void *private; /* ap driver private pointer. */
165 unsigned int special:1; /* Used for special commands. */
164}; 166};
165 167
166#define AP_DEVICE(dt) \ 168#define AP_DEVICE(dt) \
@@ -176,6 +178,7 @@ static inline void ap_init_message(struct ap_message *ap_msg)
176{ 178{
177 ap_msg->psmid = 0; 179 ap_msg->psmid = 0;
178 ap_msg->length = 0; 180 ap_msg->length = 0;
181 ap_msg->special = 0;
179} 182}
180 183
181/* 184/*
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 11ca6dc99b23..addaaddaf994 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -326,6 +326,11 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
326 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; 326 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
327 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code)); 327 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
328 328
329 if (memcmp(function_code, "US", 2) == 0)
330 ap_msg->special = 1;
331 else
332 ap_msg->special = 0;
333
329 /* copy data block */ 334 /* copy data block */
330 if (xcRB->request_data_length && 335 if (xcRB->request_data_length &&
331 copy_from_user(req_data, xcRB->request_data_address, 336 copy_from_user(req_data, xcRB->request_data_address,