drivers/net/ethernet/fungible/funeth/funeth_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/fungible/funeth/funeth_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/fungible/funeth/funeth_rx.c
Extension
.c
Size
23021 bytes
Lines
829
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 (funeth_alloc_page(q, b, node, GFP_KERNEL)) {
			fun_rxq_free_bufs(q);
			return -ENOMEM;
		}
		q->rqes[i] = FUN_EPRQ_RQBUF_INIT(b->dma_addr);
	}
	q->cur_buf = q->bufs;
	return 0;
}

/* Initialize a used-buffer cache of the given depth. */
static int fun_rxq_init_cache(struct funeth_rx_cache *c, unsigned int depth,
			      int node)
{
	c->mask = depth - 1;
	c->bufs = kvzalloc_node(depth * sizeof(*c->bufs), GFP_KERNEL, node);
	return c->bufs ? 0 : -ENOMEM;
}

/* Deallocate an Rx queue's used-buffer cache and its contents. */
static void fun_rxq_free_cache(struct funeth_rxq *q)
{
	struct funeth_rxbuf *b = q->cache.bufs;
	unsigned int i;

	for (i = 0; i <= q->cache.mask; i++, b++)
		funeth_free_page(q, b);

	kvfree(q->cache.bufs);
	q->cache.bufs = NULL;
}

int fun_rxq_set_bpf(struct funeth_rxq *q, struct bpf_prog *prog)
{
	struct funeth_priv *fp = netdev_priv(q->netdev);
	struct fun_admin_epcq_req cmd;
	u16 headroom;
	int err;

	headroom = prog ? FUN_XDP_HEADROOM : FUN_RX_HEADROOM;
	if (headroom != q->headroom) {
		cmd.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_EPCQ,
							sizeof(cmd));
		cmd.u.modify =
			FUN_ADMIN_EPCQ_MODIFY_REQ_INIT(FUN_ADMIN_SUBOP_MODIFY,
						       0, q->hw_cqid, headroom);
		err = fun_submit_admin_sync_cmd(fp->fdev, &cmd.common, NULL, 0,
						0);
		if (err)
			return err;
		q->headroom = headroom;
	}

	WRITE_ONCE(q->xdp_prog, prog);
	return 0;
}

/* Create an Rx queue, allocating the host memory it needs. */
static struct funeth_rxq *fun_rxq_create_sw(struct net_device *dev,
					    unsigned int qidx,
					    unsigned int ncqe,
					    unsigned int nrqe,
					    struct fun_irq *irq)
{
	struct funeth_priv *fp = netdev_priv(dev);
	struct funeth_rxq *q;
	int err = -ENOMEM;
	int numa_node;

	numa_node = fun_irq_node(irq);
	q = kzalloc_node(sizeof(*q), GFP_KERNEL, numa_node);
	if (!q)
		goto err;

	q->qidx = qidx;
	q->netdev = dev;
	q->cq_mask = ncqe - 1;
	q->rq_mask = nrqe - 1;
	q->numa_node = numa_node;
	q->rq_db_thres = nrqe / 4;
	u64_stats_init(&q->syncp);
	q->dma_dev = &fp->pdev->dev;

	q->rqes = fun_alloc_ring_mem(q->dma_dev, nrqe, sizeof(*q->rqes),
				     sizeof(*q->bufs), false, numa_node,
				     &q->rq_dma_addr, (void **)&q->bufs, NULL);
	if (!q->rqes)
		goto free_q;

	q->cqes = fun_alloc_ring_mem(q->dma_dev, ncqe, FUNETH_CQE_SIZE, 0,

Annotation

Implementation Notes