Commit 673184a2 authored by Marco Chiappero's avatar Marco Chiappero Committed by Herbert Xu
Browse files

crypto: qat - introduce support for PFVF block messages



GEN2 devices use a single CSR for PFVF messages, which leaves up to 10 bits
of payload per single message. While such amount is sufficient for the
currently defined messages, the transfer of bigger and more complex data
streams from the PF to the VF requires a new mechanism that extends the
protocol.

This patch adds a new layer on top of the basic PFVF messaging, called
Block Messages, to encapsulate up to 126 bytes of data in a single
logical message across multiple PFVF messages of new types (SMALL,
MEDIUM and LARGE BLOCK), including (sub)types (BLKMSG_TYPE) to carry the
information about the actual Block Message.

Regardless of the size, each Block Message uses a two bytes header,
containing the version and size, to allow for extension while
maintaining compatibility. The size and the types of Block Messages are
defined as follow:

- small block messages:  up to 16 BLKMSG types of up to 30 bytes
- medium block messages: up to 8 BLKMSG types of up to 62 bytes
- large block messages:  up to 4 BLKMSG types of up to 126 bytes

It effectively works as reading a byte at a time from a block device and
for each of these new Block Messages:
- the requestor (always a VF) can either request a specific byte of the
  larger message, in order to retrieve the full message, or request the
  value of the CRC calculated for a specific message up to the provided
  size (to allow for messages to grow while maintaining forward
  compatibility)
- the responder (always the PF) will either return a single data or CRC
  byte, along with the indication of response type (or error).

This patch provides the basic infrastructure to perform the above
operations, without defining any new message.

As CRCs are required, this code now depends on the CRC8 module.

Note: as a consequence of the Block Messages design, sending multiple
PFVF messages in bursts, the interrupt rate limiting values on the PF are
increased.

Signed-off-by: default avatarMarco Chiappero <marco.chiappero@intel.com>
Co-developed-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: default avatarFiona Trahe <fiona.trahe@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3a5b2a08
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ config CRYPTO_DEV_QAT
	select CRYPTO_SHA512
	select CRYPTO_LIB_AES
	select FW_LOADER
	select CRC8

config CRYPTO_DEV_QAT_DH895xCC
	tristate "Support for Intel(R) DH895xCC"
+74 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ struct pfvf_message {
enum pf2vf_msgtype {
	ADF_PF2VF_MSGTYPE_RESTARTING		= 0x01,
	ADF_PF2VF_MSGTYPE_VERSION_RESP		= 0x02,
	ADF_PF2VF_MSGTYPE_BLKMSG_RESP		= 0x03,
};

/* VF->PF messages */
@@ -79,6 +80,9 @@ enum vf2pf_msgtype {
	ADF_VF2PF_MSGTYPE_SHUTDOWN		= 0x04,
	ADF_VF2PF_MSGTYPE_VERSION_REQ		= 0x05,
	ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ	= 0x06,
	ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ	= 0x07,
	ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ	= 0x08,
	ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ	= 0x09,
};

/* VF/PF compatibility version. */
@@ -97,4 +101,74 @@ enum pf2vf_compat_response {
	ADF_PF2VF_VF_COMPAT_UNKNOWN		= 0x03,
};

/* PF->VF Block Responses */
#define ADF_PF2VF_BLKMSG_RESP_TYPE_MASK		GENMASK(1, 0)
#define ADF_PF2VF_BLKMSG_RESP_DATA_MASK		GENMASK(9, 2)

enum pf2vf_blkmsg_resp_type {
	ADF_PF2VF_BLKMSG_RESP_TYPE_DATA		= 0x00,
	ADF_PF2VF_BLKMSG_RESP_TYPE_CRC		= 0x01,
	ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR	= 0x02,
};

/* PF->VF Block Error Code */
enum pf2vf_blkmsg_error {
	ADF_PF2VF_INVALID_BLOCK_TYPE		= 0x00,
	ADF_PF2VF_INVALID_BYTE_NUM_REQ		= 0x01,
	ADF_PF2VF_PAYLOAD_TRUNCATED		= 0x02,
	ADF_PF2VF_UNSPECIFIED_ERROR		= 0x03,
};

/* VF->PF Block Requests */
#define ADF_VF2PF_LARGE_BLOCK_TYPE_MASK		GENMASK(1, 0)
#define ADF_VF2PF_LARGE_BLOCK_BYTE_MASK		GENMASK(8, 2)
#define ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK	GENMASK(2, 0)
#define ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK	GENMASK(8, 3)
#define ADF_VF2PF_SMALL_BLOCK_TYPE_MASK		GENMASK(3, 0)
#define ADF_VF2PF_SMALL_BLOCK_BYTE_MASK		GENMASK(8, 4)
#define ADF_VF2PF_BLOCK_CRC_REQ_MASK		BIT(9)

/* PF->VF Block Request Types
 *  0..15 - 32 byte message
 * 16..23 - 64 byte message
 * 24..27 - 128 byte message
 */
/* No block messages as of yet */

#define ADF_VF2PF_SMALL_BLOCK_TYPE_MAX \
		(FIELD_MAX(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK))

#define ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX \
		(FIELD_MAX(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK) + \
		ADF_VF2PF_SMALL_BLOCK_TYPE_MAX + 1)

#define ADF_VF2PF_LARGE_BLOCK_TYPE_MAX \
		(FIELD_MAX(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK) + \
		ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX)

#define ADF_VF2PF_SMALL_BLOCK_BYTE_MAX \
		FIELD_MAX(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK)

#define ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX \
		FIELD_MAX(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK)

#define ADF_VF2PF_LARGE_BLOCK_BYTE_MAX \
		FIELD_MAX(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK)

struct pfvf_blkmsg_header {
	u8 version;
	u8 payload_size;
} __packed;

#define ADF_PFVF_BLKMSG_HEADER_SIZE		(sizeof(struct pfvf_blkmsg_header))
#define ADF_PFVF_BLKMSG_PAYLOAD_SIZE(blkmsg)	(sizeof(blkmsg) - \
							ADF_PFVF_BLKMSG_HEADER_SIZE)
#define ADF_PFVF_BLKMSG_MSG_SIZE(blkmsg)	(ADF_PFVF_BLKMSG_HEADER_SIZE + \
							(blkmsg)->hdr.payload_size)
#define ADF_PFVF_BLKMSG_MSG_MAX_SIZE		128

/* PF->VF Block message header bytes */
#define ADF_PFVF_BLKMSG_VER_BYTE		0
#define ADF_PFVF_BLKMSG_LEN_BYTE		1

#endif /* ADF_PFVF_MSG_H */
+3 −0
Original line number Diff line number Diff line
@@ -7,4 +7,7 @@

void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev);

typedef int (*adf_pf2vf_blkmsg_provider)(struct adf_accel_dev *accel_dev,
					 u8 *buffer, u8 compat);

#endif /* ADF_PFVF_PF_MSG_H */
+137 −0
Original line number Diff line number Diff line
@@ -6,7 +6,16 @@
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_pfvf_msg.h"
#include "adf_pfvf_pf_msg.h"
#include "adf_pfvf_pf_proto.h"
#include "adf_pfvf_utils.h"

typedef u8 (*pf2vf_blkmsg_data_getter_fn)(u8 const *blkmsg, u8 byte);

static const adf_pf2vf_blkmsg_provider pf2vf_blkmsg_providers[] = {
	NULL,				  /* no message type defined for value 0 */
	NULL,				  /* no message type defined for value 1 */
};

/**
 * adf_send_pf2vf_msg() - send PF to VF message
@@ -44,6 +53,128 @@ static struct pfvf_message adf_recv_vf2pf_msg(struct adf_accel_dev *accel_dev, u
	return pfvf_ops->recv_msg(accel_dev, pfvf_offset);
}

static adf_pf2vf_blkmsg_provider get_blkmsg_response_provider(u8 type)
{
	if (type >= ARRAY_SIZE(pf2vf_blkmsg_providers))
		return NULL;

	return pf2vf_blkmsg_providers[type];
}

/* Byte pf2vf_blkmsg_data_getter_fn callback */
static u8 adf_pf2vf_blkmsg_get_byte(u8 const *blkmsg, u8 index)
{
	return blkmsg[index];
}

/* CRC pf2vf_blkmsg_data_getter_fn callback */
static u8 adf_pf2vf_blkmsg_get_crc(u8 const *blkmsg, u8 count)
{
	/* count is 0-based, turn it into a length */
	return adf_pfvf_calc_blkmsg_crc(blkmsg, count + 1);
}

static int adf_pf2vf_blkmsg_get_data(struct adf_accel_vf_info *vf_info,
				     u8 type, u8 byte, u8 max_size, u8 *data,
				     pf2vf_blkmsg_data_getter_fn data_getter)
{
	u8 blkmsg[ADF_PFVF_BLKMSG_MSG_MAX_SIZE] = { 0 };
	struct adf_accel_dev *accel_dev = vf_info->accel_dev;
	adf_pf2vf_blkmsg_provider provider;
	u8 msg_size;

	provider = get_blkmsg_response_provider(type);

	if (unlikely(!provider)) {
		pr_err("QAT: No registered provider for message %d\n", type);
		*data = ADF_PF2VF_INVALID_BLOCK_TYPE;
		return -EINVAL;
	}

	if (unlikely((*provider)(accel_dev, blkmsg, vf_info->vf_compat_ver))) {
		pr_err("QAT: unknown error from provider for message %d\n", type);
		*data = ADF_PF2VF_UNSPECIFIED_ERROR;
		return -EINVAL;
	}

	msg_size = ADF_PFVF_BLKMSG_HEADER_SIZE + blkmsg[ADF_PFVF_BLKMSG_LEN_BYTE];

	if (unlikely(msg_size >= max_size)) {
		pr_err("QAT: Invalid size %d provided for message type %d\n",
		       msg_size, type);
		*data = ADF_PF2VF_PAYLOAD_TRUNCATED;
		return -EINVAL;
	}

	if (unlikely(byte >= msg_size)) {
		pr_err("QAT: Out-of-bound byte number %d (msg size %d)\n",
		       byte, msg_size);
		*data = ADF_PF2VF_INVALID_BYTE_NUM_REQ;
		return -EINVAL;
	}

	*data = data_getter(blkmsg, byte);
	return 0;
}

static struct pfvf_message handle_blkmsg_req(struct adf_accel_vf_info *vf_info,
					     struct pfvf_message req)
{
	u8 resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR;
	struct pfvf_message resp = { 0 };
	u8 resp_data = 0;
	u8 blk_type;
	u8 blk_byte;
	u8 byte_max;

	switch (req.type) {
	case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
		blk_type = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK, req.data)
			   + ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX + 1;
		blk_byte = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, req.data);
		byte_max = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
		break;
	case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
		blk_type = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK, req.data)
			   + ADF_VF2PF_SMALL_BLOCK_TYPE_MAX + 1;
		blk_byte = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, req.data);
		byte_max = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
		break;
	case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
		blk_type = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, req.data);
		blk_byte = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, req.data);
		byte_max = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
		break;
	}

	/* Is this a request for CRC or data? */
	if (FIELD_GET(ADF_VF2PF_BLOCK_CRC_REQ_MASK, req.data)) {
		dev_dbg(&GET_DEV(vf_info->accel_dev),
			"BlockMsg of type %d for CRC over %d bytes received from VF%d\n",
			blk_type, blk_byte, vf_info->vf_nr);

		if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
					       byte_max, &resp_data,
					       adf_pf2vf_blkmsg_get_crc))
			resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_CRC;
	} else {
		dev_dbg(&GET_DEV(vf_info->accel_dev),
			"BlockMsg of type %d for data byte %d received from VF%d\n",
			blk_type, blk_byte, vf_info->vf_nr);

		if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
					       byte_max, &resp_data,
					       adf_pf2vf_blkmsg_get_byte))
			resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_DATA;
	}

	resp.type = ADF_PF2VF_MSGTYPE_BLKMSG_RESP;
	resp.data = FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp_type) |
		    FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp_data);

	return resp;
}

static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr,
				struct pfvf_message msg, struct pfvf_message *resp)
{
@@ -106,6 +237,11 @@ static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr,
		vf_info->init = false;
		}
		break;
	case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
	case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
	case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
		*resp = handle_blkmsg_req(vf_info, msg);
		break;
	default:
		dev_dbg(&GET_DEV(accel_dev),
			"Unknown message from VF%d (type 0x%.4x, data: 0x%.4x)\n",
@@ -147,6 +283,7 @@ bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr)
 */
int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
{
	adf_pfvf_crc_init();
	spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);

	return 0;
+15 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2021 Intel Corporation */
#include <linux/crc8.h>
#include <linux/pci.h>
#include <linux/types.h>
#include "adf_accel_devices.h"
#include "adf_pfvf_msg.h"
#include "adf_pfvf_utils.h"

/* CRC Calculation */
DECLARE_CRC8_TABLE(pfvf_crc8_table);
#define ADF_PFVF_CRC8_POLYNOMIAL 0x97

void adf_pfvf_crc_init(void)
{
	crc8_populate_msb(pfvf_crc8_table, ADF_PFVF_CRC8_POLYNOMIAL);
}

u8 adf_pfvf_calc_blkmsg_crc(u8 const *buf, u8 buf_len)
{
	return crc8(pfvf_crc8_table, buf, buf_len, CRC8_INIT_VALUE);
}

static bool set_value_on_csr_msg(struct adf_accel_dev *accel_dev, u32 *csr_msg,
				 u32 value, const struct pfvf_field_format *fmt)
{
Loading