Commit f0c2982a authored by Naveen Mamindlapalli's avatar Naveen Mamindlapalli Committed by Jakub Kicinski
Browse files

octeontx2-pf: Add support for SR-IOV management functions



This patch adds support for ndo_set_vf_mac, ndo_set_vf_vlan
and ndo_get_vf_config handlers. The traffic redirection
based on the VF mac address or vlan id is done by installing
MCAM rules. Reserved RX_VTAG_TYPE7 in each NIXLF for VF VLAN
which strips the VLAN tag from ingress VLAN traffic. The NIX PF
allocates two MCAM entries for VF VLAN feature, one used for
ingress VTAG strip and another entry for egress VTAG insertion.

This patch also updates the MAC address in PF installed VF VLAN
rule upon receiving nix_lf_start_rx mbox request for VF since
Administrative Function driver will assign a valid MAC addr
in nix_lf_start_rx function.

Signed-off-by: default avatarNaveen Mamindlapalli <naveenm@marvell.com>
Co-developed-by: default avatarTomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: default avatarTomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent fd9d7859
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ struct rvu_npc_mcam_rule {
	bool has_cntr;
	u8 default_rule;
	bool enable;
	bool vfvlan_cfg;
};

#endif /* NPC_H */
+4 −0
Original line number Diff line number Diff line
@@ -209,6 +209,7 @@ struct rvu_pfvf {
	u16		maxlen;
	u16		minlen;

	u8		pf_set_vf_cfg;
	u8		mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */

	/* Broadcast pkt replication info */
@@ -596,6 +597,9 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target);
void npc_mcam_disable_flows(struct rvu *rvu, u16 target);
void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
			   int blkaddr, int index, bool enable);
void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
			 int blkaddr, u16 src, struct mcam_entry *entry,
			 u8 *intf, u8 *ena);

#ifdef CONFIG_DEBUG_FS
void rvu_dbg_init(struct rvu *rvu);
+14 −0
Original line number Diff line number Diff line
@@ -1194,6 +1194,11 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
	/* Disable NPC entries as NIXLF's contexts are not initialized yet */
	rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);

	/* Configure RX VTAG Type 7 (strip) for vf vlan */
	rvu_write64(rvu, blkaddr,
		    NIX_AF_LFX_RX_VTAG_TYPEX(nixlf, NIX_AF_LFX_RX_VTAG_TYPE7),
		    VTAGSIZE_T4 | VTAG_STRIP);

	goto exit;

free_mem:
@@ -1988,6 +1993,10 @@ static int nix_rx_vtag_cfg(struct rvu *rvu, int nixlf, int blkaddr,
	    req->vtag_size > VTAGSIZE_T8)
		return -EINVAL;

	/* RX VTAG Type 7 reserved for vf vlan */
	if (req->rx.vtag_type == NIX_AF_LFX_RX_VTAG_TYPE7)
		return NIX_AF_ERR_RX_VTAG_INUSE;

	if (req->rx.capture_vtag)
		regval |= BIT_ULL(5);
	if (req->rx.strip_vtag)
@@ -2931,6 +2940,7 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,
				      struct nix_set_mac_addr *req,
				      struct msg_rsp *rsp)
{
	bool from_vf = req->hdr.pcifunc & RVU_PFVF_FUNC_MASK;
	u16 pcifunc = req->hdr.pcifunc;
	int blkaddr, nixlf, err;
	struct rvu_pfvf *pfvf;
@@ -2941,6 +2951,10 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,

	pfvf = rvu_get_pfvf(rvu, pcifunc);

	/* VF can't overwrite admin(PF) changes */
	if (from_vf && pfvf->pf_set_vf_cfg)
		return -EPERM;

	ether_addr_copy(pfvf->mac_addr, req->mac_addr);

	rvu_npc_install_ucast_entry(rvu, pcifunc, nixlf,
+88 −0
Original line number Diff line number Diff line
@@ -359,6 +359,58 @@ static void npc_get_keyword(struct mcam_entry *entry, int idx,
	*cam0 = ~*cam1 & kw_mask;
}

static void npc_fill_entryword(struct mcam_entry *entry, int idx,
			       u64 cam0, u64 cam1)
{
	/* Similar to npc_get_keyword, but fills mcam_entry structure from
	 * CAM registers.
	 */
	switch (idx) {
	case 0:
		entry->kw[0] = cam1;
		entry->kw_mask[0] = cam1 ^ cam0;
		break;
	case 1:
		entry->kw[1] = cam1;
		entry->kw_mask[1] = cam1 ^ cam0;
		break;
	case 2:
		entry->kw[1] |= (cam1 & CAM_MASK(16)) << 48;
		entry->kw[2] = (cam1 >> 16) & CAM_MASK(48);
		entry->kw_mask[1] |= ((cam1 ^ cam0) & CAM_MASK(16)) << 48;
		entry->kw_mask[2] = ((cam1 ^ cam0) >> 16) & CAM_MASK(48);
		break;
	case 3:
		entry->kw[2] |= (cam1 & CAM_MASK(16)) << 48;
		entry->kw[3] = (cam1 >> 16) & CAM_MASK(32);
		entry->kw_mask[2] |= ((cam1 ^ cam0) & CAM_MASK(16)) << 48;
		entry->kw_mask[3] = ((cam1 ^ cam0) >> 16) & CAM_MASK(32);
		break;
	case 4:
		entry->kw[3] |= (cam1 & CAM_MASK(32)) << 32;
		entry->kw[4] = (cam1 >> 32) & CAM_MASK(32);
		entry->kw_mask[3] |= ((cam1 ^ cam0) & CAM_MASK(32)) << 32;
		entry->kw_mask[4] = ((cam1 ^ cam0) >> 32) & CAM_MASK(32);
		break;
	case 5:
		entry->kw[4] |= (cam1 & CAM_MASK(32)) << 32;
		entry->kw[5] = (cam1 >> 32) & CAM_MASK(16);
		entry->kw_mask[4] |= ((cam1 ^ cam0) & CAM_MASK(32)) << 32;
		entry->kw_mask[5] = ((cam1 ^ cam0) >> 32) & CAM_MASK(16);
		break;
	case 6:
		entry->kw[5] |= (cam1 & CAM_MASK(48)) << 16;
		entry->kw[6] = (cam1 >> 48) & CAM_MASK(16);
		entry->kw_mask[5] |= ((cam1 ^ cam0) & CAM_MASK(48)) << 16;
		entry->kw_mask[6] = ((cam1 ^ cam0) >> 48) & CAM_MASK(16);
		break;
	case 7:
		entry->kw[6] |= (cam1 & CAM_MASK(48)) << 16;
		entry->kw_mask[6] |= ((cam1 ^ cam0) & CAM_MASK(48)) << 16;
		break;
	}
}

static void npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam,
					 int blkaddr, int index,
					 struct mcam_entry *entry)
@@ -459,6 +511,42 @@ static void npc_config_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
		npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, true);
}

void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
			 int blkaddr, u16 src,
			 struct mcam_entry *entry, u8 *intf, u8 *ena)
{
	int sbank = npc_get_bank(mcam, src);
	int bank, kw = 0;
	u64 cam0, cam1;

	src &= (mcam->banksize - 1);
	bank = sbank;

	for (; bank < (sbank + mcam->banks_per_entry); bank++, kw = kw + 2) {
		cam1 = rvu_read64(rvu, blkaddr,
				  NPC_AF_MCAMEX_BANKX_CAMX_W0(src, bank, 1));
		cam0 = rvu_read64(rvu, blkaddr,
				  NPC_AF_MCAMEX_BANKX_CAMX_W0(src, bank, 0));
		npc_fill_entryword(entry, kw, cam0, cam1);

		cam1 = rvu_read64(rvu, blkaddr,
				  NPC_AF_MCAMEX_BANKX_CAMX_W1(src, bank, 1));
		cam0 = rvu_read64(rvu, blkaddr,
				  NPC_AF_MCAMEX_BANKX_CAMX_W1(src, bank, 0));
		npc_fill_entryword(entry, kw + 1, cam0, cam1);
	}

	entry->action = rvu_read64(rvu, blkaddr,
				   NPC_AF_MCAMEX_BANKX_ACTION(src, sbank));
	entry->vtag_action =
		rvu_read64(rvu, blkaddr,
			   NPC_AF_MCAMEX_BANKX_TAG_ACT(src, sbank));
	*intf = rvu_read64(rvu, blkaddr,
			   NPC_AF_MCAMEX_BANKX_CAMX_INTF(src, sbank, 1)) & 3;
	*ena = rvu_read64(rvu, blkaddr,
			  NPC_AF_MCAMEX_BANKX_CFG(src, sbank)) & 1;
}

static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
				int blkaddr, u16 src, u16 dest)
{
+40 −0
Original line number Diff line number Diff line
@@ -1065,6 +1065,9 @@ update_rule:
	if (req->default_rule)
		pfvf->def_ucast_rule = rule;

	if (pfvf->pf_set_vf_cfg && req->vtag0_type == NIX_AF_LFX_RX_VTAG_TYPE7)
		rule->vfvlan_cfg = true;

	return 0;
}

@@ -1113,6 +1116,10 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,

	pfvf = rvu_get_pfvf(rvu, target);

	/* PF installing for its VF */
	if (req->hdr.pcifunc && !from_vf && req->vf)
		pfvf->pf_set_vf_cfg = 1;

	/* update req destination mac addr */
	if ((req->features & BIT_ULL(NPC_DMAC)) && is_npc_intf_rx(req->intf) &&
	    is_zero_ether_addr(req->packet.dmac)) {
@@ -1210,6 +1217,36 @@ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu,
	return 0;
}

static int npc_update_dmac_value(struct rvu *rvu, int npcblkaddr,
				 struct rvu_npc_mcam_rule *rule,
				 struct rvu_pfvf *pfvf)
{
	struct npc_mcam_write_entry_req write_req = { 0 };
	struct mcam_entry *entry = &write_req.entry_data;
	struct npc_mcam *mcam = &rvu->hw->mcam;
	struct msg_rsp rsp;
	u8 intf, enable;
	int err;

	ether_addr_copy(rule->packet.dmac, pfvf->mac_addr);

	npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry,
			    entry, &intf,  &enable);

	npc_update_entry(rvu, NPC_DMAC, entry,
			 ether_addr_to_u64(pfvf->mac_addr), 0,
			 0xffffffffffffull, 0, intf);

	write_req.hdr.pcifunc = rule->owner;
	write_req.entry = rule->entry;

	mutex_unlock(&mcam->lock);
	err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, &rsp);
	mutex_lock(&mcam->lock);

	return err;
}

void npc_mcam_enable_flows(struct rvu *rvu, u16 target)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, target);
@@ -1236,6 +1273,9 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target)
				continue;
			}

			if (rule->vfvlan_cfg)
				npc_update_dmac_value(rvu, blkaddr, rule, pfvf);

			if (rule->rx_action.op == NIX_RX_ACTION_DEFAULT) {
				if (!def_ucast_rule)
					continue;
Loading