// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) /* Copyright(c) 2022 Intel Corporation */ #include "adf_transport.h" #include "qat_algs_send.h" #include "qat_crypto.h" #define ADF_MAX_RETRIES 20 static int qat_alg_send_message_retry(struct qat_alg_req *req) { int ret = 0, ctr = 0; do { ret = adf_send_message(req->tx_ring, req->fw_req); } while (ret == -EAGAIN && ctr++ < ADF_MAX_RETRIES); if (ret == -EAGAIN) return -ENOSPC; return -EINPROGRESS; } void qat_alg_send_backlog(struct qat_instance_backlog *backlog) { struct qat_alg_req *req, *tmp; spin_lock_bh(&backlog->lock); list_for_each_entry_safe(req, tmp, &backlog->list, list) { if (adf_send_message(req->tx_ring, req->fw_req)) { /* The HW ring is full. Do nothing. * qat_alg_send_backlog() will be invoked again by * another callback. */ break; } list_del(&req->list); req->base->complete(req->base, -EINPROGRESS); } spin_unlock_bh(&backlog->lock); } static void qat_alg_backlog_req(struct qat_alg_req *req, struct qat_instance_backlog *backlog) { INIT_LIST_HEAD(&req->list); spin_lock_bh(&backlog->lock); list_add_tail(&req->list, &backlog->list); spin_unlock_bh(&backlog->lock); } static int qat_alg_send_message_maybacklog(struct qat_alg_req *req) { struct qat_instance_backlog *backlog = req->backlog; struct adf_etr_ring_data *tx_ring = req->tx_ring; u32 *fw_req = req->fw_req; /* If any request is already backlogged, then add to backlog list */ if (!list_empty(&backlog->list)) goto enqueue; /* If ring is nearly full, then add to backlog list */ if (adf_ring_nearly_full(tx_ring)) goto enqueue; /* If adding request to HW ring fails, then add to backlog list */ if (adf_send_message(tx_ring, fw_req)) goto enqueue; return -EINPROGRESS; enqueue: qat_alg_backlog_req(req, backlog); return -EBUSY; } int qat_alg_send_message(struct qat_alg_req *req) { u32 flags = req->base->flags; if (flags & CRYPTO_TFM_REQ_MAY_BACKLOG) return qat_alg_send_message_maybacklog(req); else return qat_alg_send_message_retry(req); }