drivers/rpmsg/mtk_rpmsg.c

Source file repositories/reference/linux-study-clean/drivers/rpmsg/mtk_rpmsg.c

File Facts

System
Linux kernel
Corpus path
drivers/rpmsg/mtk_rpmsg.c
Extension
.c
Size
10702 bytes
Lines
411
Domain
Driver Families
Bucket
drivers/rpmsg
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 mtk_rpmsg_rproc_subdev {
	struct platform_device *pdev;
	struct mtk_rpmsg_info *info;
	struct rpmsg_endpoint *ns_ept;
	struct rproc_subdev subdev;

	struct work_struct register_work;
	struct list_head channels;
	struct mutex channels_lock;
};

#define to_mtk_subdev(d) container_of(d, struct mtk_rpmsg_rproc_subdev, subdev)

struct mtk_rpmsg_channel_info {
	struct rpmsg_channel_info info;
	bool registered;
	struct list_head list;
};

/**
 * struct rpmsg_ns_msg - dynamic name service announcement message
 * @name: name of remote service that is published
 * @addr: address of remote service that is published
 *
 * This message is sent across to publish a new service. When we receive these
 * messages, an appropriate rpmsg channel (i.e device) is created. In turn, the
 * ->probe() handler of the appropriate rpmsg driver will be invoked
 *  (if/as-soon-as one is registered).
 */
struct rpmsg_ns_msg {
	char name[RPMSG_NAME_SIZE];
	u32 addr;
} __packed;

struct mtk_rpmsg_device {
	struct rpmsg_device rpdev;
	struct mtk_rpmsg_rproc_subdev *mtk_subdev;
};

struct mtk_rpmsg_endpoint {
	struct rpmsg_endpoint ept;
	struct mtk_rpmsg_rproc_subdev *mtk_subdev;
};

#define to_mtk_rpmsg_device(r) container_of(r, struct mtk_rpmsg_device, rpdev)
#define to_mtk_rpmsg_endpoint(r) container_of(r, struct mtk_rpmsg_endpoint, ept)

static const struct rpmsg_endpoint_ops mtk_rpmsg_endpoint_ops;

static void __mtk_ept_release(struct kref *kref)
{
	struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint,
						  refcount);
	kfree(to_mtk_rpmsg_endpoint(ept));
}

static void mtk_rpmsg_ipi_handler(void *data, unsigned int len, void *priv)
{
	struct mtk_rpmsg_endpoint *mept = priv;
	struct rpmsg_endpoint *ept = &mept->ept;
	int ret;

	ret = (*ept->cb)(ept->rpdev, data, len, ept->priv, ept->addr);
	if (ret)
		dev_warn(&ept->rpdev->dev, "rpmsg handler return error = %d",
			 ret);
}

static struct rpmsg_endpoint *
__mtk_create_ept(struct mtk_rpmsg_rproc_subdev *mtk_subdev,
		 struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv,
		 u32 id)
{
	struct mtk_rpmsg_endpoint *mept;
	struct rpmsg_endpoint *ept;
	struct platform_device *pdev = mtk_subdev->pdev;
	int ret;

	mept = kzalloc_obj(*mept);
	if (!mept)
		return NULL;
	mept->mtk_subdev = mtk_subdev;

	ept = &mept->ept;
	kref_init(&ept->refcount);

	ept->rpdev = rpdev;
	ept->cb = cb;
	ept->priv = priv;
	ept->ops = &mtk_rpmsg_endpoint_ops;

Annotation

Implementation Notes