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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/idpf/xdp.c
Extension
.c
Size
12163 bytes
Lines
530
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 (!timers[i]) {
			for (int j = i - 1; j >= 0; j--)
				kfree(timers[j]);

			return -ENOMEM;
		}
	}

	dev = vport->netdev;
	sqs = vport->dflt_qv_rsrc.xdp_txq_offset;

	for (u32 i = sqs; i < vport->num_txq; i++) {
		struct idpf_tx_queue *xdpsq = vport->txqs[i];

		xdpsq->complq = xdpsq->txq_grp->complq;
		kfree(xdpsq->refillq);
		xdpsq->refillq = NULL;

		idpf_queue_clear(FLOW_SCH_EN, xdpsq);
		idpf_queue_clear(FLOW_SCH_EN, xdpsq->complq);
		idpf_queue_set(NOIRQ, xdpsq);
		idpf_queue_set(XDP, xdpsq);
		idpf_queue_set(XDP, xdpsq->complq);

		xdpsq->timer = timers[i - sqs];
		libeth_xdpsq_get(&xdpsq->xdp_lock, dev, vport->xdpsq_share);
		libeth_xdpsq_init_timer(xdpsq->timer, xdpsq, &xdpsq->xdp_lock,
					idpf_xdp_tx_timer);

		xdpsq->pending = 0;
		xdpsq->xdp_tx = 0;
		xdpsq->thresh = libeth_xdp_queue_threshold(xdpsq->desc_count);
	}

	return 0;
}

void idpf_xdpsqs_put(const struct idpf_vport *vport)
{
	struct net_device *dev;
	u32 sqs;

	if (!idpf_xdp_enabled(vport))
		return;

	dev = vport->netdev;
	sqs = vport->dflt_qv_rsrc.xdp_txq_offset;

	for (u32 i = sqs; i < vport->num_txq; i++) {
		struct idpf_tx_queue *xdpsq = vport->txqs[i];

		if (!idpf_queue_has_clear(XDP, xdpsq))
			continue;

		libeth_xdpsq_deinit_timer(xdpsq->timer);
		libeth_xdpsq_put(&xdpsq->xdp_lock, dev);

		kfree(xdpsq->timer);
		xdpsq->refillq = NULL;
		idpf_queue_clear(NOIRQ, xdpsq);
	}
}

static int idpf_xdp_parse_cqe(const struct idpf_splitq_4b_tx_compl_desc *desc,
			      bool gen)
{
	u32 val;

#ifdef __LIBETH_WORD_ACCESS
	val = *(const u32 *)desc;
#else
	val = ((u32)le16_to_cpu(desc->q_head_compl_tag.q_head) << 16) |
	      le16_to_cpu(desc->qid_comptype_gen);
#endif
	if (!!(val & IDPF_TXD_COMPLQ_GEN_M) != gen)
		return -ENODATA;

	if (unlikely((val & GENMASK(IDPF_TXD_COMPLQ_GEN_S - 1, 0)) !=
		     FIELD_PREP(IDPF_TXD_COMPLQ_COMPL_TYPE_M,
				IDPF_TXD_COMPLT_RS)))
		return -EINVAL;

	return upper_16_bits(val);
}

u32 idpf_xdpsq_poll(struct idpf_tx_queue *xdpsq, u32 budget)
{
	struct idpf_compl_queue *cq = xdpsq->complq;
	u32 tx_ntc = xdpsq->next_to_clean;
	u32 tx_cnt = xdpsq->desc_count;

Annotation

Implementation Notes