drivers/fwctl/pds/main.c

Source file repositories/reference/linux-study-clean/drivers/fwctl/pds/main.c

File Facts

System
Linux kernel
Corpus path
drivers/fwctl/pds/main.c
Extension
.c
Size
14443 bytes
Lines
539
Domain
Driver Families
Bucket
drivers/fwctl
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

struct pdsfc_uctx {
	struct fwctl_uctx uctx;
	u32 uctx_caps;
};

struct pdsfc_rpc_endpoint_info {
	u32 endpoint;
	dma_addr_t operations_pa;
	struct pds_fwctl_query_data *operations;
	struct mutex lock;	/* lock for endpoint info management */
};

struct pdsfc_dev {
	struct fwctl_device fwctl;
	struct pds_auxiliary_dev *padev;
	u32 caps;
	struct pds_fwctl_ident ident;
	dma_addr_t endpoints_pa;
	struct pds_fwctl_query_data *endpoints;
	struct pdsfc_rpc_endpoint_info *endpoint_info;
};

static int pdsfc_open_uctx(struct fwctl_uctx *uctx)
{
	struct pdsfc_dev *pdsfc = container_of(uctx->fwctl, struct pdsfc_dev, fwctl);
	struct pdsfc_uctx *pdsfc_uctx = container_of(uctx, struct pdsfc_uctx, uctx);

	pdsfc_uctx->uctx_caps = pdsfc->caps;

	return 0;
}

static void pdsfc_close_uctx(struct fwctl_uctx *uctx)
{
}

static void *pdsfc_info(struct fwctl_uctx *uctx, size_t *length)
{
	struct pdsfc_uctx *pdsfc_uctx = container_of(uctx, struct pdsfc_uctx, uctx);
	struct fwctl_info_pds *info;

	info = kzalloc_obj(*info);
	if (!info)
		return ERR_PTR(-ENOMEM);

	info->uctx_caps = pdsfc_uctx->uctx_caps;

	return info;
}

static int pdsfc_identify(struct pdsfc_dev *pdsfc)
{
	struct device *dev = &pdsfc->fwctl.dev;
	union pds_core_adminq_comp comp = {0};
	union pds_core_adminq_cmd cmd;
	struct pds_fwctl_ident *ident;
	dma_addr_t ident_pa;
	int err;

	ident = dma_alloc_coherent(dev->parent, sizeof(*ident), &ident_pa, GFP_KERNEL);
	if (!ident) {
		dev_err(dev, "Failed to map ident buffer\n");
		return -ENOMEM;
	}

	cmd = (union pds_core_adminq_cmd) {
		.fwctl_ident = {
			.opcode = PDS_FWCTL_CMD_IDENT,
			.version = 0,
			.len = cpu_to_le32(sizeof(*ident)),
			.ident_pa = cpu_to_le64(ident_pa),
		}
	};

	err = pds_client_adminq_cmd(pdsfc->padev, &cmd, sizeof(cmd), &comp, 0);
	if (err)
		dev_err(dev, "Failed to send adminq cmd opcode: %u err: %d\n",
			cmd.fwctl_ident.opcode, err);
	else
		pdsfc->ident = *ident;

	dma_free_coherent(dev->parent, sizeof(*ident), ident, ident_pa);

	return err;
}

static void pdsfc_free_endpoints(struct pdsfc_dev *pdsfc)
{
	struct device *dev = &pdsfc->fwctl.dev;
	u32 num_endpoints;

Annotation

Implementation Notes