drivers/net/thunderbolt/main.c

Source file repositories/reference/linux-study-clean/drivers/net/thunderbolt/main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/thunderbolt/main.c
Extension
.c
Size
39898 bytes
Lines
1524
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 tbnet_netdev_ops = {
	.ndo_open = tbnet_open,
	.ndo_stop = tbnet_stop,
	.ndo_start_xmit = tbnet_start_xmit,
	.ndo_set_mac_address = eth_mac_addr,
	.ndo_get_stats64 = tbnet_get_stats64,
};

static int tbnet_get_link_ksettings(struct net_device *dev,
				    struct ethtool_link_ksettings *cmd)
{
	const struct tbnet *net = netdev_priv(dev);
	const struct tb_xdomain *xd = net->xd;
	int speed;

	ethtool_link_ksettings_zero_link_mode(cmd, supported);
	ethtool_link_ksettings_zero_link_mode(cmd, advertising);

	/* Figure out the current link speed and width */
	switch (xd->link_speed) {
	case 40:
		speed = SPEED_80000;
		break;

	case 20:
		if (xd->link_width == 2)
			speed = SPEED_40000;
		else
			speed = SPEED_20000;
		break;

	case 10:
		if (xd->link_width == 2) {
			speed = SPEED_20000;
			break;
		}
		fallthrough;

	default:
		speed = SPEED_10000;
		break;
	}

	cmd->base.speed = speed;
	cmd->base.duplex = DUPLEX_FULL;
	cmd->base.autoneg = AUTONEG_DISABLE;
	cmd->base.port = PORT_OTHER;

	return 0;
}

static const struct ethtool_ops tbnet_ethtool_ops = {
	.get_link_ksettings = tbnet_get_link_ksettings,
};

static void tbnet_generate_mac(struct net_device *dev)
{
	const struct tbnet *net = netdev_priv(dev);
	const struct tb_xdomain *xd = net->xd;
	u8 addr[ETH_ALEN];
	u8 phy_port;
	u32 hash;

	phy_port = tb_phy_port_from_link(TBNET_L0_PORT_NUM(xd->route));

	/* Unicast and locally administered MAC */
	addr[0] = phy_port << 4 | 0x02;
	hash = jhash2((u32 *)xd->local_uuid, 4, 0);
	memcpy(addr + 1, &hash, sizeof(hash));
	hash = jhash2((u32 *)xd->local_uuid, 4, hash);
	addr[5] = hash & 0xff;
	eth_hw_addr_set(dev, addr);

	/* Allow changing it if needed */
	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
}

static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
{
	struct tb_xdomain *xd = tb_service_parent(svc);
	struct net_device *dev;
	struct tbnet *net;
	int ret;

	dev = alloc_etherdev(sizeof(*net));
	if (!dev)
		return -ENOMEM;

	SET_NETDEV_DEV(dev, &svc->dev);

Annotation

Implementation Notes