drivers/crypto/intel/qat/qat_common/adf_gen2_pfvf.c

Source file repositories/reference/linux-study-clean/drivers/crypto/intel/qat/qat_common/adf_gen2_pfvf.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/intel/qat/qat_common/adf_gen2_pfvf.c
Extension
.c
Size
12201 bytes
Lines
402
Domain
Driver Families
Bucket
drivers/crypto
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pfvf_gen2_params {
	u32 pfvf_offset;
	struct mutex *csr_lock; /* lock preventing concurrent access of CSR */
	enum gen2_csr_pos local_offset;
	enum gen2_csr_pos remote_offset;
	bool (*is_notification_message)(u8 msg_type);
	u8 compat_ver;
};

static int adf_gen2_pfvf_send(struct adf_accel_dev *accel_dev,
			      struct pfvf_message msg,
			      struct pfvf_gen2_params *params)
{
	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
	enum gen2_csr_pos remote_offset = params->remote_offset;
	enum gen2_csr_pos local_offset = params->local_offset;
	unsigned int retries = ADF_PFVF_MSG_MAX_RETRIES;
	struct mutex *lock = params->csr_lock;
	u32 pfvf_offset = params->pfvf_offset;
	u32 int_bit;
	u32 csr_val;
	u32 csr_msg;
	int ret;

	/* Gen2 messages, both PF->VF and VF->PF, are all 16 bits long. This
	 * allows us to build and read messages as if they where all 0 based.
	 * However, send and receive are in a single shared 32 bits register,
	 * so we need to shift and/or mask the message half before decoding
	 * it and after encoding it. Which one to shift depends on the
	 * direction.
	 */

	int_bit = gen2_csr_get_int_bit(local_offset);

	csr_msg = adf_pfvf_csr_msg_of(accel_dev, msg, &csr_gen2_fmt);
	if (unlikely(!csr_msg))
		return -EINVAL;

	/* Prepare for CSR format, shifting the wire message in place and
	 * setting the in use pattern
	 */
	csr_msg = gen2_csr_msg_to_position(csr_msg, local_offset);
	gen2_csr_set_in_use(&csr_msg, remote_offset);

	mutex_lock(lock);

start:
	/* Check if the PFVF CSR is in use by remote function */
	csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
	if (gen2_csr_is_in_use(csr_val, local_offset)) {
		dev_dbg(&GET_DEV(accel_dev),
			"PFVF CSR in use by remote function\n");
		goto retry;
	}

	/* Attempt to get ownership of the PFVF CSR */
	ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_msg | int_bit);

	/* Wait for confirmation from remote func it received the message */
	ret = read_poll_timeout(ADF_CSR_RD, csr_val, !(csr_val & int_bit),
				ADF_PFVF_MSG_ACK_DELAY_US,
				ADF_PFVF_MSG_ACK_MAX_DELAY_US,
				true, pmisc_addr, pfvf_offset);
	if (unlikely(ret < 0)) {
		dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
		csr_val &= ~int_bit;
	}

	/* For fire-and-forget notifications, the receiver does not clear
	 * the in-use pattern. This is used to detect collisions.
	 */
	if (params->is_notification_message(msg.type) && csr_val != csr_msg) {
		/* Collision must have overwritten the message */
		dev_err(&GET_DEV(accel_dev),
			"Collision on notification - PFVF CSR overwritten by remote function\n");
		goto retry;
	}

	/* If the far side did not clear the in-use pattern it is either
	 * 1) Notification - message left intact to detect collision
	 * 2) Older protocol (compatibility version < 3) on the far side
	 *    where the sender is responsible for clearing the in-use
	 *    pattern after the received has acknowledged receipt.
	 * In either case, clear the in-use pattern now.
	 */
	if (gen2_csr_is_in_use(csr_val, remote_offset)) {
		gen2_csr_clear_in_use(&csr_val, remote_offset);
		ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val);
	}

Annotation

Implementation Notes