drivers/net/ethernet/mediatek/mtk_star_emac.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mediatek/mtk_star_emac.c
Extension
.c
Size
47481 bytes
Lines
1762
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_star_netdev_ops = {
	.ndo_open		= mtk_star_netdev_open,
	.ndo_stop		= mtk_star_netdev_stop,
	.ndo_start_xmit		= mtk_star_netdev_start_xmit,
	.ndo_get_stats64	= mtk_star_netdev_get_stats64,
	.ndo_set_rx_mode	= mtk_star_set_rx_mode,
	.ndo_eth_ioctl		= mtk_star_netdev_ioctl,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

static void mtk_star_get_drvinfo(struct net_device *dev,
				 struct ethtool_drvinfo *info)
{
	strscpy(info->driver, MTK_STAR_DRVNAME, sizeof(info->driver));
}

/* TODO Add ethtool stats. */
static const struct ethtool_ops mtk_star_ethtool_ops = {
	.get_drvinfo		= mtk_star_get_drvinfo,
	.get_link		= ethtool_op_get_link,
	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
};

static int mtk_star_rx(struct mtk_star_priv *priv, int budget)
{
	struct mtk_star_ring *ring = &priv->rx_ring;
	struct device *dev = mtk_star_get_dev(priv);
	struct mtk_star_ring_desc_data desc_data;
	struct net_device *ndev = priv->ndev;
	struct sk_buff *curr_skb, *new_skb;
	dma_addr_t new_dma_addr;
	int ret, count = 0;

	while (count < budget) {
		ret = mtk_star_ring_pop_tail(ring, &desc_data);
		if (ret)
			return -1;

		curr_skb = desc_data.skb;

		if ((desc_data.flags & MTK_STAR_DESC_BIT_RX_CRCE) ||
		    (desc_data.flags & MTK_STAR_DESC_BIT_RX_OSIZE)) {
			/* Error packet -> drop and reuse skb. */
			new_skb = curr_skb;
			goto push_new_skb;
		}

		/* Prepare new skb before receiving the current one.
		 * Reuse the current skb if we fail at any point.
		 */
		new_skb = mtk_star_alloc_skb(ndev);
		if (!new_skb) {
			ndev->stats.rx_dropped++;
			new_skb = curr_skb;
			goto push_new_skb;
		}

		new_dma_addr = mtk_star_dma_map_rx(priv, new_skb);
		if (dma_mapping_error(dev, new_dma_addr)) {
			ndev->stats.rx_dropped++;
			dev_kfree_skb(new_skb);
			new_skb = curr_skb;
			netdev_err(ndev, "DMA mapping error of RX descriptor\n");
			goto push_new_skb;
		}

		/* We can't fail anymore at this point:
		 * it's safe to unmap the skb.
		 */
		mtk_star_dma_unmap_rx(priv, &desc_data);

		skb_put(desc_data.skb, desc_data.len);
		desc_data.skb->ip_summed = CHECKSUM_NONE;
		desc_data.skb->protocol = eth_type_trans(desc_data.skb, ndev);
		desc_data.skb->dev = ndev;
		netif_receive_skb(desc_data.skb);

		/* update dma_addr for new skb */
		desc_data.dma_addr = new_dma_addr;

push_new_skb:

		count++;

		desc_data.len = skb_tailroom(new_skb);
		desc_data.skb = new_skb;
		mtk_star_ring_push_head_rx(ring, &desc_data);
	}

Annotation

Implementation Notes