drivers/net/ethernet/huawei/hinic/hinic_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic/hinic_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic/hinic_rx.c
Extension
.c
Size
15200 bytes
Lines
632
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

if (!rq_wqe) {
			rx_free_skb(rxq, skb, dma_addr);
			goto skb_out;
		}

		hinic_rq_prepare_wqe(rxq->rq, prod_idx, rq_wqe, &sge);

		hinic_rq_write_wqe(rxq->rq, prod_idx, rq_wqe, skb);
	}

skb_out:
	if (i) {
		wmb();  /* write all the wqes before update PI */

		hinic_rq_update(rxq->rq, prod_idx);
	}

	return i;
}

/**
 * free_all_rx_skbs - free all skbs in rx queue
 * @rxq: rx queue
 **/
static void free_all_rx_skbs(struct hinic_rxq *rxq)
{
	struct hinic_rq *rq = rxq->rq;
	struct hinic_hw_wqe *hw_wqe;
	struct hinic_sge sge;
	u16 ci;

	while ((hw_wqe = hinic_read_wqe(rq->wq, HINIC_RQ_WQE_SIZE, &ci))) {
		if (IS_ERR(hw_wqe))
			break;

		hinic_rq_get_sge(rq, &hw_wqe->rq_wqe, ci, &sge);

		hinic_put_wqe(rq->wq, HINIC_RQ_WQE_SIZE);

		rx_free_skb(rxq, rq->saved_skb[ci], hinic_sge_to_dma(&sge));
	}
}

/**
 * rx_recv_jumbo_pkt - Rx handler for jumbo pkt
 * @rxq: rx queue
 * @head_skb: the first skb in the list
 * @left_pkt_len: left size of the pkt exclude head skb
 * @ci: consumer index
 *
 * Return number of wqes that used for the left of the pkt
 **/
static int rx_recv_jumbo_pkt(struct hinic_rxq *rxq, struct sk_buff *head_skb,
			     unsigned int left_pkt_len, u16 ci)
{
	struct sk_buff *skb, *curr_skb = head_skb;
	struct hinic_rq_wqe *rq_wqe;
	unsigned int curr_len;
	struct hinic_sge sge;
	int num_wqes = 0;

	while (left_pkt_len > 0) {
		rq_wqe = hinic_rq_read_next_wqe(rxq->rq, HINIC_RQ_WQE_SIZE,
						&skb, &ci);

		num_wqes++;

		hinic_rq_get_sge(rxq->rq, rq_wqe, ci, &sge);

		rx_unmap_skb(rxq, hinic_sge_to_dma(&sge));

		prefetch(skb->data);

		curr_len = (left_pkt_len > HINIC_RX_BUF_SZ) ? HINIC_RX_BUF_SZ :
			    left_pkt_len;

		left_pkt_len -= curr_len;

		__skb_put(skb, curr_len);

		if (curr_skb == head_skb)
			skb_shinfo(head_skb)->frag_list = skb;
		else
			curr_skb->next = skb;

		head_skb->len += skb->len;
		head_skb->data_len += skb->len;
		head_skb->truesize += skb->truesize;

		curr_skb = skb;

Annotation

Implementation Notes