drivers/staging/most/net/net.c

Source file repositories/reference/linux-study-clean/drivers/staging/most/net/net.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/most/net/net.c
Extension
.c
Size
12636 bytes
Lines
581
Domain
Driver Families
Bucket
drivers/staging
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 net_device_ops most_nd_ops = {
	.ndo_open = most_nd_open,
	.ndo_stop = most_nd_stop,
	.ndo_start_xmit = most_nd_start_xmit,
	.ndo_set_mac_address = most_nd_set_mac_address,
};

static void most_nd_setup(struct net_device *dev)
{
	ether_setup(dev);
	dev->netdev_ops = &most_nd_ops;
}

static struct net_dev_context *get_net_dev(struct most_interface *iface)
{
	struct net_dev_context *nd;

	list_for_each_entry(nd, &net_devices, list)
		if (nd->iface == iface)
			return nd;
	return NULL;
}

static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
{
	struct net_dev_context *nd;
	unsigned long flags;

	spin_lock_irqsave(&list_lock, flags);
	nd = get_net_dev(iface);
	if (nd && nd->rx.linked && nd->tx.linked)
		dev_hold(nd->dev);
	else
		nd = NULL;
	spin_unlock_irqrestore(&list_lock, flags);
	return nd;
}

static int comp_probe_channel(struct most_interface *iface, int channel_idx,
			      struct most_channel_config *ccfg, char *name,
			      char *args)
{
	struct net_dev_context *nd;
	struct net_dev_channel *ch;
	struct net_device *dev;
	unsigned long flags;
	int ret = 0;

	if (!iface)
		return -EINVAL;

	if (ccfg->data_type != MOST_CH_ASYNC)
		return -EINVAL;

	mutex_lock(&probe_disc_mt);
	nd = get_net_dev(iface);
	if (!nd) {
		dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
				   NET_NAME_UNKNOWN, most_nd_setup);
		if (!dev) {
			ret = -ENOMEM;
			goto unlock;
		}

		nd = netdev_priv(dev);
		nd->iface = iface;
		nd->dev = dev;

		spin_lock_irqsave(&list_lock, flags);
		list_add(&nd->list, &net_devices);
		spin_unlock_irqrestore(&list_lock, flags);

		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
	} else {
		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
		if (ch->linked) {
			pr_err("direction is allocated\n");
			ret = -EINVAL;
			goto unlock;
		}

		if (register_netdev(nd->dev)) {
			pr_err("register_netdev() failed\n");
			ret = -EINVAL;
			goto unlock;
		}
	}
	ch->ch_id = channel_idx;
	ch->linked = true;

Annotation

Implementation Notes