drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
Extension
.c
Size
18438 bytes
Lines
718
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

FIELD_GET(HBG_RX_DESC_W4_DROP_B, desc->word4))) {
		priv->stats.rx_desc_drop++;
		return false;
	}

	if (unlikely(FIELD_GET(HBG_RX_DESC_W4_L2_ERR_B, desc->word4))) {
		priv->stats.rx_desc_l2_err_cnt++;
		return false;
	}

	if (unlikely(!hbg_rx_check_l3l4_error(priv, desc, skb))) {
		priv->stats.rx_desc_l3l4_err_cnt++;
		return false;
	}

	hbg_update_rx_protocol_stats(priv, desc);
	return true;
}

static int hbg_rx_fill_one_buffer(struct hbg_priv *priv)
{
	struct hbg_ring *ring = &priv->rx_ring;
	struct hbg_buffer *buffer;
	int ret;

	if (hbg_queue_is_full(ring->ntc, ring->ntu, ring) ||
	    hbg_fifo_is_full(priv, ring->dir))
		return 0;

	buffer = &ring->queue[ring->ntu];
	ret = hbg_buffer_alloc_page(buffer);
	if (unlikely(ret))
		return ret;

	memset(buffer->page_addr, 0, HBG_PACKET_HEAD_SIZE);
	dma_sync_single_for_device(&priv->pdev->dev, buffer->page_dma,
				   HBG_PACKET_HEAD_SIZE, DMA_TO_DEVICE);

	hbg_hw_fill_buffer(priv, buffer->page_dma);
	hbg_queue_move_next(ntu, ring);
	return 0;
}

static int hbg_rx_fill_buffers(struct hbg_priv *priv)
{
	u32 remained = hbg_hw_get_fifo_used_num(priv, HBG_DIR_RX);
	u32 max_count = priv->dev_specs.rx_fifo_num;
	u32 refill_count;
	int ret;

	if (unlikely(remained >= max_count))
		return 0;

	refill_count = max_count - remained;
	while (refill_count--) {
		ret = hbg_rx_fill_one_buffer(priv);
		if (unlikely(ret))
			break;
	}

	return ret;
}

static bool hbg_sync_data_from_hw(struct hbg_priv *priv,
				  struct hbg_buffer *buffer)
{
	struct hbg_rx_desc *rx_desc;

	dma_sync_single_for_cpu(&priv->pdev->dev, buffer->page_dma,
				buffer->page_size, DMA_FROM_DEVICE);

	/* make sure HW write desc complete */
	dma_rmb();

	rx_desc = (struct hbg_rx_desc *)buffer->page_addr;
	return FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2) != 0;
}

static int hbg_build_skb(struct hbg_priv *priv,
			 struct hbg_buffer *buffer, u32 pkt_len)
{
	net_prefetch(buffer->page_addr);

	buffer->skb = napi_build_skb(buffer->page_addr, buffer->page_size);
	if (unlikely(!buffer->skb))
		return -ENOMEM;
	skb_mark_for_recycle(buffer->skb);

	/* page will be freed together with the skb */
	buffer->page = NULL;

Annotation

Implementation Notes