drivers/media/pci/intel/ipu6/ipu6-fw-isys.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
Extension
.c
Size
14725 bytes
Lines
488
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source 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

if (ret == -EIO) {
			dev_err(dev, "Proxy respond with unexpected id\n");
			break;
		}
		timeout--;
	} while (ret && timeout);

	if (!timeout)
		dev_err(dev, "Proxy response timed out\n");

	return ret;
}

int ipu6_fw_isys_complex_cmd(struct ipu6_isys *isys,
			     const unsigned int stream_handle,
			     void *cpu_mapped_buf,
			     dma_addr_t dma_mapped_buf,
			     size_t size, u16 send_type)
{
	struct ipu6_fw_com_context *ctx = isys->fwcom;
	struct device *dev = &isys->adev->auxdev.dev;
	struct ipu6_fw_send_queue_token *token;

	if (send_type >= N_IPU6_FW_ISYS_SEND_TYPE)
		return -EINVAL;

	dev_dbg(dev, "send_token: %s\n", send_msg_types[send_type]);

	/*
	 * Time to flush cache in case we have some payload. Not all messages
	 * have that
	 */
	if (cpu_mapped_buf)
		clflush_cache_range(cpu_mapped_buf, size);

	token = ipu6_send_get_token(ctx,
				    stream_handle + IPU6_BASE_MSG_SEND_QUEUES);
	if (!token)
		return -EBUSY;

	token->payload = dma_mapped_buf;
	token->buf_handle = (unsigned long)cpu_mapped_buf;
	token->send_type = send_type;

	ipu6_send_put_token(ctx, stream_handle + IPU6_BASE_MSG_SEND_QUEUES);

	return 0;
}

int ipu6_fw_isys_simple_cmd(struct ipu6_isys *isys,
			    const unsigned int stream_handle, u16 send_type)
{
	return ipu6_fw_isys_complex_cmd(isys, stream_handle, NULL, 0, 0,
					send_type);
}

int ipu6_fw_isys_close(struct ipu6_isys *isys)
{
	struct device *dev = &isys->adev->auxdev.dev;
	int retry = IPU6_ISYS_CLOSE_RETRY;
	unsigned long flags;
	void *fwcom;
	int ret;

	/*
	 * Stop the isys fw. Actual close takes
	 * some time as the FW must stop its actions including code fetch
	 * to SP icache.
	 * spinlock to wait the interrupt handler to be finished
	 */
	spin_lock_irqsave(&isys->power_lock, flags);
	ret = ipu6_fw_com_close(isys->fwcom);
	fwcom = isys->fwcom;
	isys->fwcom = NULL;
	spin_unlock_irqrestore(&isys->power_lock, flags);
	if (ret)
		dev_err(dev, "Device close failure: %d\n", ret);

	/* release probably fails if the close failed. Let's try still */
	do {
		usleep_range(400, 500);
		ret = ipu6_fw_com_release(fwcom, 0);
		retry--;
	} while (ret && retry);

	if (ret) {
		dev_err(dev, "Device release time out %d\n", ret);
		spin_lock_irqsave(&isys->power_lock, flags);
		isys->fwcom = fwcom;
		spin_unlock_irqrestore(&isys->power_lock, flags);

Annotation

Implementation Notes