drivers/net/ethernet/pensando/ionic/ionic_txrx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/pensando/ionic/ionic_txrx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
Extension
.c
Size
45653 bytes
Lines
1848
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 (act == XDP_TX) {
				struct page *pg = skb_frag_page(frag);

				dma_addr = page_pool_get_dma_addr(pg) +
					   skb_frag_off(frag);
				dma_sync_single_for_device(q->dev, dma_addr,
							   skb_frag_size(frag),
							   DMA_TO_DEVICE);
			} else {
				dma_addr = ionic_tx_map_frag(q, frag, 0,
							     skb_frag_size(frag));
				if (dma_addr == DMA_MAPPING_ERROR) {
					ionic_tx_desc_unmap_bufs(q, desc_info);
					return -EIO;
				}
			}
			bi->dma_addr = dma_addr;
			bi->len = skb_frag_size(frag);
			bi->page = skb_frag_page(frag);

			elem->addr = cpu_to_le64(bi->dma_addr);
			elem->len = cpu_to_le16(bi->len);
			elem++;

			desc_info->nbufs++;
		}
	}

	cmd = encode_txq_desc_cmd(IONIC_TXQ_DESC_OPCODE_CSUM_NONE,
				  0, (desc_info->nbufs - 1), buf_info->dma_addr);
	desc->cmd = cpu_to_le64(cmd);
	desc->len = cpu_to_le16(len);
	desc->csum_start = 0;
	desc->csum_offset = 0;

	stats->xdp_frames++;
	stats->pkts++;
	stats->bytes += len;

	ionic_txq_post(q, ring_doorbell);

	return 0;
}

int ionic_xdp_xmit(struct net_device *netdev, int n,
		   struct xdp_frame **xdp_frames, u32 flags)
{
	struct ionic_lif *lif = netdev_priv(netdev);
	struct ionic_queue *txq;
	struct netdev_queue *nq;
	int nxmit;
	int space;
	int cpu;
	int qi;

	if (unlikely(!test_bit(IONIC_LIF_F_UP, lif->state)))
		return -ENETDOWN;

	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
		return -EINVAL;

	/* AdminQ is assumed on cpu 0, while we attempt to affinitize the
	 * TxRx queue pairs 0..n-1 on cpus 1..n.  We try to keep with that
	 * affinitization here, but of course irqbalance and friends might
	 * have juggled things anyway, so we have to check for the 0 case.
	 */
	cpu = smp_processor_id();
	qi = cpu ? (cpu - 1) % lif->nxqs : cpu;

	txq = &lif->txqcqs[qi]->q;
	nq = netdev_get_tx_queue(netdev, txq->index);
	__netif_tx_lock(nq, cpu);
	txq_trans_cond_update(nq);

	if (netif_tx_queue_stopped(nq) ||
	    !netif_txq_maybe_stop(q_to_ndq(netdev, txq),
				  ionic_q_space_avail(txq),
				  1, 1)) {
		__netif_tx_unlock(nq);
		return -EIO;
	}

	space = min_t(int, n, ionic_q_space_avail(txq));
	for (nxmit = 0; nxmit < space ; nxmit++) {
		if (ionic_xdp_post_frame(txq, xdp_frames[nxmit],
					 XDP_REDIRECT,
					 virt_to_page(xdp_frames[nxmit]->data),
					 0, false)) {
			nxmit--;
			break;

Annotation

Implementation Notes