mirror of https://gitee.com/openkylin/linux.git
s390/zcrypt: use explicit return code for flushed requests
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>
This commit is contained in:
parent
fcd0d1f637
commit
f58fe33600
|
@ -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_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
|
||||||
list_del_init(&ap_msg->list);
|
list_del_init(&ap_msg->list);
|
||||||
ap_dev->pendingq_count--;
|
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_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
|
||||||
list_del_init(&ap_msg->list);
|
list_del_init(&ap_msg->list);
|
||||||
ap_dev->requestq_count--;
|
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;
|
return -EBUSY;
|
||||||
case AP_RESPONSE_REQ_FAC_NOT_INST:
|
case AP_RESPONSE_REQ_FAC_NOT_INST:
|
||||||
case AP_RESPONSE_MESSAGE_TOO_BIG:
|
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;
|
return -EINVAL;
|
||||||
default: /* Device is gone. */
|
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;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1726,7 +1730,8 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
|
||||||
if (rc == -ENODEV)
|
if (rc == -ENODEV)
|
||||||
ap_dev->unregistered = 1;
|
ap_dev->unregistered = 1;
|
||||||
} else {
|
} 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;
|
rc = -ENODEV;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&ap_dev->lock);
|
spin_unlock_bh(&ap_dev->lock);
|
||||||
|
|
|
@ -187,6 +187,7 @@ struct ap_message {
|
||||||
unsigned long long psmid; /* Message id. */
|
unsigned long long psmid; /* Message id. */
|
||||||
void *message; /* Pointer to message buffer. */
|
void *message; /* Pointer to message buffer. */
|
||||||
size_t length; /* Message length. */
|
size_t length; /* Message length. */
|
||||||
|
int rc; /* Return code for this message */
|
||||||
|
|
||||||
void *private; /* ap driver private pointer. */
|
void *private; /* ap driver private pointer. */
|
||||||
unsigned int special:1; /* Used for special commands. */
|
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->psmid = 0;
|
||||||
ap_msg->length = 0;
|
ap_msg->length = 0;
|
||||||
|
ap_msg->rc = 0;
|
||||||
ap_msg->special = 0;
|
ap_msg->special = 0;
|
||||||
ap_msg->receive = NULL;
|
ap_msg->receive = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,10 +395,8 @@ static void zcrypt_cex2a_receive(struct ap_device *ap_dev,
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Copy the reply message to the request message buffer. */
|
/* Copy the reply message to the request message buffer. */
|
||||||
if (IS_ERR(reply)) {
|
if (!reply)
|
||||||
memcpy(msg->message, &error_reply, sizeof(error_reply));
|
goto out; /* ap_msg->rc indicates the error */
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
t80h = reply->message;
|
t80h = reply->message;
|
||||||
if (t80h->type == TYPE80_RSP_CODE) {
|
if (t80h->type == TYPE80_RSP_CODE) {
|
||||||
if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A)
|
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);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
rc = ap_msg.rc;
|
||||||
mex->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
||||||
|
mex->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -493,10 +493,12 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
|
||||||
init_completion(&work);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
rc = ap_msg.rc;
|
||||||
crt->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
||||||
|
crt->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
|
|
@ -829,10 +829,8 @@ static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Copy the reply message to the request message buffer. */
|
/* Copy the reply message to the request message buffer. */
|
||||||
if (IS_ERR(reply)) {
|
if (!reply)
|
||||||
memcpy(msg->message, &error_reply, sizeof(error_reply));
|
goto out; /* ap_msg->rc indicates the error */
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
t86r = reply->message;
|
t86r = reply->message;
|
||||||
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
||||||
t86r->cprbx.cprb_ver_id == 0x02) {
|
t86r->cprbx.cprb_ver_id == 0x02) {
|
||||||
|
@ -880,10 +878,8 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Copy the reply message to the request message buffer. */
|
/* Copy the reply message to the request message buffer. */
|
||||||
if (IS_ERR(reply)) {
|
if (!reply)
|
||||||
memcpy(msg->message, &error_reply, sizeof(error_reply));
|
goto out; /* ap_msg->rc indicates the error */
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
t86r = reply->message;
|
t86r = reply->message;
|
||||||
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
||||||
t86r->cprbx.cprb_ver_id == 0x04) {
|
t86r->cprbx.cprb_ver_id == 0x04) {
|
||||||
|
@ -935,10 +931,13 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
|
||||||
init_completion(&resp_type.work);
|
init_completion(&resp_type.work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&resp_type.work);
|
rc = wait_for_completion_interruptible(&resp_type.work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
|
rc = ap_msg.rc;
|
||||||
mex->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response_ica(zdev, &ap_msg,
|
||||||
|
mex->outputdata,
|
||||||
|
mex->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -976,10 +975,13 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
|
||||||
init_completion(&resp_type.work);
|
init_completion(&resp_type.work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&resp_type.work);
|
rc = wait_for_completion_interruptible(&resp_type.work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
|
rc = ap_msg.rc;
|
||||||
crt->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response_ica(zdev, &ap_msg,
|
||||||
|
crt->outputdata,
|
||||||
|
crt->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -1017,9 +1019,11 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
|
||||||
init_completion(&resp_type.work);
|
init_completion(&resp_type.work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&resp_type.work);
|
rc = wait_for_completion_interruptible(&resp_type.work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
|
rc = ap_msg.rc;
|
||||||
else
|
if (rc == 0)
|
||||||
|
rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -1057,9 +1061,12 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
|
||||||
init_completion(&resp_type.work);
|
init_completion(&resp_type.work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&resp_type.work);
|
rc = wait_for_completion_interruptible(&resp_type.work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
|
rc = ap_msg.rc;
|
||||||
else /* Signal pending. */
|
if (rc == 0)
|
||||||
|
rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
|
||||||
|
} else
|
||||||
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -1096,9 +1103,11 @@ static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
|
||||||
init_completion(&resp_type.work);
|
init_completion(&resp_type.work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&resp_type.work);
|
rc = wait_for_completion_interruptible(&resp_type.work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response_rng(zdev, &ap_msg, buffer);
|
rc = ap_msg.rc;
|
||||||
else
|
if (rc == 0)
|
||||||
|
rc = convert_response_rng(zdev, &ap_msg, buffer);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
kfree(ap_msg.message);
|
kfree(ap_msg.message);
|
||||||
|
|
|
@ -258,10 +258,8 @@ static void zcrypt_pcica_receive(struct ap_device *ap_dev,
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Copy the reply message to the request message buffer. */
|
/* Copy the reply message to the request message buffer. */
|
||||||
if (IS_ERR(reply)) {
|
if (!reply)
|
||||||
memcpy(msg->message, &error_reply, sizeof(error_reply));
|
goto out; /* ap_msg->rc indicates the error */
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
t84h = reply->message;
|
t84h = reply->message;
|
||||||
if (t84h->code == TYPE84_RSP_CODE) {
|
if (t84h->code == TYPE84_RSP_CODE) {
|
||||||
length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len);
|
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);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
rc = ap_msg.rc;
|
||||||
mex->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
||||||
|
mex->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -341,10 +341,12 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
|
||||||
init_completion(&work);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
rc = ap_msg.rc;
|
||||||
crt->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
||||||
|
crt->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
|
|
@ -461,10 +461,8 @@ static void zcrypt_pcicc_receive(struct ap_device *ap_dev,
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/* Copy the reply message to the request message buffer. */
|
/* Copy the reply message to the request message buffer. */
|
||||||
if (IS_ERR(reply)) {
|
if (!reply)
|
||||||
memcpy(msg->message, &error_reply, sizeof(error_reply));
|
goto out; /* ap_msg->rc indicates the error */
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
t86r = reply->message;
|
t86r = reply->message;
|
||||||
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
if (t86r->hdr.type == TYPE86_RSP_CODE &&
|
||||||
t86r->cprb.cprb_ver_id == 0x01) {
|
t86r->cprb.cprb_ver_id == 0x01) {
|
||||||
|
@ -508,10 +506,12 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
|
||||||
init_completion(&work);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
rc = ap_msg.rc;
|
||||||
mex->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, mex->outputdata,
|
||||||
|
mex->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -548,10 +548,12 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
|
||||||
init_completion(&work);
|
init_completion(&work);
|
||||||
ap_queue_message(zdev->ap_dev, &ap_msg);
|
ap_queue_message(zdev->ap_dev, &ap_msg);
|
||||||
rc = wait_for_completion_interruptible(&work);
|
rc = wait_for_completion_interruptible(&work);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
rc = ap_msg.rc;
|
||||||
crt->outputdatalength);
|
if (rc == 0)
|
||||||
else
|
rc = convert_response(zdev, &ap_msg, crt->outputdata,
|
||||||
|
crt->outputdatalength);
|
||||||
|
} else
|
||||||
/* Signal pending. */
|
/* Signal pending. */
|
||||||
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
ap_cancel_message(zdev->ap_dev, &ap_msg);
|
||||||
out_free:
|
out_free:
|
||||||
|
|
Loading…
Reference in New Issue