drivers/net/can/vxcan.c

Source file repositories/reference/linux-study-clean/drivers/net/can/vxcan.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/vxcan.c
Extension
.c
Size
8076 bytes
Lines
342
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 vxcan_netdev_ops = {
	.ndo_open	= vxcan_open,
	.ndo_stop	= vxcan_close,
	.ndo_start_xmit	= vxcan_xmit,
	.ndo_get_iflink	= vxcan_get_iflink,
	.ndo_change_mtu = vxcan_change_mtu,
};

static const struct ethtool_ops vxcan_ethtool_ops = {
	.get_ts_info = ethtool_op_get_ts_info,
};

static void vxcan_setup(struct net_device *dev)
{
	struct can_ml_priv *can_ml;

	dev->type		= ARPHRD_CAN;
	dev->mtu		= CANXL_MTU;
	dev->hard_header_len	= 0;
	dev->addr_len		= 0;
	dev->tx_queue_len	= 0;
	dev->flags		= IFF_NOARP;
	dev->netdev_ops		= &vxcan_netdev_ops;
	dev->ethtool_ops	= &vxcan_ethtool_ops;
	dev->needs_free_netdev	= true;

	can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
	can_set_ml_priv(dev, can_ml);
	vxcan_set_cap_info(dev);
}

/* forward declaration for rtnl_create_link() */
static struct rtnl_link_ops vxcan_link_ops;

static int vxcan_newlink(struct net_device *dev,
			 struct rtnl_newlink_params *params,
			 struct netlink_ext_ack *extack)
{
	struct net *peer_net = rtnl_newlink_peer_net(params);
	struct nlattr **data = params->data;
	struct nlattr **tb = params->tb;
	struct vxcan_priv *priv;
	struct net_device *peer;

	struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb;
	char ifname[IFNAMSIZ];
	unsigned char name_assign_type;
	struct ifinfomsg *ifmp = NULL;
	int err;

	/* register peer device */
	if (data && data[VXCAN_INFO_PEER]) {
		struct nlattr *nla_peer = data[VXCAN_INFO_PEER];

		ifmp = nla_data(nla_peer);
		rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
		tbp = peer_tb;
	}

	if (ifmp && tbp[IFLA_IFNAME]) {
		nla_strscpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
		name_assign_type = NET_NAME_USER;
	} else {
		snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
		name_assign_type = NET_NAME_ENUM;
	}

	peer = rtnl_create_link(peer_net, ifname, name_assign_type,
				&vxcan_link_ops, tbp, extack);
	if (IS_ERR(peer))
		return PTR_ERR(peer);

	if (ifmp && dev->ifindex)
		peer->ifindex = ifmp->ifi_index;

	err = register_netdevice(peer);
	if (err < 0) {
		free_netdev(peer);
		return err;
	}

	netif_carrier_off(peer);

	err = rtnl_configure_link(peer, ifmp, 0, NULL);
	if (err < 0)
		goto unregister_network_device;

	/* register first device */
	if (tb[IFLA_IFNAME])
		nla_strscpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);

Annotation

Implementation Notes