drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
Extension
.c
Size
66742 bytes
Lines
2257
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 (etype_ether->kw_mask[i] != etype_tag1->kw_mask[i]) {
				dev_err(rvu->dev, "mkex: Etype pos is different for untagged and tagged pkts.\n");
				goto vlan_tci;
			}
		}
		key_fields[NPC_ETYPE] = *etype_tag1;
	}
	if (etype_ether->nr_kws && etype_tag2->nr_kws) {
		for (i = 0; i < max_kw; i++) {
			if (etype_ether->kw_mask[i] != etype_tag2->kw_mask[i]) {
				dev_err(rvu->dev, "mkex: Etype pos is different for untagged and double tagged pkts.\n");
				goto vlan_tci;
			}
		}
		key_fields[NPC_ETYPE] = *etype_tag2;
	}
	if (etype_tag1->nr_kws && etype_tag2->nr_kws) {
		for (i = 0; i < max_kw; i++) {
			if (etype_tag1->kw_mask[i] != etype_tag2->kw_mask[i]) {
				dev_err(rvu->dev, "mkex: Etype pos is different for tagged and double tagged pkts.\n");
				goto vlan_tci;
			}
		}
		key_fields[NPC_ETYPE] = *etype_tag2;
	}

	/* check none of higher layers overwrite Ethertype */
	start_lid = key_fields[NPC_ETYPE].layer_mdata.lid + 1;
	if (npc_check_overlap(rvu, blkaddr, NPC_ETYPE, start_lid, intf)) {
		dev_err(rvu->dev, "mkex: Ethertype is overwritten by higher layers.\n");
		goto vlan_tci;
	}
	*features |= BIT_ULL(NPC_ETYPE);
vlan_tci:
	/* if key profile does not extract outer vlan tci at all */
	if (!vlan_tag1->nr_kws && !vlan_tag2->nr_kws) {
		dev_err(rvu->dev, "mkex: Outer vlan tci is not extracted.\n");
		goto done;
	}

	/* if key profile extracts outer vlan tci from one layer */
	if (vlan_tag1->nr_kws && !vlan_tag2->nr_kws)
		key_fields[NPC_OUTER_VID] = *vlan_tag1;
	if (!vlan_tag1->nr_kws && vlan_tag2->nr_kws)
		key_fields[NPC_OUTER_VID] = *vlan_tag2;

	/* if key profile extracts outer vlan tci from multiple layers */
	if (vlan_tag1->nr_kws && vlan_tag2->nr_kws) {
		for (i = 0; i < max_kw; i++) {
			if (vlan_tag1->kw_mask[i] != vlan_tag2->kw_mask[i]) {
				dev_err(rvu->dev, "mkex: Out vlan tci pos is different for tagged and double tagged pkts.\n");
				goto done;
			}
		}
		key_fields[NPC_OUTER_VID] = *vlan_tag2;
	}
	/* check none of higher layers overwrite outer vlan tci */
	start_lid = key_fields[NPC_OUTER_VID].layer_mdata.lid + 1;
	if (npc_check_overlap(rvu, blkaddr, NPC_OUTER_VID, start_lid, intf)) {
		dev_err(rvu->dev, "mkex: Outer vlan tci is overwritten by higher layers.\n");
		goto done;
	}
	*features |= BIT_ULL(NPC_OUTER_VID);

	/* If key profile extracts inner vlan tci */
	if (vlan_tag3->nr_kws) {
		key_fields[NPC_INNER_VID] = *vlan_tag3;
		*features |= BIT_ULL(NPC_INNER_VID);
	}
done:
	return;
}

static void npc_scan_ldata(struct rvu *rvu, int blkaddr, u8 lid,
			   u8 lt, u64 cfg, u8 intf)
{
	struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u8 hdr, key, nr_bytes, bit_offset;
	u8 la_ltype, la_start;
	/* starting KW index and starting bit position */
	int start_kwi, offset;

	if (is_cn20k(rvu->pdev))
		nr_bytes = FIELD_GET(NPC_CN20K_BYTESM, cfg) + 1;
	else
		nr_bytes = FIELD_GET(NPC_BYTESM, cfg) + 1;

	hdr = FIELD_GET(NPC_HDR_OFFSET, cfg);
	key = FIELD_GET(NPC_KEY_OFFSET, cfg);

Annotation

Implementation Notes