drivers/net/ethernet/netronome/nfp/nfdk/dp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/netronome/nfp/nfdk/dp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/netronome/nfp/nfdk/dp.c
Extension
.c
Size
41648 bytes
Lines
1576
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 (skb_is_nonlinear(skb)) {
			err = skb_linearize(skb);
			if (err)
				return err;
			goto recount_descs;
		}
		return -EINVAL;
	}

	/* Under count by 1 (don't count meta) for the round down to work out */
	n_descs += !!skb_is_gso(skb);

	if (round_down(tx_ring->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
	    round_down(tx_ring->wr_p + n_descs, NFDK_TX_DESC_BLOCK_CNT))
		goto close_block;

	if ((u32)tx_ring->data_pending + skb->len > NFDK_TX_MAX_DATA_PER_BLOCK)
		goto close_block;

	return 0;

close_block:
	wr_p = tx_ring->wr_p;
	nop_slots = D_BLOCK_CPL(wr_p);

	wr_idx = D_IDX(tx_ring, wr_p);
	tx_ring->ktxbufs[wr_idx].skb = NULL;
	txd = &tx_ring->ktxds[wr_idx];

	memset(txd, 0, array_size(nop_slots, sizeof(struct nfp_nfdk_tx_desc)));

	tx_ring->data_pending = 0;
	tx_ring->wr_p += nop_slots;
	tx_ring->wr_ptr_add += nop_slots;

	return 0;
}

static int
nfp_nfdk_prep_tx_meta(struct nfp_net_dp *dp, struct nfp_app *app,
		      struct sk_buff *skb, bool *ipsec)
{
	struct metadata_dst *md_dst = skb_metadata_dst(skb);
	struct nfp_ipsec_offload offload_info;
	unsigned char *data;
	bool vlan_insert;
	u32 meta_id = 0;
	int md_bytes;

#ifdef CONFIG_NFP_NET_IPSEC
	if (xfrm_offload(skb))
		*ipsec = nfp_net_ipsec_tx_prep(dp, skb, &offload_info);
#endif

	if (unlikely(md_dst && md_dst->type != METADATA_HW_PORT_MUX))
		md_dst = NULL;

	vlan_insert = skb_vlan_tag_present(skb) && (dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2);

	if (!(md_dst || vlan_insert || *ipsec))
		return 0;

	md_bytes = sizeof(meta_id) +
		   (!!md_dst ? NFP_NET_META_PORTID_SIZE : 0) +
		   (vlan_insert ? NFP_NET_META_VLAN_SIZE : 0) +
		   (*ipsec ? NFP_NET_META_IPSEC_FIELD_SIZE : 0);

	if (unlikely(skb_cow_head(skb, md_bytes)))
		return -ENOMEM;

	data = skb_push(skb, md_bytes) + md_bytes;
	if (md_dst) {
		data -= NFP_NET_META_PORTID_SIZE;
		put_unaligned_be32(md_dst->u.port_info.port_id, data);
		meta_id = NFP_NET_META_PORTID;
	}
	if (vlan_insert) {
		data -= NFP_NET_META_VLAN_SIZE;
		/* data type of skb->vlan_proto is __be16
		 * so it fills metadata without calling put_unaligned_be16
		 */
		memcpy(data, &skb->vlan_proto, sizeof(skb->vlan_proto));
		put_unaligned_be16(skb_vlan_tag_get(skb), data + sizeof(skb->vlan_proto));
		meta_id <<= NFP_NET_META_FIELD_SIZE;
		meta_id |= NFP_NET_META_VLAN;
	}

	if (*ipsec) {
		data -= NFP_NET_META_IPSEC_SIZE;
		put_unaligned_be32(offload_info.seq_hi, data);

Annotation

Implementation Notes