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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/fungible/funeth/funeth_tx.c
Extension
.c
Size
21461 bytes
Lines
801
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 (likely(tls_ctx->next_seq == seq)) {
			*tls_len = datalen;
			return skb;
		}
		if (seq - tls_ctx->next_seq < U32_MAX / 4) {
			tls_offload_tx_resync_request(skb->sk, seq,
						      tls_ctx->next_seq);
		}
	}

	FUN_QSTAT_INC(q, tx_tls_fallback);
	skb = tls_encrypt_skb(skb);
	if (!skb)
		FUN_QSTAT_INC(q, tx_tls_drops);

	return skb;
#else
	return NULL;
#endif
}

/* Write as many descriptors as needed for the supplied skb starting at the
 * current producer location. The caller has made certain enough descriptors
 * are available.
 *
 * Returns the number of descriptors written, 0 on error.
 */
static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q,
				   unsigned int tls_len)
{
	unsigned int extra_bytes = 0, extra_pkts = 0;
	unsigned int idx = q->prod_cnt & q->mask;
	const struct skb_shared_info *shinfo;
	unsigned int lens[MAX_SKB_FRAGS + 1];
	dma_addr_t addrs[MAX_SKB_FRAGS + 1];
	struct fun_eth_tx_req *req;
	struct fun_dataop_gl *gle;
	const struct tcphdr *th;
	unsigned int l4_hlen;
	unsigned int ngle;
	u16 flags;

	shinfo = skb_shinfo(skb);
	if (unlikely(fun_map_pkt(q->dma_dev, shinfo, skb->data,
				 skb_headlen(skb), addrs, lens))) {
		FUN_QSTAT_INC(q, tx_map_err);
		return 0;
	}

	req = fun_tx_desc_addr(q, idx);
	req->op = FUN_ETH_OP_TX;
	req->len8 = 0;
	req->flags = 0;
	req->suboff8 = offsetof(struct fun_eth_tx_req, dataop);
	req->repr_idn = 0;
	req->encap_proto = 0;

	if (likely(shinfo->gso_size)) {
		if (skb->encapsulation) {
			u16 ol4_ofst;

			flags = FUN_ETH_OUTER_EN | FUN_ETH_INNER_LSO |
				FUN_ETH_UPDATE_INNER_L4_CKSUM |
				FUN_ETH_UPDATE_OUTER_L3_LEN;
			if (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
						SKB_GSO_UDP_TUNNEL_CSUM)) {
				flags |= FUN_ETH_UPDATE_OUTER_L4_LEN |
					 FUN_ETH_OUTER_UDP;
				if (shinfo->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
					flags |= FUN_ETH_UPDATE_OUTER_L4_CKSUM;
				ol4_ofst = skb_transport_offset(skb);
			} else {
				ol4_ofst = skb_inner_network_offset(skb);
			}

			if (ip_hdr(skb)->version == 4)
				flags |= FUN_ETH_UPDATE_OUTER_L3_CKSUM;
			else
				flags |= FUN_ETH_OUTER_IPV6;

			if (skb->inner_network_header) {
				if (inner_ip_hdr(skb)->version == 4)
					flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM |
						 FUN_ETH_UPDATE_INNER_L3_LEN;
				else
					flags |= FUN_ETH_INNER_IPV6 |
						 FUN_ETH_UPDATE_INNER_L3_LEN;
			}
			th = inner_tcp_hdr(skb);
			l4_hlen = __tcp_hdrlen(th);

Annotation

Implementation Notes