Commit 23109f8d authored by Subbaraya Sundeep's avatar Subbaraya Sundeep Committed by David S. Miller
Browse files

octeontx2-af: Introduce internal packet switching



As of now any communication between CGXs PFs and
their VFs within the system is possible only by
external switches sending packets back to the
system. This patch adds internal switching support.
Broadcast packet replication is not covered here.
RVU admin function (AF) maintains MAC addresses
of all interfaces in the system. When switching is
enabled, MCAM entries are allocated to install rules
such that packets with DMAC matching any of the
internal interface MAC addresses is punted back
into the system via the loopback channel.
On the receive side the default unicast rules
are modified to not check for ingress channel.
So any packet with matching DMAC irrespective of
which interface it is coming from will be forwarded
to the respective PF/VF interface.
The transmit side rules and default unicast rules
are updated if user changes MAC address of an interface.

Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb7a6b3b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -10,4 +10,4 @@ obj-$(CONFIG_OCTEONTX2_AF) += rvu_af.o
rvu_mbox-y := mbox.o rvu_trace.o
rvu_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
		  rvu_reg.o rvu_npc.o rvu_debugfs.o ptp.o rvu_npc_fs.o \
		  rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o
		  rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o
+3 −1
Original line number Diff line number Diff line
@@ -1314,7 +1314,7 @@ int rvu_mbox_handler_detach_resources(struct rvu *rvu,
	return rvu_detach_rsrcs(rvu, detach, detach->hdr.pcifunc);
}

static int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc)
int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
	int blkaddr = BLKADDR_NIX0, vf;
@@ -3007,6 +3007,8 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	/* Initialize debugfs */
	rvu_dbg_init(rvu);

	mutex_init(&rvu->rswitch.switch_lock);

	return 0;
err_dl:
	rvu_unregister_dl(rvu);
+19 −0
Original line number Diff line number Diff line
@@ -417,6 +417,14 @@ struct npc_kpu_profile_adapter {

#define RVU_SWITCH_LBK_CHAN	63

struct rvu_switch {
	struct mutex switch_lock; /* Serialize flow installation */
	u32 used_entries;
	u16 *entry2pcifunc;
	u16 mode;
	u16 start_entry;
};

struct rvu {
	void __iomem		*afreg_base;
	void __iomem		*pfreg_base;
@@ -447,6 +455,7 @@ struct rvu {

	/* CGX */
#define PF_CGXMAP_BASE		1 /* PF 0 is reserved for RVU PF */
	u16			cgx_mapped_vfs; /* maximum CGX mapped VFs */
	u8			cgx_mapped_pfs;
	u8			cgx_cnt_max;	 /* CGX port count max */
	u8			*pf2cgxlmac_map; /* pf to cgx_lmac map */
@@ -479,6 +488,9 @@ struct rvu {
	struct rvu_debugfs	rvu_dbg;
#endif
	struct rvu_devlink	*rvu_dl;

	/* RVU switch implementation over NPC with DMAC rules */
	struct rvu_switch	rswitch;
};

static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
@@ -693,6 +705,7 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw,
			struct nix_cn10k_aq_enq_req *aq_req,
			struct nix_cn10k_aq_enq_rsp *aq_rsp,
			u16 pcifunc, u8 ctype, u32 qidx);
int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc);

/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
@@ -770,4 +783,10 @@ void rvu_dbg_exit(struct rvu *rvu);
static inline void rvu_dbg_init(struct rvu *rvu) {}
static inline void rvu_dbg_exit(struct rvu *rvu) {}
#endif

/* RVU Switch */
void rvu_switch_enable(struct rvu *rvu);
void rvu_switch_disable(struct rvu *rvu);
void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc);

#endif /* RVU_H */
+3 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
	unsigned long lmac_bmap;
	int size, free_pkind;
	int cgx, lmac, iter;
	int numvfs, hwvfs;

	if (!cgx_cnt_max)
		return 0;
@@ -166,6 +167,8 @@ static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
			pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16;
			rvu_map_cgx_nix_block(rvu, pf, cgx, lmac);
			rvu->cgx_mapped_pfs++;
			rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvfs);
			rvu->cgx_mapped_vfs += numvfs;
			pf++;
		}
	}
+41 −7
Original line number Diff line number Diff line
@@ -1364,6 +1364,44 @@ static void rvu_health_reporters_destroy(struct rvu *rvu)
	rvu_nix_health_reporters_destroy(rvu_dl);
}

static int rvu_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
{
	struct rvu_devlink *rvu_dl = devlink_priv(devlink);
	struct rvu *rvu = rvu_dl->rvu;
	struct rvu_switch *rswitch;

	rswitch = &rvu->rswitch;
	*mode = rswitch->mode;

	return 0;
}

static int rvu_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
					struct netlink_ext_ack *extack)
{
	struct rvu_devlink *rvu_dl = devlink_priv(devlink);
	struct rvu *rvu = rvu_dl->rvu;
	struct rvu_switch *rswitch;

	rswitch = &rvu->rswitch;
	switch (mode) {
	case DEVLINK_ESWITCH_MODE_LEGACY:
	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
		if (rswitch->mode == mode)
			return 0;
		rswitch->mode = mode;
		if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
			rvu_switch_enable(rvu);
		else
			rvu_switch_disable(rvu);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int rvu_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
				struct netlink_ext_ack *extack)
{
@@ -1372,6 +1410,8 @@ static int rvu_devlink_info_get(struct devlink *devlink, struct devlink_info_req

static const struct devlink_ops rvu_devlink_ops = {
	.info_get = rvu_devlink_info_get,
	.eswitch_mode_get = rvu_devlink_eswitch_mode_get,
	.eswitch_mode_set = rvu_devlink_eswitch_mode_set,
};

int rvu_register_dl(struct rvu *rvu)
@@ -1380,14 +1420,9 @@ int rvu_register_dl(struct rvu *rvu)
	struct devlink *dl;
	int err;

	rvu_dl = kzalloc(sizeof(*rvu_dl), GFP_KERNEL);
	if (!rvu_dl)
		return -ENOMEM;

	dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink));
	if (!dl) {
		dev_warn(rvu->dev, "devlink_alloc failed\n");
		kfree(rvu_dl);
		return -ENOMEM;
	}

@@ -1395,10 +1430,10 @@ int rvu_register_dl(struct rvu *rvu)
	if (err) {
		dev_err(rvu->dev, "devlink register failed with error %d\n", err);
		devlink_free(dl);
		kfree(rvu_dl);
		return err;
	}

	rvu_dl = devlink_priv(dl);
	rvu_dl->dl = dl;
	rvu_dl->rvu = rvu;
	rvu->rvu_dl = rvu_dl;
@@ -1417,5 +1452,4 @@ void rvu_unregister_dl(struct rvu *rvu)
	rvu_health_reporters_destroy(rvu);
	devlink_unregister(dl);
	devlink_free(dl);
	kfree(rvu_dl);
}
Loading