drivers/net/ethernet/sun/ldmvsw.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sun/ldmvsw.c
Extension
.c
Size
11477 bytes
Lines
479
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 vsw_ops = {
	.ndo_open		= ldmvsw_open,
	.ndo_stop		= sunvnet_close_common,
	.ndo_set_rx_mode	= vsw_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		= vsw_start_xmit,
	.ndo_select_queue	= vsw_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller    = vsw_poll_controller,
#endif
};

static const char *local_mac_prop = "local-mac-address";
static const char *cfg_handle_prop = "cfg-handle";

static struct vnet *vsw_get_vnet(struct mdesc_handle *hp,
				 u64 port_node,
				 u64 *handle)
{
	struct vnet *vp;
	struct vnet *iter;
	const u64 *local_mac = NULL;
	const u64 *cfghandle = NULL;
	u64 a;

	/* Get the parent virtual-network-switch macaddr and cfghandle */
	mdesc_for_each_arc(a, hp, port_node, MDESC_ARC_TYPE_BACK) {
		u64 target = mdesc_arc_target(hp, a);
		const char *name;

		name = mdesc_get_property(hp, target, "name", NULL);
		if (!name || strcmp(name, "virtual-network-switch"))
			continue;

		local_mac = mdesc_get_property(hp, target,
					       local_mac_prop, NULL);
		cfghandle = mdesc_get_property(hp, target,
					       cfg_handle_prop, NULL);
		break;
	}
	if (!local_mac || !cfghandle)
		return ERR_PTR(-ENODEV);

	/* find or create associated vnet */
	vp = NULL;
	mutex_lock(&vnet_list_mutex);
	list_for_each_entry(iter, &vnet_list, list) {
		if (iter->local_mac == *local_mac) {
			vp = iter;
			break;
		}
	}

	if (!vp) {
		vp = kzalloc_obj(*vp);
		if (unlikely(!vp)) {
			mutex_unlock(&vnet_list_mutex);
			return ERR_PTR(-ENOMEM);
		}

		spin_lock_init(&vp->lock);
		INIT_LIST_HEAD(&vp->port_list);
		INIT_LIST_HEAD(&vp->list);
		vp->local_mac = *local_mac;
		list_add(&vp->list, &vnet_list);
	}

	mutex_unlock(&vnet_list_mutex);

	*handle = (u64)*cfghandle;

	return vp;
}

static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
					   struct vio_dev *vdev,
					   u64 handle,
					   u64 port_id)
{
	struct net_device *dev;
	struct vnet_port *port;

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

Annotation

Implementation Notes