drivers/net/wwan/rpmsg_wwan_ctrl.c

Source file repositories/reference/linux-study-clean/drivers/net/wwan/rpmsg_wwan_ctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/rpmsg_wwan_ctrl.c
Extension
.c
Size
4353 bytes
Lines
168
Domain
Driver Families
Bucket
drivers/net
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 rpmsg_wwan_dev {
	/* Lower level is a rpmsg dev, upper level is a wwan port */
	struct rpmsg_device *rpdev;
	struct wwan_port *wwan_port;
	struct rpmsg_endpoint *ept;
};

static int rpmsg_wwan_ctrl_callback(struct rpmsg_device *rpdev,
				    void *buf, int len, void *priv, u32 src)
{
	struct rpmsg_wwan_dev *rpwwan = priv;
	struct sk_buff *skb;

	skb = alloc_skb(len, GFP_ATOMIC);
	if (!skb)
		return -ENOMEM;

	skb_put_data(skb, buf, len);
	wwan_port_rx(rpwwan->wwan_port, skb);
	return 0;
}

static int rpmsg_wwan_ctrl_start(struct wwan_port *port)
{
	struct rpmsg_wwan_dev *rpwwan = wwan_port_get_drvdata(port);
	struct rpmsg_channel_info chinfo = {
		.src = rpwwan->rpdev->src,
		.dst = RPMSG_ADDR_ANY,
	};

	strscpy(chinfo.name, rpwwan->rpdev->id.name, sizeof(chinfo.name));
	rpwwan->ept = rpmsg_create_ept(rpwwan->rpdev, rpmsg_wwan_ctrl_callback,
				       rpwwan, chinfo);
	if (!rpwwan->ept)
		return -EREMOTEIO;

	return 0;
}

static void rpmsg_wwan_ctrl_stop(struct wwan_port *port)
{
	struct rpmsg_wwan_dev *rpwwan = wwan_port_get_drvdata(port);

	rpmsg_destroy_ept(rpwwan->ept);
	rpwwan->ept = NULL;
}

static int rpmsg_wwan_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
{
	struct rpmsg_wwan_dev *rpwwan = wwan_port_get_drvdata(port);
	int ret;

	ret = rpmsg_trysend(rpwwan->ept, skb->data, skb->len);
	if (ret)
		return ret;

	consume_skb(skb);
	return 0;
}

static int rpmsg_wwan_ctrl_tx_blocking(struct wwan_port *port, struct sk_buff *skb)
{
	struct rpmsg_wwan_dev *rpwwan = wwan_port_get_drvdata(port);
	int ret;

	ret = rpmsg_send(rpwwan->ept, skb->data, skb->len);
	if (ret)
		return ret;

	consume_skb(skb);
	return 0;
}

static __poll_t rpmsg_wwan_ctrl_tx_poll(struct wwan_port *port,
					struct file *filp, poll_table *wait)
{
	struct rpmsg_wwan_dev *rpwwan = wwan_port_get_drvdata(port);

	return rpmsg_poll(rpwwan->ept, filp, wait);
}

static const struct wwan_port_ops rpmsg_wwan_pops = {
	.start = rpmsg_wwan_ctrl_start,
	.stop = rpmsg_wwan_ctrl_stop,
	.tx = rpmsg_wwan_ctrl_tx,
	.tx_blocking = rpmsg_wwan_ctrl_tx_blocking,
	.tx_poll = rpmsg_wwan_ctrl_tx_poll,
};

static struct device *rpmsg_wwan_find_parent(struct device *dev)

Annotation

Implementation Notes