1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) 2 /* Copyright(c) 2022 Intel Corporation */ 3 #include <crypto/algapi.h> 4 #include "adf_transport.h" 5 #include "qat_algs_send.h" 6 #include "qat_crypto.h" 7 8 #define ADF_MAX_RETRIES 20 9 10 static int qat_alg_send_message_retry(struct qat_alg_req *req) 11 { 12 int ret = 0, ctr = 0; 13 14 do { 15 ret = adf_send_message(req->tx_ring, req->fw_req); 16 } while (ret == -EAGAIN && ctr++ < ADF_MAX_RETRIES); 17 18 if (ret == -EAGAIN) 19 return -ENOSPC; 20 21 return -EINPROGRESS; 22 } 23 24 void qat_alg_send_backlog(struct qat_instance_backlog *backlog) 25 { 26 struct qat_alg_req *req, *tmp; 27 28 spin_lock_bh(&backlog->lock); 29 list_for_each_entry_safe(req, tmp, &backlog->list, list) { 30 if (adf_send_message(req->tx_ring, req->fw_req)) { 31 /* The HW ring is full. Do nothing. 32 * qat_alg_send_backlog() will be invoked again by 33 * another callback. 34 */ 35 break; 36 } 37 list_del(&req->list); 38 crypto_request_complete(req->base, -EINPROGRESS); 39 } 40 spin_unlock_bh(&backlog->lock); 41 } 42 43 static void qat_alg_backlog_req(struct qat_alg_req *req, 44 struct qat_instance_backlog *backlog) 45 { 46 INIT_LIST_HEAD(&req->list); 47 48 spin_lock_bh(&backlog->lock); 49 list_add_tail(&req->list, &backlog->list); 50 spin_unlock_bh(&backlog->lock); 51 } 52 53 static int qat_alg_send_message_maybacklog(struct qat_alg_req *req) 54 { 55 struct qat_instance_backlog *backlog = req->backlog; 56 struct adf_etr_ring_data *tx_ring = req->tx_ring; 57 u32 *fw_req = req->fw_req; 58 59 /* If any request is already backlogged, then add to backlog list */ 60 if (!list_empty(&backlog->list)) 61 goto enqueue; 62 63 /* If ring is nearly full, then add to backlog list */ 64 if (adf_ring_nearly_full(tx_ring)) 65 goto enqueue; 66 67 /* If adding request to HW ring fails, then add to backlog list */ 68 if (adf_send_message(tx_ring, fw_req)) 69 goto enqueue; 70 71 return -EINPROGRESS; 72 73 enqueue: 74 qat_alg_backlog_req(req, backlog); 75 76 return -EBUSY; 77 } 78 79 int qat_alg_send_message(struct qat_alg_req *req) 80 { 81 u32 flags = req->base->flags; 82 83 if (flags & CRYPTO_TFM_REQ_MAY_BACKLOG) 84 return qat_alg_send_message_maybacklog(req); 85 else 86 return qat_alg_send_message_retry(req); 87 } 88