drivers/net/ethernet/intel/idpf/xsk.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/idpf/xsk.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/idpf/xsk.c
Extension
.c
Size
14046 bytes
Lines
637
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

struct idpf_xskfq_refill_set {
	struct {
		struct idpf_buf_queue	*q;
		u32			buf_id;
		u32			pending;
	} bufqs[IDPF_MAX_BUFQS_PER_RXQ_GRP];
};

static bool idpf_xskfq_refill_set(const struct idpf_xskfq_refill_set *set)
{
	bool ret = true;

	for (u32 i = 0; i < ARRAY_SIZE(set->bufqs); i++) {
		struct idpf_buf_queue *bufq = set->bufqs[i].q;
		u32 ntc;

		if (!bufq)
			continue;

		ntc = set->bufqs[i].buf_id;
		if (unlikely(++ntc == bufq->desc_count))
			ntc = 0;

		bufq->next_to_clean = ntc;
		bufq->pending += set->bufqs[i].pending;

		if (bufq->pending > bufq->thresh)
			ret &= idpf_xskfq_refill(bufq);
	}

	return ret;
}

int idpf_xskrq_poll(struct idpf_rx_queue *rxq, u32 budget)
{
	struct idpf_xskfq_refill_set set = { };
	struct libeth_rq_napi_stats rs = { };
	bool wake, gen, fail = false;
	u32 ntc = rxq->next_to_clean;
	struct libeth_xdp_buff *xdp;
	LIBETH_XDP_ONSTACK_BULK(bq);
	u32 cnt = rxq->desc_count;

	wake = xsk_uses_need_wakeup(rxq->pool);
	if (wake)
		xsk_clear_rx_need_wakeup(rxq->pool);

	gen = idpf_queue_has(GEN_CHK, rxq);

	libeth_xsk_tx_init_bulk(&bq, rxq->xdp_prog, rxq->xdp_rxq.dev,
				rxq->xdpsqs, rxq->num_xdp_txq);
	xdp = rxq->xsk;

	while (likely(rs.packets < budget)) {
		const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc;
		struct idpf_xdp_rx_desc desc __uninitialized;
		struct idpf_buf_queue *bufq;
		u32 bufq_id, buf_id;

		rx_desc = &rxq->rx[ntc].flex_adv_nic_3_wb;

		idpf_xdp_get_qw0(&desc, rx_desc);
		if (idpf_xdp_rx_gen(&desc) != gen)
			break;

		dma_rmb();

		bufq_id = idpf_xdp_rx_bufq(&desc);
		bufq = set.bufqs[bufq_id].q;
		if (!bufq) {
			bufq = &rxq->bufq_sets[bufq_id].bufq;
			set.bufqs[bufq_id].q = bufq;
		}

		idpf_xdp_get_qw1(&desc, rx_desc);
		buf_id = idpf_xdp_rx_buf(&desc);

		set.bufqs[bufq_id].buf_id = buf_id;
		set.bufqs[bufq_id].pending++;

		xdp = libeth_xsk_process_buff(xdp, bufq->xsk_buf[buf_id],
					      idpf_xdp_rx_len(&desc));

		if (unlikely(++ntc == cnt)) {
			ntc = 0;
			gen = !gen;
			idpf_queue_change(GEN_CHK, rxq);
		}

		if (!idpf_xdp_rx_eop(&desc) || unlikely(!xdp))

Annotation

Implementation Notes