[1/2] common/qat: get version of QAT firmware
Checks
Commit Message
This patch adds the function for retrieving QAT firmware
version, required to check the internal capabilities that
depend on the FW version.
Signed-off-by: Adam Dybkowski <adamx.dybkowski@intel.com>
---
drivers/common/qat/qat_adf/icp_qat_fw.h | 2 +
drivers/common/qat/qat_qp.c | 89 +++++++++++++++++++++++++
drivers/common/qat/qat_qp.h | 3 +
3 files changed, 94 insertions(+)
Comments
Hi Adam,
> -----Original Message-----
> From: Dybkowski, AdamX <adamx.dybkowski@intel.com>
> Sent: Thursday, March 12, 2020 2:14 PM
> To: dev@dpdk.org; Trahe, Fiona <fiona.trahe@intel.com>; akhil.goyal@nxp.com
> Cc: Dybkowski, AdamX <adamx.dybkowski@intel.com>
> Subject: [PATCH 1/2] common/qat: get version of QAT firmware
>
> This patch adds the function for retrieving QAT firmware
> version, required to check the internal capabilities that
> depend on the FW version.
>
> Signed-off-by: Adam Dybkowski <adamx.dybkowski@intel.com>
> ---
> drivers/common/qat/qat_adf/icp_qat_fw.h | 2 +
> drivers/common/qat/qat_qp.c | 89 +++++++++++++++++++++++++
> drivers/common/qat/qat_qp.h | 3 +
> 3 files changed, 94 insertions(+)
>
> diff --git a/drivers/common/qat/qat_adf/icp_qat_fw.h b/drivers/common/qat/qat_adf/icp_qat_fw.h
> index 1265c2a13..be10fc9bd 100644
> --- a/drivers/common/qat/qat_adf/icp_qat_fw.h
> +++ b/drivers/common/qat/qat_adf/icp_qat_fw.h
> @@ -121,6 +121,8 @@ struct icp_qat_fw_comn_resp {
> #define ICP_QAT_FW_COMN_CNV_FLAG_MASK 0x1
> #define ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS 5
> #define ICP_QAT_FW_COMN_CNVNR_FLAG_MASK 0x1
> +#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS 0
> +#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK 0x1
>
> #define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \
> icp_qat_fw_comn_req_hdr_t.service_type
> diff --git a/drivers/common/qat/qat_qp.c b/drivers/common/qat/qat_qp.c
> index 9958789f0..93685aeb0 100644
> --- a/drivers/common/qat/qat_qp.c
> +++ b/drivers/common/qat/qat_qp.c
> @@ -19,6 +19,7 @@
> #include "qat_comp.h"
> #include "adf_transport_access_macros.h"
>
> +#define QAT_CQ_MAX_DEQ_RETRIES 10
>
> #define ADF_MAX_DESC 4096
> #define ADF_MIN_DESC 128
> @@ -695,6 +696,94 @@ qat_dequeue_op_burst(void *qp, void **ops, uint16_t nb_ops)
> return resp_counter;
> }
>
> +/* This is almost same as dequeue_op_burst, without the atomic, without stats
> + * and without the op. Dequeues one response.
> + */
> +static uint8_t
> +qat_cq_dequeue_response(struct qat_qp *qp, void *out_data)
> +{
> + uint8_t result = 0;
> + uint8_t retries = 0;
> + struct qat_queue *queue = &(qp->rx_q);
> + struct icp_qat_fw_comn_resp *resp_msg = (struct icp_qat_fw_comn_resp *)
> + ((uint8_t *)queue->base_addr + queue->head);
> +
> + while (retries++ < QAT_CQ_MAX_DEQ_RETRIES &&
> + *(uint32_t *)resp_msg == ADF_RING_EMPTY_SIG) {
> + /* loop waiting for response until we reach the timeout */
> + rte_delay_ms(20);
> + }
> +
> + if (*(uint32_t *)resp_msg != ADF_RING_EMPTY_SIG) {
> + /* response received, check status flag */
> + if (ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(
> + resp_msg->comn_hdr.comn_status) ==
> + ICP_QAT_FW_COMN_STATUS_FLAG_OK) {
> + /* success */
> + memcpy(out_data, resp_msg, queue->msg_size);
> + result = 1;
> + }
> +
[Fiona] Need to distinguish between the case where no response is received (something bad happened - can't use this ring) and an
error response is received - corner case, but could happen in some older fw, so ok to assume the issue is only with
this message and fw is otherwise ok.
So just move the result = 1 outside the bracket and return 0 in out_data in this case.
> + queue->head = adf_modulo(queue->head + queue->msg_size,
> + queue->modulo_mask);
> + rxq_free_desc(qp, queue);
> + }
> +
> + return result;
> +}
> +
> +/* Sends a NULL message and extracts QAT fw version from the response.
> + * Used to determine detailed capabilities based on the fw version number.
> + * This assumes that there are no inflight messages, i.e. assumes there's space
> + * on the qp, one message is sent and only one response collected.
> + * Returns fw version number or a negative error code.
[Fiona] update comment to include the 3rd possible outcome - 0 = don't know fw version.
> + */
> +int
> +qat_cq_get_fw_version(struct qat_qp *qp)
> +{
> + struct qat_queue *queue = &(qp->tx_q);
> + uint8_t *base_addr = (uint8_t *)queue->base_addr;
> + struct icp_qat_fw_comn_req null_msg;
> + struct icp_qat_fw_comn_resp response;
> +
> + /* prepare the NULL request */
> + memset(&null_msg, 0, sizeof(null_msg));
> + null_msg.comn_hdr.hdr_flags =
> + ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
> + null_msg.comn_hdr.service_type = ICP_QAT_FW_COMN_REQ_NULL;
> + null_msg.comn_hdr.service_cmd_id = ICP_QAT_FW_NULL_REQ_SERV_ID;
> +
> +#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
> + QAT_DP_HEXDUMP_LOG(DEBUG, "NULL request", &null_msg, sizeof(null_msg));
> +#endif
> +
> + /* send the NULL request */
> + memcpy(base_addr + queue->tail, &null_msg, sizeof(null_msg));
> + queue->tail = adf_modulo(queue->tail + queue->msg_size,
> + queue->modulo_mask);
> + txq_write_tail(qp, queue);
> +
> + /* receive a response */
> + memset(&response, 0, sizeof(response));
> + if (qat_cq_dequeue_response(qp, &response)) {
> +
> +#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
> + QAT_DP_HEXDUMP_LOG(DEBUG, "NULL response:", &response,
> + sizeof(response));
> +#endif
> + /* if LW0 bit 24 is set - then the fw version was returned */
> + if (QAT_FIELD_GET(response.comn_hdr.hdr_flags,
> + ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS,
> + ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK))
> + return response.resrvd[0]; /* return LW4 */
> + else
> + return 0; /* not set - we don't know fw version */
> + }
> +
> + QAT_LOG(ERR, "No response received");
> + return -EINVAL;
> +}
> +
> __rte_weak int
> qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
> void *op_cookie __rte_unused,
> diff --git a/drivers/common/qat/qat_qp.h b/drivers/common/qat/qat_qp.h
> index 0b95ea3c9..47ad5dd20 100644
> --- a/drivers/common/qat/qat_qp.h
> +++ b/drivers/common/qat/qat_qp.h
> @@ -103,6 +103,9 @@ int
> qat_qps_per_service(const struct qat_qp_hw_data *qp_hw_data,
> enum qat_service_type service);
>
> +int
> +qat_cq_get_fw_version(struct qat_qp *qp);
> +
> /* Needed for weak function*/
> int
> qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
> --
> 2.17.1
@@ -121,6 +121,8 @@ struct icp_qat_fw_comn_resp {
#define ICP_QAT_FW_COMN_CNV_FLAG_MASK 0x1
#define ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS 5
#define ICP_QAT_FW_COMN_CNVNR_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS 0
+#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK 0x1
#define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \
icp_qat_fw_comn_req_hdr_t.service_type
@@ -19,6 +19,7 @@
#include "qat_comp.h"
#include "adf_transport_access_macros.h"
+#define QAT_CQ_MAX_DEQ_RETRIES 10
#define ADF_MAX_DESC 4096
#define ADF_MIN_DESC 128
@@ -695,6 +696,94 @@ qat_dequeue_op_burst(void *qp, void **ops, uint16_t nb_ops)
return resp_counter;
}
+/* This is almost same as dequeue_op_burst, without the atomic, without stats
+ * and without the op. Dequeues one response.
+ */
+static uint8_t
+qat_cq_dequeue_response(struct qat_qp *qp, void *out_data)
+{
+ uint8_t result = 0;
+ uint8_t retries = 0;
+ struct qat_queue *queue = &(qp->rx_q);
+ struct icp_qat_fw_comn_resp *resp_msg = (struct icp_qat_fw_comn_resp *)
+ ((uint8_t *)queue->base_addr + queue->head);
+
+ while (retries++ < QAT_CQ_MAX_DEQ_RETRIES &&
+ *(uint32_t *)resp_msg == ADF_RING_EMPTY_SIG) {
+ /* loop waiting for response until we reach the timeout */
+ rte_delay_ms(20);
+ }
+
+ if (*(uint32_t *)resp_msg != ADF_RING_EMPTY_SIG) {
+ /* response received, check status flag */
+ if (ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(
+ resp_msg->comn_hdr.comn_status) ==
+ ICP_QAT_FW_COMN_STATUS_FLAG_OK) {
+ /* success */
+ memcpy(out_data, resp_msg, queue->msg_size);
+ result = 1;
+ }
+
+ queue->head = adf_modulo(queue->head + queue->msg_size,
+ queue->modulo_mask);
+ rxq_free_desc(qp, queue);
+ }
+
+ return result;
+}
+
+/* Sends a NULL message and extracts QAT fw version from the response.
+ * Used to determine detailed capabilities based on the fw version number.
+ * This assumes that there are no inflight messages, i.e. assumes there's space
+ * on the qp, one message is sent and only one response collected.
+ * Returns fw version number or a negative error code.
+ */
+int
+qat_cq_get_fw_version(struct qat_qp *qp)
+{
+ struct qat_queue *queue = &(qp->tx_q);
+ uint8_t *base_addr = (uint8_t *)queue->base_addr;
+ struct icp_qat_fw_comn_req null_msg;
+ struct icp_qat_fw_comn_resp response;
+
+ /* prepare the NULL request */
+ memset(&null_msg, 0, sizeof(null_msg));
+ null_msg.comn_hdr.hdr_flags =
+ ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
+ null_msg.comn_hdr.service_type = ICP_QAT_FW_COMN_REQ_NULL;
+ null_msg.comn_hdr.service_cmd_id = ICP_QAT_FW_NULL_REQ_SERV_ID;
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+ QAT_DP_HEXDUMP_LOG(DEBUG, "NULL request", &null_msg, sizeof(null_msg));
+#endif
+
+ /* send the NULL request */
+ memcpy(base_addr + queue->tail, &null_msg, sizeof(null_msg));
+ queue->tail = adf_modulo(queue->tail + queue->msg_size,
+ queue->modulo_mask);
+ txq_write_tail(qp, queue);
+
+ /* receive a response */
+ memset(&response, 0, sizeof(response));
+ if (qat_cq_dequeue_response(qp, &response)) {
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+ QAT_DP_HEXDUMP_LOG(DEBUG, "NULL response:", &response,
+ sizeof(response));
+#endif
+ /* if LW0 bit 24 is set - then the fw version was returned */
+ if (QAT_FIELD_GET(response.comn_hdr.hdr_flags,
+ ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS,
+ ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK))
+ return response.resrvd[0]; /* return LW4 */
+ else
+ return 0; /* not set - we don't know fw version */
+ }
+
+ QAT_LOG(ERR, "No response received");
+ return -EINVAL;
+}
+
__rte_weak int
qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
void *op_cookie __rte_unused,
@@ -103,6 +103,9 @@ int
qat_qps_per_service(const struct qat_qp_hw_data *qp_hw_data,
enum qat_service_type service);
+int
+qat_cq_get_fw_version(struct qat_qp *qp);
+
/* Needed for weak function*/
int
qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,