drivers/net/vmxnet3/vmxnet3_xdp.c

Source file repositories/reference/linux-study-clean/drivers/net/vmxnet3/vmxnet3_xdp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/vmxnet3/vmxnet3_xdp.c
Extension
.c
Size
10436 bytes
Lines
430
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 (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) {
			spin_unlock_irq(&tq->tx_lock);
			return -EFAULT;
		}
		tbi->map_type |= VMXNET3_MAP_SINGLE;
	} else { /* XDP buffer from page pool */
		page = virt_to_page(xdpf->data);
		tbi->dma_addr = page_pool_get_dma_addr(page) +
				(xdpf->data - (void *)xdpf);
		dma_sync_single_for_device(&adapter->pdev->dev,
					   tbi->dma_addr, buf_size,
					   DMA_TO_DEVICE);
	}
	tbi->xdpf = xdpf;
	tbi->len = buf_size;

	gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
	WARN_ON_ONCE(gdesc->txd.gen == tq->tx_ring.gen);

	gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
	gdesc->dword[2] = cpu_to_le32(dw2);

	/* Setup the EOP desc */
	gdesc->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP);

	gdesc->txd.om = 0;
	gdesc->txd.msscof = 0;
	gdesc->txd.hlen = 0;
	gdesc->txd.ti = 0;

	tx_num_deferred = le32_to_cpu(tq->shared->txNumDeferred);
	le32_add_cpu(&tq->shared->txNumDeferred, 1);
	tx_num_deferred++;

	vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);

	/* set the last buf_info for the pkt */
	tbi->sop_idx = ctx.sop_txd - tq->tx_ring.base;

	dma_wmb();
	gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
						  VMXNET3_TXD_GEN);
	spin_unlock_irq(&tq->tx_lock);

	/* No need to handle the case when tx_num_deferred doesn't reach
	 * threshold. Backend driver at hypervisor side will poll and reset
	 * tq->shared->txNumDeferred to 0.
	 */
	if (tx_num_deferred >= le32_to_cpu(tq->shared->txThreshold)) {
		tq->shared->txNumDeferred = 0;
		VMXNET3_WRITE_BAR0_REG(adapter,
				       VMXNET3_REG_TXPROD + tq->qid * 8,
				       tq->tx_ring.next2fill);
	}

	return 0;
}

static int
vmxnet3_xdp_xmit_back(struct vmxnet3_adapter *adapter,
		      struct xdp_frame *xdpf)
{
	struct vmxnet3_tx_queue *tq;
	struct netdev_queue *nq;
	int err;

	tq = vmxnet3_xdp_get_tq(adapter);
	if (tq->stopped)
		return -ENETDOWN;

	nq = netdev_get_tx_queue(adapter->netdev, tq->qid);

	__netif_tx_lock(nq, smp_processor_id());
	err = vmxnet3_xdp_xmit_frame(adapter, xdpf, tq, false);
	__netif_tx_unlock(nq);

	return err;
}

/* ndo_xdp_xmit */
int
vmxnet3_xdp_xmit(struct net_device *dev,
		 int n, struct xdp_frame **frames, u32 flags)
{
	struct vmxnet3_adapter *adapter = netdev_priv(dev);
	struct vmxnet3_tx_queue *tq;
	struct netdev_queue *nq;
	int i;

	if (unlikely(test_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state)))

Annotation

Implementation Notes