drivers/net/ethernet/intel/i40e/i40e_xsk.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/i40e/i40e_xsk.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/i40e/i40e_xsk.c
Extension
.c
Size
19704 bytes
Lines
791
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 (!page) {
			dev_kfree_skb(skb);
			return NULL;
		}
		addr = page_to_virt(page);

		memcpy(addr, skb_frag_page(frag), skb_frag_size(frag));

		__skb_fill_page_desc_noacc(skinfo, skinfo->nr_frags++,
					   addr, 0, skb_frag_size(frag));
	}

out:
	xsk_buff_free(xdp);
	return skb;
}

static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring,
				      struct xdp_buff *xdp_buff,
				      union i40e_rx_desc *rx_desc,
				      unsigned int *rx_packets,
				      unsigned int *rx_bytes,
				      unsigned int xdp_res,
				      bool *failure)
{
	struct sk_buff *skb;

	*rx_packets = 1;
	*rx_bytes = xdp_get_buff_len(xdp_buff);

	if (likely(xdp_res == I40E_XDP_REDIR) || xdp_res == I40E_XDP_TX)
		return;

	if (xdp_res == I40E_XDP_EXIT) {
		*failure = true;
		return;
	}

	if (xdp_res == I40E_XDP_CONSUMED) {
		xsk_buff_free(xdp_buff);
		return;
	}
	if (xdp_res == I40E_XDP_PASS) {
		/* NB! We are not checking for errors using
		 * i40e_test_staterr with
		 * BIT(I40E_RXD_QW1_ERROR_SHIFT). This is due to that
		 * SBP is *not* set in PRT_SBPVSI (default not set).
		 */
		skb = i40e_construct_skb_zc(rx_ring, xdp_buff);
		if (!skb) {
			rx_ring->rx_stats.alloc_buff_failed++;
			*rx_packets = 0;
			*rx_bytes = 0;
			return;
		}

		if (eth_skb_pad(skb)) {
			*rx_packets = 0;
			*rx_bytes = 0;
			return;
		}

		i40e_process_skb_fields(rx_ring, rx_desc, skb);
		napi_gro_receive(&rx_ring->q_vector->napi, skb);
		return;
	}

	/* Should never get here, as all valid cases have been handled already.
	 */
	WARN_ON_ONCE(1);
}

/**
 * i40e_clean_rx_irq_zc - Consumes Rx packets from the hardware ring
 * @rx_ring: Rx ring
 * @budget: NAPI budget
 *
 * Returns amount of work completed
 **/
int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
{
	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
	u16 next_to_process = rx_ring->next_to_process;
	u16 next_to_clean = rx_ring->next_to_clean;
	unsigned int xdp_res, xdp_xmit = 0;
	struct xdp_buff *first = NULL;
	u32 count = rx_ring->count;
	struct bpf_prog *xdp_prog;
	u32 entries_to_alloc;
	bool failure = false;

Annotation

Implementation Notes