s390/zcrypt: use explicit return code for flushed requests
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 14 Sep 2015 14:59:27 +0000 (16:59 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 14 Oct 2015 12:32:22 +0000 (14:32 +0200)
If a AP device is removed while messages are still pending, the requests
are cancelled by calling the message receive function with an error pointer
for the reply. The message type receive handler recognize this and create
a fake hardware error TYPE82_RSP_CODE / REP82_ERROR_MACHINE_FAILURE.
The message with the hardware error then causes a printk and a return
code of -EAGAIN.

Replace the intricate scheme with an explicit return code for this sitation
and avoid the error message.

Reviewd-by: Ingo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c

index ba1f806051b72babb00ca178a4b0e3c85932185d..7224bf7fa9bf1db740711f6aeab98579329127c4 100644 (file)
@@ -1027,12 +1027,14 @@ static void __ap_flush_queue(struct ap_device *ap_dev)
        list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
                list_del_init(&ap_msg->list);
                ap_dev->pendingq_count--;
-               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->rc = -EAGAIN;
+               ap_msg->receive(ap_dev, ap_msg, NULL);
        }
        list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
                list_del_init(&ap_msg->list);
                ap_dev->requestq_count--;
-               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->rc = -EAGAIN;
+               ap_msg->receive(ap_dev, ap_msg, NULL);
        }
 }
 
@@ -1690,10 +1692,12 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
                        return -EBUSY;
                case AP_RESPONSE_REQ_FAC_NOT_INST:
                case AP_RESPONSE_MESSAGE_TOO_BIG:
-                       ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
+                       ap_msg->rc = -EINVAL;
+                       ap_msg->receive(ap_dev, ap_msg, NULL);
                        return -EINVAL;
                default:        /* Device is gone. */
-                       ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+                       ap_msg->rc = -ENODEV;
+                       ap_msg->receive(ap_dev, ap_msg, NULL);
                        return -ENODEV;
                }
        } else {
@@ -1726,7 +1730,8 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
                if (rc == -ENODEV)
                        ap_dev->unregistered = 1;
        } else {
-               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->rc = -ENODEV;
+               ap_msg->receive(ap_dev, ap_msg, NULL);
                rc = -ENODEV;
        }
        spin_unlock_bh(&ap_dev->lock);
index 83cc9e404a77d15f7ae74eacd6870b81413b07b7..af9b705976bc19f5a6436f48dfb1a9b06297724e 100644 (file)
@@ -187,6 +187,7 @@ struct ap_message {
        unsigned long long psmid;       /* Message id. */
        void *message;                  /* Pointer to message buffer. */
        size_t length;                  /* Message length. */
+       int rc;                         /* Return code for this message */
 
        void *private;                  /* ap driver private pointer. */
        unsigned int special:1;         /* Used for special commands. */
@@ -219,6 +220,7 @@ static inline void ap_init_message(struct ap_message *ap_msg)
 {
        ap_msg->psmid = 0;
        ap_msg->length = 0;
+       ap_msg->rc = 0;
        ap_msg->special = 0;
        ap_msg->receive = NULL;
 }
index 6c9af133296745dc3b4ef005ad56bdae1fa682b3..71ceee9137a88919d8c53ca7148afff0a7211e95 100644 (file)
@@ -395,10 +395,8 @@ static void zcrypt_cex2a_receive(struct ap_device *ap_dev,
        int length;
 
        /* Copy the reply message to the request message buffer. */
-       if (IS_ERR(reply)) {
-               memcpy(msg->message, &error_reply, sizeof(error_reply));
-               goto out;
-       }
+       if (!reply)
+               goto out;       /* ap_msg->rc indicates the error */
        t80h = reply->message;
        if (t80h->type == TYPE80_RSP_CODE) {
                if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A)
@@ -449,10 +447,12 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, mex->outputdata,
-                                     mex->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, mex->outputdata,
+                                             mex->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -493,10 +493,12 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, crt->outputdata,
-                                     crt->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, crt->outputdata,
+                                             crt->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
index 46b324ce6c7a8d46fe335b6b994db455e7c3beb8..74762214193b0326a8ee2cb6d21141f3c414123b 100644 (file)
@@ -829,10 +829,8 @@ static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
        int length;
 
        /* Copy the reply message to the request message buffer. */
-       if (IS_ERR(reply)) {
-               memcpy(msg->message, &error_reply, sizeof(error_reply));
-               goto out;
-       }
+       if (!reply)
+               goto out;       /* ap_msg->rc indicates the error */
        t86r = reply->message;
        if (t86r->hdr.type == TYPE86_RSP_CODE &&
                 t86r->cprbx.cprb_ver_id == 0x02) {
@@ -880,10 +878,8 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
        int length;
 
        /* Copy the reply message to the request message buffer. */
-       if (IS_ERR(reply)) {
-               memcpy(msg->message, &error_reply, sizeof(error_reply));
-               goto out;
-       }
+       if (!reply)
+               goto out;       /* ap_msg->rc indicates the error */
        t86r = reply->message;
        if (t86r->hdr.type == TYPE86_RSP_CODE &&
            t86r->cprbx.cprb_ver_id == 0x04) {
@@ -935,10 +931,13 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
        init_completion(&resp_type.work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&resp_type.work);
-       if (rc == 0)
-               rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
-                                         mex->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response_ica(zdev, &ap_msg,
+                                                 mex->outputdata,
+                                                 mex->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -976,10 +975,13 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
        init_completion(&resp_type.work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&resp_type.work);
-       if (rc == 0)
-               rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
-                                         crt->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response_ica(zdev, &ap_msg,
+                                                 crt->outputdata,
+                                                 crt->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -1017,9 +1019,11 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
        init_completion(&resp_type.work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&resp_type.work);
-       if (rc == 0)
-               rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -1057,9 +1061,12 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
        init_completion(&resp_type.work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&resp_type.work);
-       if (rc == 0)
-               rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
-       else /* Signal pending. */
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
+       } else
+               /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 
 out_free:
@@ -1096,9 +1103,11 @@ static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
        init_completion(&resp_type.work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&resp_type.work);
-       if (rc == 0)
-               rc = convert_response_rng(zdev, &ap_msg, buffer);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response_rng(zdev, &ap_msg, buffer);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
        kfree(ap_msg.message);
index 2f220208da6352501ad97d28b5f0f5d0a69cbd94..6af9c9fd39b1125080b51e328e75d9153a438b78 100644 (file)
@@ -258,10 +258,8 @@ static void zcrypt_pcica_receive(struct ap_device *ap_dev,
        int length;
 
        /* Copy the reply message to the request message buffer. */
-       if (IS_ERR(reply)) {
-               memcpy(msg->message, &error_reply, sizeof(error_reply));
-               goto out;
-       }
+       if (!reply)
+               goto out;       /* ap_msg->rc indicates the error */
        t84h = reply->message;
        if (t84h->code == TYPE84_RSP_CODE) {
                length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len);
@@ -302,10 +300,12 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, mex->outputdata,
-                                     mex->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, mex->outputdata,
+                                             mex->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -341,10 +341,12 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, crt->outputdata,
-                                     crt->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, crt->outputdata,
+                                             crt->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
index 9f18876f058b9b33a5c4f17cbd771fa534875cae..4cf2115adfc18f21d886d6da66041dce48542697 100644 (file)
@@ -461,10 +461,8 @@ static void zcrypt_pcicc_receive(struct ap_device *ap_dev,
        int length;
 
        /* Copy the reply message to the request message buffer. */
-       if (IS_ERR(reply)) {
-               memcpy(msg->message, &error_reply, sizeof(error_reply));
-               goto out;
-       }
+       if (!reply)
+               goto out;       /* ap_msg->rc indicates the error */
        t86r = reply->message;
        if (t86r->hdr.type == TYPE86_RSP_CODE &&
                 t86r->cprb.cprb_ver_id == 0x01) {
@@ -508,10 +506,12 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, mex->outputdata,
-                                     mex->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, mex->outputdata,
+                                             mex->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
@@ -548,10 +548,12 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
        init_completion(&work);
        ap_queue_message(zdev->ap_dev, &ap_msg);
        rc = wait_for_completion_interruptible(&work);
-       if (rc == 0)
-               rc = convert_response(zdev, &ap_msg, crt->outputdata,
-                                     crt->outputdatalength);
-       else
+       if (rc == 0) {
+               rc = ap_msg.rc;
+               if (rc == 0)
+                       rc = convert_response(zdev, &ap_msg, crt->outputdata,
+                                             crt->outputdatalength);
+       } else
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free: