drivers/media/pci/intel/ipu6/ipu6-cpd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/intel/ipu6/ipu6-cpd.c
Extension
.c
Size
10150 bytes
Lines
363
Domain
Driver Families
Bucket
drivers/media
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

if (id < 0 || id > MAX_COMPONENT_ID) {
			dev_err(&isp->pdev->dev, "Invalid CPD component id\n");
			return -EINVAL;
		}

		ver = ipu6_cpd_metadata_cmpnt_version(isp, metadata,
						      metadata_size, i);
		if (ver < 0 || ver > MAX_COMPONENT_VERSION) {
			dev_err(&isp->pdev->dev,
				"Invalid CPD component version\n");
			return -EINVAL;
		}

		*p = FIELD_PREP(PKG_DIR_SIZE_MASK, dir_ent->len) |
			FIELD_PREP(PKG_DIR_TYPE_MASK, id) |
			FIELD_PREP(PKG_DIR_VERSION_MASK, ver);
	}

	return 0;
}

int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
{
	dma_addr_t dma_addr_src = sg_dma_address(adev->fw_sgt.sgl);
	const struct ipu6_cpd_ent *ent, *man_ent, *met_ent;
	struct ipu6_device *isp = adev->isp;
	unsigned int man_sz, met_sz;
	void *pkg_dir_pos;
	int ret;

	man_ent = ipu6_cpd_get_manifest(src);
	man_sz = man_ent->len;

	met_ent = ipu6_cpd_get_metadata(src);
	met_sz = met_ent->len;

	adev->pkg_dir_size = PKG_DIR_SIZE + man_sz + met_sz;
	adev->pkg_dir = ipu6_dma_alloc(adev, adev->pkg_dir_size,
				       &adev->pkg_dir_dma_addr, GFP_KERNEL, 0);
	if (!adev->pkg_dir)
		return -ENOMEM;

	/*
	 * pkg_dir entry/header:
	 * qword | 63:56 | 55   | 54:48 | 47:32 | 31:24 | 23:0
	 * N         Address/Offset/"_IUPKDR_"
	 * N + 1 | rsvd  | rsvd | type  | ver   | rsvd  | size
	 *
	 * We can ignore other fields that size in N + 1 qword as they
	 * are 0 anyway. Just setting size for now.
	 */

	ent = ipu6_cpd_get_moduledata(src);

	ret = ipu6_cpd_parse_module_data(isp, src + ent->offset,
					 ent->len, dma_addr_src + ent->offset,
					 adev->pkg_dir, src + met_ent->offset,
					 met_ent->len);
	if (ret) {
		dev_err(&isp->pdev->dev, "Failed to parse module data\n");
		ipu6_dma_free(adev, adev->pkg_dir_size,
			      adev->pkg_dir, adev->pkg_dir_dma_addr, 0);
		return ret;
	}

	/* Copy manifest after pkg_dir */
	pkg_dir_pos = adev->pkg_dir + PKG_DIR_ENT_LEN * MAX_PKG_DIR_ENT_CNT;
	memcpy(pkg_dir_pos, src + man_ent->offset, man_sz);

	/* Copy metadata after manifest */
	pkg_dir_pos += man_sz;
	memcpy(pkg_dir_pos, src + met_ent->offset, met_sz);

	ipu6_dma_sync_single(adev, adev->pkg_dir_dma_addr,
			     adev->pkg_dir_size);

	return 0;
}
EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, "INTEL_IPU6");

void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev)
{
	ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir,
		      adev->pkg_dir_dma_addr, 0);
}
EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, "INTEL_IPU6");

static int ipu6_cpd_validate_cpd(struct ipu6_device *isp, const void *cpd,
				 unsigned long cpd_size,
				 unsigned long data_size)

Annotation

Implementation Notes