drivers/net/ethernet/mediatek/mtk_eth_soc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mediatek/mtk_eth_soc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mediatek/mtk_eth_soc.c
Extension
.c
Size
144003 bytes
Lines
5676
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 mtk_netdev_ops = {
	.ndo_uninit		= mtk_uninit,
	.ndo_open		= mtk_open,
	.ndo_stop		= mtk_stop,
	.ndo_start_xmit		= mtk_start_xmit,
	.ndo_set_mac_address	= mtk_set_mac_address,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= mtk_do_ioctl,
	.ndo_change_mtu		= mtk_change_mtu,
	.ndo_tx_timeout		= mtk_tx_timeout,
	.ndo_get_stats64        = mtk_get_stats64,
	.ndo_fix_features	= mtk_fix_features,
	.ndo_set_features	= mtk_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= mtk_poll_controller,
#endif
	.ndo_setup_tc		= mtk_eth_setup_tc,
	.ndo_bpf		= mtk_xdp,
	.ndo_xdp_xmit		= mtk_xdp_xmit,
	.ndo_select_queue	= mtk_select_queue,
};

static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
	const struct phylink_mac_ops *mac_ops = &mtk_phylink_ops;
	const __be32 *_id = of_get_property(np, "reg", NULL);
	phy_interface_t phy_mode;
	struct phylink *phylink;
	struct mtk_mac *mac;
	int id, err;
	int txqs = 1;
	u32 val;

	if (!_id) {
		dev_err(eth->dev, "missing mac id\n");
		return -EINVAL;
	}

	id = be32_to_cpup(_id);
	if (id >= MTK_MAX_DEVS) {
		dev_err(eth->dev, "%d is not a valid mac id\n", id);
		return -EINVAL;
	}

	if (eth->netdev[id]) {
		dev_err(eth->dev, "duplicate mac id found: %d\n", id);
		return -EINVAL;
	}

	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
		txqs = MTK_QDMA_NUM_QUEUES;

	eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1);
	if (!eth->netdev[id]) {
		dev_err(eth->dev, "alloc_etherdev failed\n");
		return -ENOMEM;
	}
	mac = netdev_priv(eth->netdev[id]);
	eth->mac[id] = mac;
	mac->id = id;
	mac->hw = eth;
	mac->of_node = np;

	err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
	if (err == -EPROBE_DEFER)
		return err;

	if (err) {
		/* If the mac address is invalid, use random mac address */
		eth_hw_addr_random(eth->netdev[id]);
		dev_err(eth->dev, "generated random MAC address %pM\n",
			eth->netdev[id]->dev_addr);
	}

	memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
	mac->hwlro_ip_cnt = 0;

	mac->hw_stats = devm_kzalloc(eth->dev,
				     sizeof(*mac->hw_stats),
				     GFP_KERNEL);
	if (!mac->hw_stats) {
		dev_err(eth->dev, "failed to allocate counter memory\n");
		err = -ENOMEM;
		goto free_netdev;
	}
	spin_lock_init(&mac->hw_stats->stats_lock);
	u64_stats_init(&mac->hw_stats->syncp);

	if (mtk_is_netsys_v3_or_greater(eth))
		mac->hw_stats->reg_offset = id * 0x80;

Annotation

Implementation Notes