drivers/net/ethernet/sun/sunvnet.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sun/sunvnet.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sun/sunvnet.c
Extension
.c
Size
13367 bytes
Lines
557
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 net_device_ops vnet_ops = {
	.ndo_open		= sunvnet_open_common,
	.ndo_stop		= sunvnet_close_common,
	.ndo_set_rx_mode	= vnet_set_rx_mode,
	.ndo_set_mac_address	= sunvnet_set_mac_addr_common,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_tx_timeout		= sunvnet_tx_timeout_common,
	.ndo_start_xmit		= vnet_start_xmit,
	.ndo_select_queue	= vnet_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= vnet_poll_controller,
#endif
};

static struct vnet *vnet_new(const u64 *local_mac,
			     struct vio_dev *vdev)
{
	struct net_device *dev;
	u8 addr[ETH_ALEN];
	struct vnet *vp;
	int err, i;

	dev = alloc_etherdev_mqs(sizeof(*vp), VNET_MAX_TXQS, 1);
	if (!dev)
		return ERR_PTR(-ENOMEM);
	dev->needed_headroom = VNET_PACKET_SKIP + 8;
	dev->needed_tailroom = 8;

	for (i = 0; i < ETH_ALEN; i++)
		addr[i] = (*local_mac >> (5 - i) * 8) & 0xff;
	eth_hw_addr_set(dev, addr);

	vp = netdev_priv(dev);

	spin_lock_init(&vp->lock);
	vp->dev = dev;

	INIT_LIST_HEAD(&vp->port_list);
	for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
		INIT_HLIST_HEAD(&vp->port_hash[i]);
	INIT_LIST_HEAD(&vp->list);
	vp->local_mac = *local_mac;

	dev->netdev_ops = &vnet_ops;
	dev->ethtool_ops = &vnet_ethtool_ops;
	dev->watchdog_timeo = VNET_TX_TIMEOUT;

	dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_ALL_TSO |
			   NETIF_F_HW_CSUM | NETIF_F_SG;
	dev->features = dev->hw_features;

	/* MTU range: 68 - 65535 */
	dev->min_mtu = ETH_MIN_MTU;
	dev->max_mtu = VNET_MAX_MTU;

	SET_NETDEV_DEV(dev, &vdev->dev);

	err = register_netdev(dev);
	if (err) {
		pr_err("Cannot register net device, aborting\n");
		goto err_out_free_dev;
	}

	netdev_info(dev, "Sun LDOM vnet %pM\n", dev->dev_addr);

	list_add(&vp->list, &vnet_list);

	return vp;

err_out_free_dev:
	free_netdev(dev);

	return ERR_PTR(err);
}

static struct vnet *vnet_find_or_create(const u64 *local_mac,
					struct vio_dev *vdev)
{
	struct vnet *iter, *vp;

	mutex_lock(&vnet_list_mutex);
	vp = NULL;
	list_for_each_entry(iter, &vnet_list, list) {
		if (iter->local_mac == *local_mac) {
			vp = iter;
			break;
		}
	}
	if (!vp)
		vp = vnet_new(local_mac, vdev);

Annotation

Implementation Notes