diff options
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 20 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 3 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_pcixcc.c | 5 |
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 | */ |
291 | static inline struct ap_queue_status | 292 | static 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, |