|
@@ -25,6 +25,7 @@
|
|
|
#include "linux/platform_data/qcom_crypto_device.h"
|
|
|
#include "linux/qcedev.h"
|
|
|
#include <linux/interconnect.h>
|
|
|
+#include <linux/delay.h>
|
|
|
|
|
|
#include <crypto/hash.h>
|
|
|
#include "qcedevi.h"
|
|
@@ -50,6 +51,7 @@ enum qcedev_req_status {
|
|
|
QCEDEV_REQ_CURRENT = 0,
|
|
|
QCEDEV_REQ_WAITING = 1,
|
|
|
QCEDEV_REQ_SUBMITTED = 2,
|
|
|
+ QCEDEV_REQ_DONE = 3,
|
|
|
};
|
|
|
|
|
|
static uint8_t _std_init_vector_sha1_uint8[] = {
|
|
@@ -69,17 +71,6 @@ static uint8_t _std_init_vector_sha256_uint8[] = {
|
|
|
#define QCEDEV_CTX_USE_HW_KEY 0x00000001
|
|
|
#define QCEDEV_CTX_USE_PIPE_KEY 0x00000002
|
|
|
|
|
|
-// Key timer expiry for pipes 1-15 (Status3)
|
|
|
-#define PIPE_KEY_TIMER_EXPIRED_STATUS3_MASK 0x000000FF
|
|
|
-// Key timer expiry for pipes 16-19 (Status6)
|
|
|
-#define PIPE_KEY_TIMER_EXPIRED_STATUS6_MASK 0x00000003
|
|
|
-// Key pause for pipes 1-15 (Status3)
|
|
|
-#define PIPE_KEY_PAUSE_STATUS3_MASK 0xFF0000
|
|
|
-// Key pause for pipes 16-19 (Status6)
|
|
|
-#define PIPE_KEY_PAUSE_STATUS6_MASK 0x30000
|
|
|
-
|
|
|
-#define QCEDEV_STATUS1_ERR_INTR_MASK 0x10
|
|
|
-
|
|
|
static DEFINE_MUTEX(send_cmd_lock);
|
|
|
static DEFINE_MUTEX(qcedev_sent_bw_req);
|
|
|
static DEFINE_MUTEX(hash_access_lock);
|
|
@@ -324,8 +315,10 @@ static void req_done(unsigned long data)
|
|
|
areq = podev->active_command;
|
|
|
podev->active_command = NULL;
|
|
|
|
|
|
- if (areq && !areq->timed_out)
|
|
|
+ if (areq && !areq->timed_out) {
|
|
|
complete(&areq->complete);
|
|
|
+ areq->state = QCEDEV_REQ_DONE;
|
|
|
+ }
|
|
|
|
|
|
/* Look through queued requests and wake up the corresponding thread */
|
|
|
if (!list_empty(&podev->ready_commands)) {
|
|
@@ -686,52 +679,29 @@ static int start_sha_req(struct qcedev_control *podev,
|
|
|
};
|
|
|
|
|
|
static void qcedev_check_crypto_status(
|
|
|
- struct qcedev_async_req *qcedev_areq, void *handle,
|
|
|
- bool print_err)
|
|
|
+ struct qcedev_async_req *qcedev_areq, void *handle)
|
|
|
{
|
|
|
- unsigned int s1, s2, s3, s4, s5, s6;
|
|
|
+ struct qce_error error = {0};
|
|
|
|
|
|
qcedev_areq->offload_cipher_op_req.err = QCEDEV_OFFLOAD_NO_ERROR;
|
|
|
- qce_get_crypto_status(handle, &s1, &s2, &s3, &s4, &s5, &s6);
|
|
|
+ qce_get_crypto_status(handle, &error);
|
|
|
|
|
|
- if (print_err) {
|
|
|
- pr_err("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
|
|
|
- s1, s2, s3, s4, s5, s6);
|
|
|
- }
|
|
|
-
|
|
|
- // Check for key timer expiry
|
|
|
- if ((s6 & PIPE_KEY_TIMER_EXPIRED_STATUS6_MASK) ||
|
|
|
- (s3 & PIPE_KEY_TIMER_EXPIRED_STATUS3_MASK)) {
|
|
|
- pr_info("%s: crypto timer expired\n", __func__);
|
|
|
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
|
|
|
- s1, s2, s3, s4, s5, s6);
|
|
|
+ if (error.timer_error) {
|
|
|
qcedev_areq->offload_cipher_op_req.err =
|
|
|
- QCEDEV_OFFLOAD_KEY_TIMER_EXPIRED_ERROR;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Check for key pause
|
|
|
- if ((s6 & PIPE_KEY_PAUSE_STATUS6_MASK) ||
|
|
|
- (s3 & PIPE_KEY_PAUSE_STATUS3_MASK)) {
|
|
|
- pr_info("%s: crypto key paused\n", __func__);
|
|
|
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
|
|
|
- s1, s2, s3, s4, s5, s6);
|
|
|
+ QCEDEV_OFFLOAD_KEY_TIMER_EXPIRED_ERROR;
|
|
|
+ } else if (error.key_paused) {
|
|
|
qcedev_areq->offload_cipher_op_req.err =
|
|
|
- QCEDEV_OFFLOAD_KEY_PAUSE_ERROR;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Check for generic error
|
|
|
- if (s1 & QCEDEV_STATUS1_ERR_INTR_MASK) {
|
|
|
- pr_err("%s: generic crypto error\n", __func__);
|
|
|
- pr_info("%s: sts = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__,
|
|
|
- s1, s2, s3, s4, s5, s6);
|
|
|
+ QCEDEV_OFFLOAD_KEY_PAUSE_ERROR;
|
|
|
+ } else if (error.generic_error) {
|
|
|
qcedev_areq->offload_cipher_op_req.err =
|
|
|
- QCEDEV_OFFLOAD_GENERIC_ERROR;
|
|
|
- return;
|
|
|
+ QCEDEV_OFFLOAD_GENERIC_ERROR;
|
|
|
}
|
|
|
+
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
+#define MAX_RETRIES 333
|
|
|
+
|
|
|
static int submit_req(struct qcedev_async_req *qcedev_areq,
|
|
|
struct qcedev_handle *handle)
|
|
|
{
|
|
@@ -741,14 +711,13 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
|
|
|
struct qcedev_stat *pstat;
|
|
|
int current_req_info = 0;
|
|
|
int wait = MAX_CRYPTO_WAIT_TIME;
|
|
|
- bool print_sts = false;
|
|
|
struct qcedev_async_req *new_req = NULL;
|
|
|
+ int retries = 0;
|
|
|
|
|
|
qcedev_areq->err = 0;
|
|
|
podev = handle->cntl;
|
|
|
init_waitqueue_head(&qcedev_areq->wait_q);
|
|
|
|
|
|
-
|
|
|
spin_lock_irqsave(&podev->lock, flags);
|
|
|
|
|
|
/*
|
|
@@ -823,17 +792,25 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
|
|
|
*/
|
|
|
pr_err("%s: wait timed out, req info = %d\n", __func__,
|
|
|
current_req_info);
|
|
|
- print_sts = true;
|
|
|
+ qcedev_check_crypto_status(qcedev_areq, podev->qce);
|
|
|
+ if (qcedev_areq->offload_cipher_op_req.err ==
|
|
|
+ QCEDEV_OFFLOAD_NO_ERROR) {
|
|
|
+ pr_err("%s: no error, wait for request to be done", __func__);
|
|
|
+ while (qcedev_areq->state != QCEDEV_REQ_DONE &&
|
|
|
+ retries < MAX_RETRIES) {
|
|
|
+ usleep_range(3000, 5000);
|
|
|
+ retries++;
|
|
|
+ pr_err("%s: waiting for req state to be done, retries = %d",
|
|
|
+ __func__, retries);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
spin_lock_irqsave(&podev->lock, flags);
|
|
|
- qcedev_check_crypto_status(qcedev_areq, podev->qce, print_sts);
|
|
|
qcedev_areq->timed_out = true;
|
|
|
ret = qce_manage_timeout(podev->qce, current_req_info);
|
|
|
- if (ret) {
|
|
|
+ if (ret)
|
|
|
pr_err("%s: error during manage timeout", __func__);
|
|
|
- qcedev_areq->err = -EIO;
|
|
|
- spin_unlock_irqrestore(&podev->lock, flags);
|
|
|
- return qcedev_areq->err;
|
|
|
- }
|
|
|
+
|
|
|
spin_unlock_irqrestore(&podev->lock, flags);
|
|
|
tasklet_schedule(&podev->done_tasklet);
|
|
|
if (qcedev_areq->offload_cipher_op_req.err !=
|