drivers/net/wwan/wwan_core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/wwan_core.c
Extension
.c
Size
33851 bytes
Lines
1442
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations wwan_port_fops = {
	.owner = THIS_MODULE,
	.open = wwan_port_fops_open,
	.release = wwan_port_fops_release,
	.read = wwan_port_fops_read,
	.write = wwan_port_fops_write,
	.poll = wwan_port_fops_poll,
	.unlocked_ioctl = wwan_port_fops_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = compat_ptr_ioctl,
#endif
	.llseek = noop_llseek,
};

static int wwan_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
			      struct netlink_ext_ack *extack)
{
	if (!data)
		return -EINVAL;

	if (!tb[IFLA_PARENT_DEV_NAME])
		return -EINVAL;

	if (!data[IFLA_WWAN_LINK_ID])
		return -EINVAL;

	return 0;
}

static const struct device_type wwan_type = { .name = "wwan" };

static struct net_device *wwan_rtnl_alloc(struct nlattr *tb[],
					  const char *ifname,
					  unsigned char name_assign_type,
					  unsigned int num_tx_queues,
					  unsigned int num_rx_queues)
{
	const char *devname = nla_data(tb[IFLA_PARENT_DEV_NAME]);
	struct wwan_device *wwandev = wwan_dev_get_by_name(devname);
	struct net_device *dev;
	unsigned int priv_size;

	if (IS_ERR(wwandev))
		return ERR_CAST(wwandev);

	/* only supported if ops were registered (not just ports) */
	if (!wwandev->ops) {
		dev = ERR_PTR(-EOPNOTSUPP);
		goto out;
	}

	priv_size = sizeof(struct wwan_netdev_priv) + wwandev->ops->priv_size;
	dev = alloc_netdev_mqs(priv_size, ifname, name_assign_type,
			       wwandev->ops->setup, num_tx_queues, num_rx_queues);

	if (dev) {
		SET_NETDEV_DEV(dev, &wwandev->dev);
		SET_NETDEV_DEVTYPE(dev, &wwan_type);
	}

out:
	/* release the reference */
	put_device(&wwandev->dev);
	return dev;
}

static int wwan_rtnl_newlink(struct net_device *dev,
			     struct rtnl_newlink_params *params,
			     struct netlink_ext_ack *extack)
{
	struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent);
	struct wwan_netdev_priv *priv = netdev_priv(dev);
	struct nlattr **data = params->data;
	u32 link_id;
	int ret;

	link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]);

	if (IS_ERR(wwandev))
		return PTR_ERR(wwandev);

	/* shouldn't have a netdev (left) with us as parent so WARN */
	if (WARN_ON(!wwandev->ops)) {
		ret = -EOPNOTSUPP;
		goto out;
	}

	priv->link_id = link_id;
	if (wwandev->ops->newlink)
		ret = wwandev->ops->newlink(wwandev->ops_ctxt, dev,

Annotation

Implementation Notes