diff mbox series

[net-next,v10,03/11] octeontx2-pf: Create representor netdev

Message ID 20240805131815.7588-4-gakula@marvell.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series Introduce RVU representors | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7 this patch: 7
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 4 maintainers not CCed: linux-doc@vger.kernel.org lcherian@marvell.com corbet@lwn.net jerinj@marvell.com
netdev/build_clang success Errors and warnings before: 29 this patch: 29
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 41 this patch: 41
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 340 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-08-06--00-00 (tests: 707)

Commit Message

Geetha sowjanya Aug. 5, 2024, 1:18 p.m. UTC
Adds initial devlink support to set/get the switchdev mode.
Representor netdevs are created for each rvu devices when
the switch mode is set to 'switchdev'. These netdevs are
be used to control and configure VFs.

Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Reviewed-by: Simon Horman <horms@kernel.org>
---
 .../ethernet/marvell/octeontx2.rst            |  85 +++++++++
 .../marvell/octeontx2/nic/otx2_devlink.c      |  49 ++++++
 .../net/ethernet/marvell/octeontx2/nic/rep.c  | 165 ++++++++++++++++++
 .../net/ethernet/marvell/octeontx2/nic/rep.h  |   3 +
 4 files changed, 302 insertions(+)

Comments

Jiri Pirko Aug. 8, 2024, 3:51 p.m. UTC | #1
Mon, Aug 05, 2024 at 03:18:07PM CEST, gakula@marvell.com wrote:
>Adds initial devlink support to set/get the switchdev mode.
>Representor netdevs are created for each rvu devices when
>the switch mode is set to 'switchdev'. These netdevs are
>be used to control and configure VFs.
>
>Signed-off-by: Geetha sowjanya <gakula@marvell.com>
>Reviewed-by: Simon Horman <horms@kernel.org>
>---
> .../ethernet/marvell/octeontx2.rst            |  85 +++++++++
> .../marvell/octeontx2/nic/otx2_devlink.c      |  49 ++++++
> .../net/ethernet/marvell/octeontx2/nic/rep.c  | 165 ++++++++++++++++++
> .../net/ethernet/marvell/octeontx2/nic/rep.h  |   3 +
> 4 files changed, 302 insertions(+)
>
>diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
>index 1e196cb9ce25..4eb4e6788ffc 100644
>--- a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
>+++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
>@@ -14,6 +14,7 @@ Contents
> - `Basic packet flow`_
> - `Devlink health reporters`_
> - `Quality of service`_
>+- `RVU representors`_
> 
> Overview
> ========
>@@ -340,3 +341,87 @@ Setup HTB offload
>         # tc class add dev <interface> parent 1: classid 1:2 htb rate 10Gbit prio 2 quantum 188416
> 
>         # tc class add dev <interface> parent 1: classid 1:3 htb rate 10Gbit prio 2 quantum 32768
>+
>+
>+RVU Representors
>+================
>+
>+RVU representor driver adds support for creation of representor devices for
>+RVU PFs' VFs in the system. Representor devices are created when user enables
>+the switchdev mode.
>+Switchdev mode can be enabled either before or after setting up SRIOV numVFs.
>+All representor devices share a single NIXLF but each has a dedicated queue
>+(ie RQ/SQ. RVU PF representor driver registers a separate netdev for each
>+RQ/SQ queue pair.
>+
>+HW doesn't have a in-built switch which can do L2 learning and forward pkts
>+between representee and representor. Hence packet patch between representee
>+and it's representor is achieved by setting up appropriate NPC MCAM filters.
>+Transmit packets matching these filters will be loopbacked through hardware
>+loopback channel/interface (ie instead of sending them out of MAC interface).
>+Which will again match the installed filters and will be forwarded.
>+This way representee => representor and representor => representee packet
>+path is achieved.These rules get installed when representors are created
>+and gets active/deactivate based on the representor/representee interface state.
>+
>+Usage example:
>+
>+ - List of devices on the system before vfs are created::
>+
>+	# devlink dev
>+	pci/0002:02:00.0
>+	pci/0002:1c:00.0
>+
>+- Change device to switchdev mode::
>+	# devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
>+
>+ - List the devices on the system::
>+
>+	# ip link show
>+
>+Sample output::
>+
>+	# ip link show
>+	eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7e:58:2d:b6:97:51 brd ff:ff:ff:ff:ff:ff
>+	r0p1v0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7e:5a:66:ea:fe:d6 brd ff:ff:ff:ff:ff:ff
>+	r1p1v1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether de:29:be:10:9e:bf brd ff:ff:ff:ff:ff:ff
>+	r2p1v2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 4a:12:c7:a2:66:ad brd ff:ff:ff:ff:ff:ff
>+	r3p1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether c2:b8:a8:0e:73:fd brd ff:ff:ff:ff:ff:ff
>+
>+
>+RVU representors can be managed using devlink ports
>+(see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.
>+
>+ - Show devlink ports of representors::
>+
>+	# devlink port
>+
>+Sample output::
>+
>+	pci/0002:1c:00.0/0: type eth netdev r0p1v0 flavour pcipf controller 0 pfnum 1 vfnum 0 external false splittable false
>+	pci/0002:1c:00.0/1: type eth netdev r1p1v1 flavour pcivf controller 0 pfnum 1 vfnum 1 external false splittable false
>+	pci/0002:1c:00.0/2: type eth netdev r2p1v2 flavour pcivf controller 0 pfnum 1 vfnum 2 external false splittable false
>+	pci/0002:1c:00.0/3: type eth netdev r3p1v3 flavour pcivf controller 0 pfnum 1 vfnum 3 external false splittable false
>+
>+Function attributes
>+===================
>+
>+The RVU representor support function attributes for representors
>+Port function configuration of the representors are supported through devlink eswitch port.
>+
>+MAC address setup
>+-----------------
>+
>+RVU representor driver support devlink port function attr mechanism to setup MAC
>+address. (refer to Documentation/networking/devlink/devlink-port.rst)
>+
>+ - To setup MAC address for port 2::
>+
>+	# devlink port function set  pci/0002:1c:00.0/2 hw_addr 5c:a1:1b:5e:43:11 state active

Why you pass "state active" here? That is no-op for VFs.


>+
>+
>+To remove the representors from the system. Change the device to legacy mode.
>+
>+ - Change device to legacy mode::
>+
>+	# devlink dev eswitch set pci/0002:1c:00.0 mode legacy
>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>index 53f14aa944bd..33ec9a7f7c03 100644
>--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>@@ -141,7 +141,56 @@ static const struct devlink_param otx2_dl_params[] = {
> 			     otx2_dl_ucast_flt_cnt_validate),
> };
> 
>+#ifdef CONFIG_RVU_ESWITCH
>+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
>+{
>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>+
>+	if (!otx2_rep_dev(pfvf->pdev))
>+		return -EOPNOTSUPP;
>+
>+	*mode = pfvf->esw_mode;
>+
>+	return 0;
>+}
>+
>+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
>+					 struct netlink_ext_ack *extack)
>+{
>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>+	int ret = 0;
>+
>+	if (!otx2_rep_dev(pfvf->pdev))
>+		return -EOPNOTSUPP;
>+
>+	if (pfvf->esw_mode == mode)
>+		return 0;
>+
>+	switch (mode) {
>+	case DEVLINK_ESWITCH_MODE_LEGACY:
>+		rvu_rep_destroy(pfvf);
>+		break;
>+	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
>+		ret = rvu_rep_create(pfvf, extack);
>+		break;
>+	default:
>+		return -EINVAL;
>+	}
>+
>+	if (!ret)
>+		pfvf->esw_mode = mode;
>+
>+	return ret;
>+}
>+#endif
>+
> static const struct devlink_ops otx2_devlink_ops = {
>+#ifdef CONFIG_RVU_ESWITCH
>+	.eswitch_mode_get = otx2_devlink_eswitch_mode_get,
>+	.eswitch_mode_set = otx2_devlink_eswitch_mode_set,
>+#endif
> };
> 
> int otx2_register_dl(struct otx2_nic *pfvf)
>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>index b0a0080e50d7..6ea5b4904a7c 100644
>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>@@ -28,6 +28,164 @@ MODULE_DESCRIPTION(DRV_STRING);
> MODULE_LICENSE("GPL");
> MODULE_DEVICE_TABLE(pci, rvu_rep_id_table);
> 
>+static int rvu_rep_napi_init(struct otx2_nic *priv,
>+			     struct netlink_ext_ack *extack)
>+{
>+	struct otx2_qset *qset = &priv->qset;
>+	struct otx2_cq_poll *cq_poll = NULL;
>+	struct otx2_hw *hw = &priv->hw;
>+	int err = 0, qidx, vec;
>+	char *irq_name;
>+
>+	qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
>+	if (!qset->napi)
>+		return -ENOMEM;
>+
>+	/* Register NAPI handler */
>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>+		cq_poll = &qset->napi[qidx];
>+		cq_poll->cint_idx = qidx;
>+		cq_poll->cq_ids[CQ_RX] =
>+			(qidx <  hw->rx_queues) ? qidx : CINT_INVALID_CQ;
>+		cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
>+					  qidx + hw->rx_queues :
>+					  CINT_INVALID_CQ;
>+		cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
>+		cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
>+
>+		cq_poll->dev = (void *)priv;
>+		netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
>+			       otx2_napi_handler);
>+		napi_enable(&cq_poll->napi);
>+	}
>+	/* Register CQ IRQ handlers */
>+	vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>+		irq_name = &hw->irq_name[vec * NAME_SIZE];
>+
>+		snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
>+
>+		err = request_irq(pci_irq_vector(priv->pdev, vec),
>+				  otx2_cq_intr_handler, 0, irq_name,
>+				  &qset->napi[qidx]);
>+		if (err) {
>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>+					       "RVU REP IRQ registration failed for CQ%d",
>+					       qidx);
>+			goto err_free_cints;
>+		}
>+		vec++;
>+
>+		/* Enable CQ IRQ */
>+		otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
>+	}
>+	priv->flags &= ~OTX2_FLAG_INTF_DOWN;
>+	return 0;
>+
>+err_free_cints:
>+	otx2_free_cints(priv, qidx);
>+	otx2_disable_napi(priv);
>+	return err;
>+}
>+
>+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv)
>+{
>+	struct otx2_qset *qset = &priv->qset;
>+	struct otx2_cq_poll *cq_poll = NULL;
>+	int qidx, vec;
>+
>+	/* Cleanup CQ NAPI and IRQ */
>+	vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
>+	for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
>+		/* Disable interrupt */
>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0));
>+
>+		synchronize_irq(pci_irq_vector(priv->pdev, vec));
>+
>+		cq_poll = &qset->napi[qidx];
>+		napi_synchronize(&cq_poll->napi);
>+		vec++;
>+	}
>+	otx2_free_cints(priv, priv->hw.cint_cnt);
>+	otx2_disable_napi(priv);
>+}
>+
>+void rvu_rep_destroy(struct otx2_nic *priv)
>+{
>+	struct rep_dev *rep;
>+	int rep_id;
>+
>+	priv->flags |= OTX2_FLAG_INTF_DOWN;
>+	rvu_rep_free_cq_rsrc(priv);
>+	for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
>+		rep = priv->reps[rep_id];
>+		unregister_netdev(rep->netdev);
>+		free_netdev(rep->netdev);
>+	}
>+	kfree(priv->reps);
>+}
>+
>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack)
>+{
>+	int rep_cnt = priv->rep_cnt;
>+	struct net_device *ndev;
>+	struct rep_dev *rep;
>+	int rep_id, err;
>+	u16 pcifunc;
>+
>+	priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
>+	if (!priv->reps)
>+		return -ENOMEM;
>+
>+	for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
>+		ndev = alloc_etherdev(sizeof(*rep));
>+		if (!ndev) {
>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>+					       "PFVF representor:%d creation failed",
>+					       rep_id);
>+			err = -ENOMEM;
>+			goto exit;
>+		}
>+
>+		rep = netdev_priv(ndev);
>+		priv->reps[rep_id] = rep;
>+		rep->mdev = priv;
>+		rep->netdev = ndev;
>+		rep->rep_id = rep_id;
>+
>+		ndev->min_mtu = OTX2_MIN_MTU;
>+		ndev->max_mtu = priv->hw.max_mtu;
>+		pcifunc = priv->rep_pf_map[rep_id];
>+		rep->pcifunc = pcifunc;
>+
>+		snprintf(ndev->name, sizeof(ndev->name), "r%dp%d", rep_id,
>+			 rvu_get_pf(pcifunc));
>+
>+		eth_hw_addr_random(ndev);
>+		err = register_netdev(ndev);

I don't follow. You just create netdevices, no devlink ports. That is
inconsistent with your documentation above.


>+		if (err) {
>+			NL_SET_ERR_MSG_MOD(extack,
>+					   "PFVF reprentator registration failed");
>+			free_netdev(ndev);
>+			goto exit;
>+		}
>+	}
>+	err = rvu_rep_napi_init(priv, extack);
>+	if (err)
>+		goto exit;
>+
>+	return 0;
>+exit:
>+	while (--rep_id >= 0) {
>+		rep = priv->reps[rep_id];
>+		unregister_netdev(rep->netdev);
>+		free_netdev(rep->netdev);
>+	}
>+	kfree(priv->reps);
>+	return err;
>+}
>+
> static void rvu_rep_rsrc_free(struct otx2_nic *priv)
> {
> 	struct otx2_qset *qset = &priv->qset;
>@@ -167,6 +325,10 @@ static int rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> 	if (err)
> 		goto err_detach_rsrc;
> 
>+	err = otx2_register_dl(priv);
>+	if (err)
>+		goto err_detach_rsrc;
>+
> 	return 0;
> 
> err_detach_rsrc:
>@@ -188,6 +350,9 @@ static void rvu_rep_remove(struct pci_dev *pdev)
> {
> 	struct otx2_nic *priv = pci_get_drvdata(pdev);
> 
>+	otx2_unregister_dl(priv);
>+	if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
>+		rvu_rep_destroy(priv);
> 	rvu_rep_rsrc_free(priv);
> 	otx2_detach_resources(&priv->mbox);
> 	if (priv->hw.lmt_info)
>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>index 565e75628df2..c04874c4d4c6 100644
>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>@@ -28,4 +28,7 @@ static inline bool otx2_rep_dev(struct pci_dev *pdev)
> {
> 	return pdev->device == PCI_DEVID_RVU_REP;
> }
>+
>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack);
>+void rvu_rep_destroy(struct otx2_nic *priv);
> #endif /* REP_H */
>-- 
>2.25.1
>
>
Geetha sowjanya Aug. 16, 2024, 1:36 p.m. UTC | #2
>-----Original Message-----
>From: Jiri Pirko <jiri@resnulli.us>
>Sent: Thursday, August 8, 2024 9:22 PM
>To: Geethasowjanya Akula <gakula@marvell.com>
>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; kuba@kernel.org;
>davem@davemloft.net; pabeni@redhat.com; edumazet@google.com; Sunil
>Kovvuri Goutham <sgoutham@marvell.com>; Subbaraya Sundeep Bhatta
><sbhatta@marvell.com>; Hariprasad Kelam <hkelam@marvell.com>
>Subject: [EXTERNAL] Re: [net-next PATCH v10 03/11] octeontx2-pf: Create
>representor netdev
>
>Mon, Aug 05, 2024 at 03:18:07PM CEST, gakula@marvell.com wrote:
>>Adds initial devlink support to set/get the switchdev mode.
>>Representor netdevs are created for each rvu devices when the switch
>>mode is set to 'switchdev'. These netdevs are be used to control and
>>configure VFs.
>>
>>Signed-off-by: Geetha sowjanya <gakula@marvell.com>
>>Reviewed-by: Simon Horman <horms@kernel.org>
>>---
>> .../ethernet/marvell/octeontx2.rst            |  85 +++++++++
>> .../marvell/octeontx2/nic/otx2_devlink.c      |  49 ++++++
>> .../net/ethernet/marvell/octeontx2/nic/rep.c  | 165 ++++++++++++++++++
>> .../net/ethernet/marvell/octeontx2/nic/rep.h  |   3 +
>> 4 files changed, 302 insertions(+)
>>
>>diff --git
>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>t
>>b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>t index 1e196cb9ce25..4eb4e6788ffc 100644
>>---
>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>t
>>+++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx
>>+++ 2.rst
>>@@ -14,6 +14,7 @@ Contents
>> - `Basic packet flow`_
>> - `Devlink health reporters`_
>> - `Quality of service`_
>>+- `RVU representors`_
>>
>> Overview
>> ========
>>@@ -340,3 +341,87 @@ Setup HTB offload
>>         # tc class add dev <interface> parent 1: classid 1:2 htb rate
>>10Gbit prio 2 quantum 188416
>>
>>         # tc class add dev <interface> parent 1: classid 1:3 htb rate
>> 10Gbit prio 2 quantum 32768
>>+
>>+
>>+RVU Representors
>>+================
>>+
>>+RVU representor driver adds support for creation of representor
>>+devices for RVU PFs' VFs in the system. Representor devices are
>>+created when user enables the switchdev mode.
>>+Switchdev mode can be enabled either before or after setting up SRIOV
>numVFs.
>>+All representor devices share a single NIXLF but each has a dedicated
>>+queue (ie RQ/SQ. RVU PF representor driver registers a separate netdev
>>+for each RQ/SQ queue pair.
>>+
>>+HW doesn't have a in-built switch which can do L2 learning and forward
>>+pkts between representee and representor. Hence packet patch between
>>+representee and it's representor is achieved by setting up appropriate NPC
>MCAM filters.
>>+Transmit packets matching these filters will be loopbacked through
>>+hardware loopback channel/interface (ie instead of sending them out of
>MAC interface).
>>+Which will again match the installed filters and will be forwarded.
>>+This way representee => representor and representor => representee
>>+packet path is achieved.These rules get installed when representors
>>+are created and gets active/deactivate based on the representor/representee
>interface state.
>>+
>>+Usage example:
>>+
>>+ - List of devices on the system before vfs are created::
>>+
>>+	# devlink dev
>>+	pci/0002:02:00.0
>>+	pci/0002:1c:00.0
>>+
>>+- Change device to switchdev mode::
>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
>>+
>>+ - List the devices on the system::
>>+
>>+	# ip link show
>>+
>>+Sample output::
>>+
>>+	# ip link show
>>+	eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>mode DEFAULT group default qlen 1000 link/ether 7e:58:2d:b6:97:51 brd
>ff:ff:ff:ff:ff:ff
>>+	r0p1v0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>mode DEFAULT group default qlen 1000 link/ether 7e:5a:66:ea:fe:d6 brd
>ff:ff:ff:ff:ff:ff
>>+	r1p1v1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>mode DEFAULT group default qlen 1000 link/ether de:29:be:10:9e:bf brd
>ff:ff:ff:ff:ff:ff
>>+	r2p1v2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>mode DEFAULT group default qlen 1000 link/ether 4a:12:c7:a2:66:ad brd
>ff:ff:ff:ff:ff:ff
>>+	r3p1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>mode
>>+DEFAULT group default qlen 1000 link/ether c2:b8:a8:0e:73:fd brd
>>+ff:ff:ff:ff:ff:ff
>>+
>>+
>>+RVU representors can be managed using devlink ports (see
>>+:ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`)
>interface.
>>+
>>+ - Show devlink ports of representors::
>>+
>>+	# devlink port
>>+
>>+Sample output::
>>+
>>+	pci/0002:1c:00.0/0: type eth netdev r0p1v0 flavour pcipf controller 0
>pfnum 1 vfnum 0 external false splittable false
>>+	pci/0002:1c:00.0/1: type eth netdev r1p1v1 flavour pcivf controller 0
>pfnum 1 vfnum 1 external false splittable false
>>+	pci/0002:1c:00.0/2: type eth netdev r2p1v2 flavour pcivf controller 0
>pfnum 1 vfnum 2 external false splittable false
>>+	pci/0002:1c:00.0/3: type eth netdev r3p1v3 flavour pcivf controller 0
>>+pfnum 1 vfnum 3 external false splittable false
>>+
>>+Function attributes
>>+===================
>>+
>>+The RVU representor support function attributes for representors Port
>>+function configuration of the representors are supported through devlink
>eswitch port.
>>+
>>+MAC address setup
>>+-----------------
>>+
>>+RVU representor driver support devlink port function attr mechanism to
>>+setup MAC address. (refer to
>>+Documentation/networking/devlink/devlink-port.rst)
>>+
>>+ - To setup MAC address for port 2::
>>+
>>+	# devlink port function set  pci/0002:1c:00.0/2 hw_addr
>>+5c:a1:1b:5e:43:11 state active
>
>Why you pass "state active" here? That is no-op for VFs.
>
>
>>+
>>+
>>+To remove the representors from the system. Change the device to legacy
>mode.
>>+
>>+ - Change device to legacy mode::
>>+
>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode legacy
>>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>index 53f14aa944bd..33ec9a7f7c03 100644
>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>@@ -141,7 +141,56 @@ static const struct devlink_param otx2_dl_params[] =
>{
>> 			     otx2_dl_ucast_flt_cnt_validate),  };
>>
>>+#ifdef CONFIG_RVU_ESWITCH
>>+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16
>>+*mode) {
>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>+
>>+	if (!otx2_rep_dev(pfvf->pdev))
>>+		return -EOPNOTSUPP;
>>+
>>+	*mode = pfvf->esw_mode;
>>+
>>+	return 0;
>>+}
>>+
>>+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
>>+					 struct netlink_ext_ack *extack)
>>+{
>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>+	int ret = 0;
>>+
>>+	if (!otx2_rep_dev(pfvf->pdev))
>>+		return -EOPNOTSUPP;
>>+
>>+	if (pfvf->esw_mode == mode)
>>+		return 0;
>>+
>>+	switch (mode) {
>>+	case DEVLINK_ESWITCH_MODE_LEGACY:
>>+		rvu_rep_destroy(pfvf);
>>+		break;
>>+	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
>>+		ret = rvu_rep_create(pfvf, extack);
>>+		break;
>>+	default:
>>+		return -EINVAL;
>>+	}
>>+
>>+	if (!ret)
>>+		pfvf->esw_mode = mode;
>>+
>>+	return ret;
>>+}
>>+#endif
>>+
>> static const struct devlink_ops otx2_devlink_ops = {
>>+#ifdef CONFIG_RVU_ESWITCH
>>+	.eswitch_mode_get = otx2_devlink_eswitch_mode_get,
>>+	.eswitch_mode_set = otx2_devlink_eswitch_mode_set, #endif
>> };
>>
>> int otx2_register_dl(struct otx2_nic *pfvf) diff --git
>>a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>index b0a0080e50d7..6ea5b4904a7c 100644
>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>@@ -28,6 +28,164 @@ MODULE_DESCRIPTION(DRV_STRING);
>>MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, rvu_rep_id_table);
>>
>>+static int rvu_rep_napi_init(struct otx2_nic *priv,
>>+			     struct netlink_ext_ack *extack) {
>>+	struct otx2_qset *qset = &priv->qset;
>>+	struct otx2_cq_poll *cq_poll = NULL;
>>+	struct otx2_hw *hw = &priv->hw;
>>+	int err = 0, qidx, vec;
>>+	char *irq_name;
>>+
>>+	qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
>>+	if (!qset->napi)
>>+		return -ENOMEM;
>>+
>>+	/* Register NAPI handler */
>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>+		cq_poll = &qset->napi[qidx];
>>+		cq_poll->cint_idx = qidx;
>>+		cq_poll->cq_ids[CQ_RX] =
>>+			(qidx <  hw->rx_queues) ? qidx : CINT_INVALID_CQ;
>>+		cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
>>+					  qidx + hw->rx_queues :
>>+					  CINT_INVALID_CQ;
>>+		cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
>>+		cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
>>+
>>+		cq_poll->dev = (void *)priv;
>>+		netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
>>+			       otx2_napi_handler);
>>+		napi_enable(&cq_poll->napi);
>>+	}
>>+	/* Register CQ IRQ handlers */
>>+	vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>+		irq_name = &hw->irq_name[vec * NAME_SIZE];
>>+
>>+		snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
>>+
>>+		err = request_irq(pci_irq_vector(priv->pdev, vec),
>>+				  otx2_cq_intr_handler, 0, irq_name,
>>+				  &qset->napi[qidx]);
>>+		if (err) {
>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>+					       "RVU REP IRQ registration failed for
>CQ%d",
>>+					       qidx);
>>+			goto err_free_cints;
>>+		}
>>+		vec++;
>>+
>>+		/* Enable CQ IRQ */
>>+		otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
>>+	}
>>+	priv->flags &= ~OTX2_FLAG_INTF_DOWN;
>>+	return 0;
>>+
>>+err_free_cints:
>>+	otx2_free_cints(priv, qidx);
>>+	otx2_disable_napi(priv);
>>+	return err;
>>+}
>>+
>>+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv) {
>>+	struct otx2_qset *qset = &priv->qset;
>>+	struct otx2_cq_poll *cq_poll = NULL;
>>+	int qidx, vec;
>>+
>>+	/* Cleanup CQ NAPI and IRQ */
>>+	vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
>>+	for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
>>+		/* Disable interrupt */
>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx),
>BIT_ULL(0));
>>+
>>+		synchronize_irq(pci_irq_vector(priv->pdev, vec));
>>+
>>+		cq_poll = &qset->napi[qidx];
>>+		napi_synchronize(&cq_poll->napi);
>>+		vec++;
>>+	}
>>+	otx2_free_cints(priv, priv->hw.cint_cnt);
>>+	otx2_disable_napi(priv);
>>+}
>>+
>>+void rvu_rep_destroy(struct otx2_nic *priv) {
>>+	struct rep_dev *rep;
>>+	int rep_id;
>>+
>>+	priv->flags |= OTX2_FLAG_INTF_DOWN;
>>+	rvu_rep_free_cq_rsrc(priv);
>>+	for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
>>+		rep = priv->reps[rep_id];
>>+		unregister_netdev(rep->netdev);
>>+		free_netdev(rep->netdev);
>>+	}
>>+	kfree(priv->reps);
>>+}
>>+
>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>+*extack) {
>>+	int rep_cnt = priv->rep_cnt;
>>+	struct net_device *ndev;
>>+	struct rep_dev *rep;
>>+	int rep_id, err;
>>+	u16 pcifunc;
>>+
>>+	priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
>>+	if (!priv->reps)
>>+		return -ENOMEM;
>>+
>>+	for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
>>+		ndev = alloc_etherdev(sizeof(*rep));
>>+		if (!ndev) {
>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>+					       "PFVF representor:%d creation
>failed",
>>+					       rep_id);
>>+			err = -ENOMEM;
>>+			goto exit;
>>+		}
>>+
>>+		rep = netdev_priv(ndev);
>>+		priv->reps[rep_id] = rep;
>>+		rep->mdev = priv;
>>+		rep->netdev = ndev;
>>+		rep->rep_id = rep_id;
>>+
>>+		ndev->min_mtu = OTX2_MIN_MTU;
>>+		ndev->max_mtu = priv->hw.max_mtu;
>>+		pcifunc = priv->rep_pf_map[rep_id];
>>+		rep->pcifunc = pcifunc;
>>+
>>+		snprintf(ndev->name, sizeof(ndev->name), "r%dp%d", rep_id,
>>+			 rvu_get_pf(pcifunc));
>>+
>>+		eth_hw_addr_random(ndev);
>>+		err = register_netdev(ndev);
>
>I don't follow. You just create netdevices, no devlink ports. That is inconsistent
>with your documentation above.
Creation on devlink port is implemented in patch 10 " octeontx2-pf: Add devlink port support".
>
>
>>+		if (err) {
>>+			NL_SET_ERR_MSG_MOD(extack,
>>+					   "PFVF reprentator registration
>failed");
>>+			free_netdev(ndev);
>>+			goto exit;
>>+		}
>>+	}
>>+	err = rvu_rep_napi_init(priv, extack);
>>+	if (err)
>>+		goto exit;
>>+
>>+	return 0;
>>+exit:
>>+	while (--rep_id >= 0) {
>>+		rep = priv->reps[rep_id];
>>+		unregister_netdev(rep->netdev);
>>+		free_netdev(rep->netdev);
>>+	}
>>+	kfree(priv->reps);
>>+	return err;
>>+}
>>+
>> static void rvu_rep_rsrc_free(struct otx2_nic *priv)  {
>> 	struct otx2_qset *qset = &priv->qset; @@ -167,6 +325,10 @@ static int
>>rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> 	if (err)
>> 		goto err_detach_rsrc;
>>
>>+	err = otx2_register_dl(priv);
>>+	if (err)
>>+		goto err_detach_rsrc;
>>+
>> 	return 0;
>>
>> err_detach_rsrc:
>>@@ -188,6 +350,9 @@ static void rvu_rep_remove(struct pci_dev *pdev)  {
>> 	struct otx2_nic *priv = pci_get_drvdata(pdev);
>>
>>+	otx2_unregister_dl(priv);
>>+	if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
>>+		rvu_rep_destroy(priv);
>> 	rvu_rep_rsrc_free(priv);
>> 	otx2_detach_resources(&priv->mbox);
>> 	if (priv->hw.lmt_info)
>>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>index 565e75628df2..c04874c4d4c6 100644
>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>@@ -28,4 +28,7 @@ static inline bool otx2_rep_dev(struct pci_dev *pdev)
>>{
>> 	return pdev->device == PCI_DEVID_RVU_REP;  }
>>+
>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>+*extack); void rvu_rep_destroy(struct otx2_nic *priv);
>> #endif /* REP_H */
>>--
>>2.25.1
>>
>>
Jiri Pirko Aug. 16, 2024, 2:12 p.m. UTC | #3
Fri, Aug 16, 2024 at 03:36:12PM CEST, gakula@marvell.com wrote:
>
>
>>-----Original Message-----
>>From: Jiri Pirko <jiri@resnulli.us>
>>Sent: Thursday, August 8, 2024 9:22 PM
>>To: Geethasowjanya Akula <gakula@marvell.com>
>>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; kuba@kernel.org;
>>davem@davemloft.net; pabeni@redhat.com; edumazet@google.com; Sunil
>>Kovvuri Goutham <sgoutham@marvell.com>; Subbaraya Sundeep Bhatta
>><sbhatta@marvell.com>; Hariprasad Kelam <hkelam@marvell.com>
>>Subject: [EXTERNAL] Re: [net-next PATCH v10 03/11] octeontx2-pf: Create
>>representor netdev
>>
>>Mon, Aug 05, 2024 at 03:18:07PM CEST, gakula@marvell.com wrote:
>>>Adds initial devlink support to set/get the switchdev mode.
>>>Representor netdevs are created for each rvu devices when the switch
>>>mode is set to 'switchdev'. These netdevs are be used to control and
>>>configure VFs.
>>>
>>>Signed-off-by: Geetha sowjanya <gakula@marvell.com>
>>>Reviewed-by: Simon Horman <horms@kernel.org>
>>>---
>>> .../ethernet/marvell/octeontx2.rst            |  85 +++++++++
>>> .../marvell/octeontx2/nic/otx2_devlink.c      |  49 ++++++
>>> .../net/ethernet/marvell/octeontx2/nic/rep.c  | 165 ++++++++++++++++++
>>> .../net/ethernet/marvell/octeontx2/nic/rep.h  |   3 +
>>> 4 files changed, 302 insertions(+)
>>>
>>>diff --git
>>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>>t
>>>b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>>t index 1e196cb9ce25..4eb4e6788ffc 100644
>>>---
>>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rs
>>>t
>>>+++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx
>>>+++ 2.rst
>>>@@ -14,6 +14,7 @@ Contents
>>> - `Basic packet flow`_
>>> - `Devlink health reporters`_
>>> - `Quality of service`_
>>>+- `RVU representors`_
>>>
>>> Overview
>>> ========
>>>@@ -340,3 +341,87 @@ Setup HTB offload
>>>         # tc class add dev <interface> parent 1: classid 1:2 htb rate
>>>10Gbit prio 2 quantum 188416
>>>
>>>         # tc class add dev <interface> parent 1: classid 1:3 htb rate
>>> 10Gbit prio 2 quantum 32768
>>>+
>>>+
>>>+RVU Representors
>>>+================
>>>+
>>>+RVU representor driver adds support for creation of representor
>>>+devices for RVU PFs' VFs in the system. Representor devices are
>>>+created when user enables the switchdev mode.
>>>+Switchdev mode can be enabled either before or after setting up SRIOV
>>numVFs.
>>>+All representor devices share a single NIXLF but each has a dedicated
>>>+queue (ie RQ/SQ. RVU PF representor driver registers a separate netdev
>>>+for each RQ/SQ queue pair.
>>>+
>>>+HW doesn't have a in-built switch which can do L2 learning and forward
>>>+pkts between representee and representor. Hence packet patch between
>>>+representee and it's representor is achieved by setting up appropriate NPC
>>MCAM filters.
>>>+Transmit packets matching these filters will be loopbacked through
>>>+hardware loopback channel/interface (ie instead of sending them out of
>>MAC interface).
>>>+Which will again match the installed filters and will be forwarded.
>>>+This way representee => representor and representor => representee
>>>+packet path is achieved.These rules get installed when representors
>>>+are created and gets active/deactivate based on the representor/representee
>>interface state.
>>>+
>>>+Usage example:
>>>+
>>>+ - List of devices on the system before vfs are created::
>>>+
>>>+	# devlink dev
>>>+	pci/0002:02:00.0
>>>+	pci/0002:1c:00.0
>>>+
>>>+- Change device to switchdev mode::
>>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
>>>+
>>>+ - List the devices on the system::
>>>+
>>>+	# ip link show
>>>+
>>>+Sample output::
>>>+
>>>+	# ip link show
>>>+	eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>mode DEFAULT group default qlen 1000 link/ether 7e:58:2d:b6:97:51 brd
>>ff:ff:ff:ff:ff:ff
>>>+	r0p1v0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>mode DEFAULT group default qlen 1000 link/ether 7e:5a:66:ea:fe:d6 brd
>>ff:ff:ff:ff:ff:ff
>>>+	r1p1v1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>mode DEFAULT group default qlen 1000 link/ether de:29:be:10:9e:bf brd
>>ff:ff:ff:ff:ff:ff
>>>+	r2p1v2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>mode DEFAULT group default qlen 1000 link/ether 4a:12:c7:a2:66:ad brd
>>ff:ff:ff:ff:ff:ff
>>>+	r3p1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>mode
>>>+DEFAULT group default qlen 1000 link/ether c2:b8:a8:0e:73:fd brd
>>>+ff:ff:ff:ff:ff:ff
>>>+
>>>+
>>>+RVU representors can be managed using devlink ports (see
>>>+:ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`)
>>interface.
>>>+
>>>+ - Show devlink ports of representors::
>>>+
>>>+	# devlink port
>>>+
>>>+Sample output::
>>>+
>>>+	pci/0002:1c:00.0/0: type eth netdev r0p1v0 flavour pcipf controller 0
>>pfnum 1 vfnum 0 external false splittable false
>>>+	pci/0002:1c:00.0/1: type eth netdev r1p1v1 flavour pcivf controller 0
>>pfnum 1 vfnum 1 external false splittable false
>>>+	pci/0002:1c:00.0/2: type eth netdev r2p1v2 flavour pcivf controller 0
>>pfnum 1 vfnum 2 external false splittable false
>>>+	pci/0002:1c:00.0/3: type eth netdev r3p1v3 flavour pcivf controller 0
>>>+pfnum 1 vfnum 3 external false splittable false
>>>+
>>>+Function attributes
>>>+===================
>>>+
>>>+The RVU representor support function attributes for representors Port
>>>+function configuration of the representors are supported through devlink
>>eswitch port.
>>>+
>>>+MAC address setup
>>>+-----------------
>>>+
>>>+RVU representor driver support devlink port function attr mechanism to
>>>+setup MAC address. (refer to
>>>+Documentation/networking/devlink/devlink-port.rst)
>>>+
>>>+ - To setup MAC address for port 2::
>>>+
>>>+	# devlink port function set  pci/0002:1c:00.0/2 hw_addr
>>>+5c:a1:1b:5e:43:11 state active
>>
>>Why you pass "state active" here? That is no-op for VFs.
>>
>>
>>>+
>>>+
>>>+To remove the representors from the system. Change the device to legacy
>>mode.
>>>+
>>>+ - Change device to legacy mode::
>>>+
>>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode legacy
>>>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>index 53f14aa944bd..33ec9a7f7c03 100644
>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>@@ -141,7 +141,56 @@ static const struct devlink_param otx2_dl_params[] =
>>{
>>> 			     otx2_dl_ucast_flt_cnt_validate),  };
>>>
>>>+#ifdef CONFIG_RVU_ESWITCH
>>>+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16
>>>+*mode) {
>>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>>+
>>>+	if (!otx2_rep_dev(pfvf->pdev))
>>>+		return -EOPNOTSUPP;
>>>+
>>>+	*mode = pfvf->esw_mode;
>>>+
>>>+	return 0;
>>>+}
>>>+
>>>+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
>>>+					 struct netlink_ext_ack *extack)
>>>+{
>>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>>+	int ret = 0;
>>>+
>>>+	if (!otx2_rep_dev(pfvf->pdev))
>>>+		return -EOPNOTSUPP;
>>>+
>>>+	if (pfvf->esw_mode == mode)
>>>+		return 0;
>>>+
>>>+	switch (mode) {
>>>+	case DEVLINK_ESWITCH_MODE_LEGACY:
>>>+		rvu_rep_destroy(pfvf);
>>>+		break;
>>>+	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
>>>+		ret = rvu_rep_create(pfvf, extack);
>>>+		break;
>>>+	default:
>>>+		return -EINVAL;
>>>+	}
>>>+
>>>+	if (!ret)
>>>+		pfvf->esw_mode = mode;
>>>+
>>>+	return ret;
>>>+}
>>>+#endif
>>>+
>>> static const struct devlink_ops otx2_devlink_ops = {
>>>+#ifdef CONFIG_RVU_ESWITCH
>>>+	.eswitch_mode_get = otx2_devlink_eswitch_mode_get,
>>>+	.eswitch_mode_set = otx2_devlink_eswitch_mode_set, #endif
>>> };
>>>
>>> int otx2_register_dl(struct otx2_nic *pfvf) diff --git
>>>a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>index b0a0080e50d7..6ea5b4904a7c 100644
>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>@@ -28,6 +28,164 @@ MODULE_DESCRIPTION(DRV_STRING);
>>>MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, rvu_rep_id_table);
>>>
>>>+static int rvu_rep_napi_init(struct otx2_nic *priv,
>>>+			     struct netlink_ext_ack *extack) {
>>>+	struct otx2_qset *qset = &priv->qset;
>>>+	struct otx2_cq_poll *cq_poll = NULL;
>>>+	struct otx2_hw *hw = &priv->hw;
>>>+	int err = 0, qidx, vec;
>>>+	char *irq_name;
>>>+
>>>+	qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
>>>+	if (!qset->napi)
>>>+		return -ENOMEM;
>>>+
>>>+	/* Register NAPI handler */
>>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>>+		cq_poll = &qset->napi[qidx];
>>>+		cq_poll->cint_idx = qidx;
>>>+		cq_poll->cq_ids[CQ_RX] =
>>>+			(qidx <  hw->rx_queues) ? qidx : CINT_INVALID_CQ;
>>>+		cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
>>>+					  qidx + hw->rx_queues :
>>>+					  CINT_INVALID_CQ;
>>>+		cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
>>>+		cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
>>>+
>>>+		cq_poll->dev = (void *)priv;
>>>+		netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
>>>+			       otx2_napi_handler);
>>>+		napi_enable(&cq_poll->napi);
>>>+	}
>>>+	/* Register CQ IRQ handlers */
>>>+	vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
>>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>>+		irq_name = &hw->irq_name[vec * NAME_SIZE];
>>>+
>>>+		snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
>>>+
>>>+		err = request_irq(pci_irq_vector(priv->pdev, vec),
>>>+				  otx2_cq_intr_handler, 0, irq_name,
>>>+				  &qset->napi[qidx]);
>>>+		if (err) {
>>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>>+					       "RVU REP IRQ registration failed for
>>CQ%d",
>>>+					       qidx);
>>>+			goto err_free_cints;
>>>+		}
>>>+		vec++;
>>>+
>>>+		/* Enable CQ IRQ */
>>>+		otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
>>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
>>>+	}
>>>+	priv->flags &= ~OTX2_FLAG_INTF_DOWN;
>>>+	return 0;
>>>+
>>>+err_free_cints:
>>>+	otx2_free_cints(priv, qidx);
>>>+	otx2_disable_napi(priv);
>>>+	return err;
>>>+}
>>>+
>>>+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv) {
>>>+	struct otx2_qset *qset = &priv->qset;
>>>+	struct otx2_cq_poll *cq_poll = NULL;
>>>+	int qidx, vec;
>>>+
>>>+	/* Cleanup CQ NAPI and IRQ */
>>>+	vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
>>>+	for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
>>>+		/* Disable interrupt */
>>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx),
>>BIT_ULL(0));
>>>+
>>>+		synchronize_irq(pci_irq_vector(priv->pdev, vec));
>>>+
>>>+		cq_poll = &qset->napi[qidx];
>>>+		napi_synchronize(&cq_poll->napi);
>>>+		vec++;
>>>+	}
>>>+	otx2_free_cints(priv, priv->hw.cint_cnt);
>>>+	otx2_disable_napi(priv);
>>>+}
>>>+
>>>+void rvu_rep_destroy(struct otx2_nic *priv) {
>>>+	struct rep_dev *rep;
>>>+	int rep_id;
>>>+
>>>+	priv->flags |= OTX2_FLAG_INTF_DOWN;
>>>+	rvu_rep_free_cq_rsrc(priv);
>>>+	for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
>>>+		rep = priv->reps[rep_id];
>>>+		unregister_netdev(rep->netdev);
>>>+		free_netdev(rep->netdev);
>>>+	}
>>>+	kfree(priv->reps);
>>>+}
>>>+
>>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>>+*extack) {
>>>+	int rep_cnt = priv->rep_cnt;
>>>+	struct net_device *ndev;
>>>+	struct rep_dev *rep;
>>>+	int rep_id, err;
>>>+	u16 pcifunc;
>>>+
>>>+	priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
>>>+	if (!priv->reps)
>>>+		return -ENOMEM;
>>>+
>>>+	for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
>>>+		ndev = alloc_etherdev(sizeof(*rep));
>>>+		if (!ndev) {
>>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>>+					       "PFVF representor:%d creation
>>failed",
>>>+					       rep_id);
>>>+			err = -ENOMEM;
>>>+			goto exit;
>>>+		}
>>>+
>>>+		rep = netdev_priv(ndev);
>>>+		priv->reps[rep_id] = rep;
>>>+		rep->mdev = priv;
>>>+		rep->netdev = ndev;
>>>+		rep->rep_id = rep_id;
>>>+
>>>+		ndev->min_mtu = OTX2_MIN_MTU;
>>>+		ndev->max_mtu = priv->hw.max_mtu;
>>>+		pcifunc = priv->rep_pf_map[rep_id];
>>>+		rep->pcifunc = pcifunc;
>>>+
>>>+		snprintf(ndev->name, sizeof(ndev->name), "r%dp%d", rep_id,
>>>+			 rvu_get_pf(pcifunc));
>>>+
>>>+		eth_hw_addr_random(ndev);
>>>+		err = register_netdev(ndev);
>>
>>I don't follow. You just create netdevices, no devlink ports. That is inconsistent
>>with your documentation above.
>Creation on devlink port is implemented in patch 10 " octeontx2-pf: Add devlink port support".

So adjust the docs here to be consistent with the code and add the parts
of documentation alonside with the support in patch 10.


>>
>>
>>>+		if (err) {
>>>+			NL_SET_ERR_MSG_MOD(extack,
>>>+					   "PFVF reprentator registration
>>failed");
>>>+			free_netdev(ndev);
>>>+			goto exit;
>>>+		}
>>>+	}
>>>+	err = rvu_rep_napi_init(priv, extack);
>>>+	if (err)
>>>+		goto exit;
>>>+
>>>+	return 0;
>>>+exit:
>>>+	while (--rep_id >= 0) {
>>>+		rep = priv->reps[rep_id];
>>>+		unregister_netdev(rep->netdev);
>>>+		free_netdev(rep->netdev);
>>>+	}
>>>+	kfree(priv->reps);
>>>+	return err;
>>>+}
>>>+
>>> static void rvu_rep_rsrc_free(struct otx2_nic *priv)  {
>>> 	struct otx2_qset *qset = &priv->qset; @@ -167,6 +325,10 @@ static int
>>>rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>> 	if (err)
>>> 		goto err_detach_rsrc;
>>>
>>>+	err = otx2_register_dl(priv);
>>>+	if (err)
>>>+		goto err_detach_rsrc;
>>>+
>>> 	return 0;
>>>
>>> err_detach_rsrc:
>>>@@ -188,6 +350,9 @@ static void rvu_rep_remove(struct pci_dev *pdev)  {
>>> 	struct otx2_nic *priv = pci_get_drvdata(pdev);
>>>
>>>+	otx2_unregister_dl(priv);
>>>+	if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
>>>+		rvu_rep_destroy(priv);
>>> 	rvu_rep_rsrc_free(priv);
>>> 	otx2_detach_resources(&priv->mbox);
>>> 	if (priv->hw.lmt_info)
>>>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>index 565e75628df2..c04874c4d4c6 100644
>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>@@ -28,4 +28,7 @@ static inline bool otx2_rep_dev(struct pci_dev *pdev)
>>>{
>>> 	return pdev->device == PCI_DEVID_RVU_REP;  }
>>>+
>>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>>+*extack); void rvu_rep_destroy(struct otx2_nic *priv);
>>> #endif /* REP_H */
>>>--
>>>2.25.1
>>>
>>>
Geetha sowjanya Aug. 20, 2024, 5:21 a.m. UTC | #4
>-----Original Message-----
>From: Jiri Pirko <jiri@resnulli.us>
>Sent: Friday, August 16, 2024 7:42 PM
>To: Geethasowjanya Akula <gakula@marvell.com>
>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; kuba@kernel.org;
>davem@davemloft.net; pabeni@redhat.com; edumazet@google.com; Sunil
>Kovvuri Goutham <sgoutham@marvell.com>; Subbaraya Sundeep Bhatta
><sbhatta@marvell.com>; Hariprasad Kelam <hkelam@marvell.com>
>Subject: Re: [EXTERNAL] Re: [net-next PATCH v10 03/11] octeontx2-pf: Create
>representor netdev
>
>Fri, Aug 16, 2024 at 03: 36: 12PM CEST, gakula@ marvell. com wrote: > > >>-----
>Original Message----- >>From: Jiri Pirko <jiri@ resnulli. us> >>Sent: Thursday,
>August 8, 2024 9: 22 PM >>To: Geethasowjanya Akula <gakula@ marvell. com>
>>
>>>-----Original Message-----
>>>From: Jiri Pirko <jiri@resnulli.us>
>>>Sent: Thursday, August 8, 2024 9:22 PM
>>>To: Geethasowjanya Akula <gakula@marvell.com>
>>>Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
>>>kuba@kernel.org; davem@davemloft.net; pabeni@redhat.com;
>>>edumazet@google.com; Sunil Kovvuri Goutham <sgoutham@marvell.com>;
>>>Subbaraya Sundeep Bhatta <sbhatta@marvell.com>; Hariprasad Kelam
>>><hkelam@marvell.com>
>>>Subject: [EXTERNAL] Re: [net-next PATCH v10 03/11] octeontx2-pf:
>>>Create representor netdev
>>>
>>>Mon, Aug 05, 2024 at 03:18:07PM CEST, gakula@marvell.com wrote:
>>>>Adds initial devlink support to set/get the switchdev mode.
>>>>Representor netdevs are created for each rvu devices when the switch
>>>>mode is set to 'switchdev'. These netdevs are be used to control and
>>>>configure VFs.
>>>>
>>>>Signed-off-by: Geetha sowjanya <gakula@marvell.com>
>>>>Reviewed-by: Simon Horman <horms@kernel.org>
>>>>---
>>>> .../ethernet/marvell/octeontx2.rst            |  85 +++++++++
>>>> .../marvell/octeontx2/nic/otx2_devlink.c      |  49 ++++++
>>>> .../net/ethernet/marvell/octeontx2/nic/rep.c  | 165 ++++++++++++++++++
>>>> .../net/ethernet/marvell/octeontx2/nic/rep.h  |   3 +
>>>> 4 files changed, 302 insertions(+)
>>>>
>>>>diff --git
>>>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.
>>>>rs
>>>>t
>>>>b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.
>>>>rs t index 1e196cb9ce25..4eb4e6788ffc 100644
>>>>---
>>>>a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.
>>>>rs
>>>>t
>>>>+++
>b/Documentation/networking/device_drivers/ethernet/marvell/octeon
>>>>+++ tx
>>>>+++ 2.rst
>>>>@@ -14,6 +14,7 @@ Contents
>>>> - `Basic packet flow`_
>>>> - `Devlink health reporters`_
>>>> - `Quality of service`_
>>>>+- `RVU representors`_
>>>>
>>>> Overview
>>>> ========
>>>>@@ -340,3 +341,87 @@ Setup HTB offload
>>>>         # tc class add dev <interface> parent 1: classid 1:2 htb
>>>>rate 10Gbit prio 2 quantum 188416
>>>>
>>>>         # tc class add dev <interface> parent 1: classid 1:3 htb
>>>> rate 10Gbit prio 2 quantum 32768
>>>>+
>>>>+
>>>>+RVU Representors
>>>>+================
>>>>+
>>>>+RVU representor driver adds support for creation of representor
>>>>+devices for RVU PFs' VFs in the system. Representor devices are
>>>>+created when user enables the switchdev mode.
>>>>+Switchdev mode can be enabled either before or after setting up
>>>>+SRIOV
>>>numVFs.
>>>>+All representor devices share a single NIXLF but each has a
>>>>+dedicated queue (ie RQ/SQ. RVU PF representor driver registers a
>>>>+separate netdev for each RQ/SQ queue pair.
>>>>+
>>>>+HW doesn't have a in-built switch which can do L2 learning and
>>>>+forward pkts between representee and representor. Hence packet patch
>>>>+between representee and it's representor is achieved by setting up
>>>>+appropriate NPC
>>>MCAM filters.
>>>>+Transmit packets matching these filters will be loopbacked through
>>>>+hardware loopback channel/interface (ie instead of sending them out
>>>>+of
>>>MAC interface).
>>>>+Which will again match the installed filters and will be forwarded.
>>>>+This way representee => representor and representor => representee
>>>>+packet path is achieved.These rules get installed when representors
>>>>+are created and gets active/deactivate based on the
>>>>+representor/representee
>>>interface state.
>>>>+
>>>>+Usage example:
>>>>+
>>>>+ - List of devices on the system before vfs are created::
>>>>+
>>>>+	# devlink dev
>>>>+	pci/0002:02:00.0
>>>>+	pci/0002:1c:00.0
>>>>+
>>>>+- Change device to switchdev mode::
>>>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
>>>>+
>>>>+ - List the devices on the system::
>>>>+
>>>>+	# ip link show
>>>>+
>>>>+Sample output::
>>>>+
>>>>+	# ip link show
>>>>+	eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>>mode DEFAULT group default qlen 1000 link/ether 7e:58:2d:b6:97:51 brd
>>>ff:ff:ff:ff:ff:ff
>>>>+	r0p1v0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>>mode DEFAULT group default qlen 1000 link/ether 7e:5a:66:ea:fe:d6 brd
>>>ff:ff:ff:ff:ff:ff
>>>>+	r1p1v1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>>mode DEFAULT group default qlen 1000 link/ether de:29:be:10:9e:bf brd
>>>ff:ff:ff:ff:ff:ff
>>>>+	r2p1v2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>>mode DEFAULT group default qlen 1000 link/ether 4a:12:c7:a2:66:ad brd
>>>ff:ff:ff:ff:ff:ff
>>>>+	r3p1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
>>>mode
>>>>+DEFAULT group default qlen 1000 link/ether c2:b8:a8:0e:73:fd brd
>>>>+ff:ff:ff:ff:ff:ff
>>>>+
>>>>+
>>>>+RVU representors can be managed using devlink ports (see
>>>>+:ref:`Documentation/networking/devlink/devlink-port.rst
>>>>+<devlink_port>`)
>>>interface.
>>>>+
>>>>+ - Show devlink ports of representors::
>>>>+
>>>>+	# devlink port
>>>>+
>>>>+Sample output::
>>>>+
>>>>+	pci/0002:1c:00.0/0: type eth netdev r0p1v0 flavour pcipf controller
>>>>+0
>>>pfnum 1 vfnum 0 external false splittable false
>>>>+	pci/0002:1c:00.0/1: type eth netdev r1p1v1 flavour pcivf controller
>>>>+0
>>>pfnum 1 vfnum 1 external false splittable false
>>>>+	pci/0002:1c:00.0/2: type eth netdev r2p1v2 flavour pcivf controller
>>>>+0
>>>pfnum 1 vfnum 2 external false splittable false
>>>>+	pci/0002:1c:00.0/3: type eth netdev r3p1v3 flavour pcivf controller
>>>>+0 pfnum 1 vfnum 3 external false splittable false
>>>>+
>>>>+Function attributes
>>>>+===================
>>>>+
>>>>+The RVU representor support function attributes for representors
>>>>+Port function configuration of the representors are supported
>>>>+through devlink
>>>eswitch port.
>>>>+
>>>>+MAC address setup
>>>>+-----------------
>>>>+
>>>>+RVU representor driver support devlink port function attr mechanism
>>>>+to setup MAC address. (refer to
>>>>+Documentation/networking/devlink/devlink-port.rst)
>>>>+
>>>>+ - To setup MAC address for port 2::
>>>>+
>>>>+	# devlink port function set  pci/0002:1c:00.0/2 hw_addr
>>>>+5c:a1:1b:5e:43:11 state active
>>>
>>>Why you pass "state active" here? That is no-op for VFs.
>>>
>>>
>>>>+
>>>>+
>>>>+To remove the representors from the system. Change the device to
>>>>+legacy
>>>mode.
>>>>+
>>>>+ - Change device to legacy mode::
>>>>+
>>>>+	# devlink dev eswitch set pci/0002:1c:00.0 mode legacy
>>>>diff --git
>>>>a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>>b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>>index 53f14aa944bd..33ec9a7f7c03 100644
>>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
>>>>@@ -141,7 +141,56 @@ static const struct devlink_param
>>>>otx2_dl_params[] =
>>>{
>>>> 			     otx2_dl_ucast_flt_cnt_validate),  };
>>>>
>>>>+#ifdef CONFIG_RVU_ESWITCH
>>>>+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink,
>>>>+u16
>>>>+*mode) {
>>>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>>>+
>>>>+	if (!otx2_rep_dev(pfvf->pdev))
>>>>+		return -EOPNOTSUPP;
>>>>+
>>>>+	*mode = pfvf->esw_mode;
>>>>+
>>>>+	return 0;
>>>>+}
>>>>+
>>>>+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16
>mode,
>>>>+					 struct netlink_ext_ack *extack) {
>>>>+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
>>>>+	struct otx2_nic *pfvf = otx2_dl->pfvf;
>>>>+	int ret = 0;
>>>>+
>>>>+	if (!otx2_rep_dev(pfvf->pdev))
>>>>+		return -EOPNOTSUPP;
>>>>+
>>>>+	if (pfvf->esw_mode == mode)
>>>>+		return 0;
>>>>+
>>>>+	switch (mode) {
>>>>+	case DEVLINK_ESWITCH_MODE_LEGACY:
>>>>+		rvu_rep_destroy(pfvf);
>>>>+		break;
>>>>+	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
>>>>+		ret = rvu_rep_create(pfvf, extack);
>>>>+		break;
>>>>+	default:
>>>>+		return -EINVAL;
>>>>+	}
>>>>+
>>>>+	if (!ret)
>>>>+		pfvf->esw_mode = mode;
>>>>+
>>>>+	return ret;
>>>>+}
>>>>+#endif
>>>>+
>>>> static const struct devlink_ops otx2_devlink_ops = {
>>>>+#ifdef CONFIG_RVU_ESWITCH
>>>>+	.eswitch_mode_get = otx2_devlink_eswitch_mode_get,
>>>>+	.eswitch_mode_set = otx2_devlink_eswitch_mode_set, #endif
>>>> };
>>>>
>>>> int otx2_register_dl(struct otx2_nic *pfvf) diff --git
>>>>a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>>index b0a0080e50d7..6ea5b4904a7c 100644
>>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
>>>>@@ -28,6 +28,164 @@ MODULE_DESCRIPTION(DRV_STRING);
>>>>MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci,
>rvu_rep_id_table);
>>>>
>>>>+static int rvu_rep_napi_init(struct otx2_nic *priv,
>>>>+			     struct netlink_ext_ack *extack) {
>>>>+	struct otx2_qset *qset = &priv->qset;
>>>>+	struct otx2_cq_poll *cq_poll = NULL;
>>>>+	struct otx2_hw *hw = &priv->hw;
>>>>+	int err = 0, qidx, vec;
>>>>+	char *irq_name;
>>>>+
>>>>+	qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
>>>>+	if (!qset->napi)
>>>>+		return -ENOMEM;
>>>>+
>>>>+	/* Register NAPI handler */
>>>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>>>+		cq_poll = &qset->napi[qidx];
>>>>+		cq_poll->cint_idx = qidx;
>>>>+		cq_poll->cq_ids[CQ_RX] =
>>>>+			(qidx <  hw->rx_queues) ? qidx : CINT_INVALID_CQ;
>>>>+		cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
>>>>+					  qidx + hw->rx_queues :
>>>>+					  CINT_INVALID_CQ;
>>>>+		cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
>>>>+		cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
>>>>+
>>>>+		cq_poll->dev = (void *)priv;
>>>>+		netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
>>>>+			       otx2_napi_handler);
>>>>+		napi_enable(&cq_poll->napi);
>>>>+	}
>>>>+	/* Register CQ IRQ handlers */
>>>>+	vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
>>>>+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
>>>>+		irq_name = &hw->irq_name[vec * NAME_SIZE];
>>>>+
>>>>+		snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
>>>>+
>>>>+		err = request_irq(pci_irq_vector(priv->pdev, vec),
>>>>+				  otx2_cq_intr_handler, 0, irq_name,
>>>>+				  &qset->napi[qidx]);
>>>>+		if (err) {
>>>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>>>+					       "RVU REP IRQ registration failed for
>>>CQ%d",
>>>>+					       qidx);
>>>>+			goto err_free_cints;
>>>>+		}
>>>>+		vec++;
>>>>+
>>>>+		/* Enable CQ IRQ */
>>>>+		otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
>>>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
>>>>+	}
>>>>+	priv->flags &= ~OTX2_FLAG_INTF_DOWN;
>>>>+	return 0;
>>>>+
>>>>+err_free_cints:
>>>>+	otx2_free_cints(priv, qidx);
>>>>+	otx2_disable_napi(priv);
>>>>+	return err;
>>>>+}
>>>>+
>>>>+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv) {
>>>>+	struct otx2_qset *qset = &priv->qset;
>>>>+	struct otx2_cq_poll *cq_poll = NULL;
>>>>+	int qidx, vec;
>>>>+
>>>>+	/* Cleanup CQ NAPI and IRQ */
>>>>+	vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
>>>>+	for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
>>>>+		/* Disable interrupt */
>>>>+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx),
>>>BIT_ULL(0));
>>>>+
>>>>+		synchronize_irq(pci_irq_vector(priv->pdev, vec));
>>>>+
>>>>+		cq_poll = &qset->napi[qidx];
>>>>+		napi_synchronize(&cq_poll->napi);
>>>>+		vec++;
>>>>+	}
>>>>+	otx2_free_cints(priv, priv->hw.cint_cnt);
>>>>+	otx2_disable_napi(priv);
>>>>+}
>>>>+
>>>>+void rvu_rep_destroy(struct otx2_nic *priv) {
>>>>+	struct rep_dev *rep;
>>>>+	int rep_id;
>>>>+
>>>>+	priv->flags |= OTX2_FLAG_INTF_DOWN;
>>>>+	rvu_rep_free_cq_rsrc(priv);
>>>>+	for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
>>>>+		rep = priv->reps[rep_id];
>>>>+		unregister_netdev(rep->netdev);
>>>>+		free_netdev(rep->netdev);
>>>>+	}
>>>>+	kfree(priv->reps);
>>>>+}
>>>>+
>>>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>>>+*extack) {
>>>>+	int rep_cnt = priv->rep_cnt;
>>>>+	struct net_device *ndev;
>>>>+	struct rep_dev *rep;
>>>>+	int rep_id, err;
>>>>+	u16 pcifunc;
>>>>+
>>>>+	priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
>>>>+	if (!priv->reps)
>>>>+		return -ENOMEM;
>>>>+
>>>>+	for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
>>>>+		ndev = alloc_etherdev(sizeof(*rep));
>>>>+		if (!ndev) {
>>>>+			NL_SET_ERR_MSG_FMT_MOD(extack,
>>>>+					       "PFVF representor:%d creation
>>>failed",
>>>>+					       rep_id);
>>>>+			err = -ENOMEM;
>>>>+			goto exit;
>>>>+		}
>>>>+
>>>>+		rep = netdev_priv(ndev);
>>>>+		priv->reps[rep_id] = rep;
>>>>+		rep->mdev = priv;
>>>>+		rep->netdev = ndev;
>>>>+		rep->rep_id = rep_id;
>>>>+
>>>>+		ndev->min_mtu = OTX2_MIN_MTU;
>>>>+		ndev->max_mtu = priv->hw.max_mtu;
>>>>+		pcifunc = priv->rep_pf_map[rep_id];
>>>>+		rep->pcifunc = pcifunc;
>>>>+
>>>>+		snprintf(ndev->name, sizeof(ndev->name), "r%dp%d", rep_id,
>>>>+			 rvu_get_pf(pcifunc));
>>>>+
>>>>+		eth_hw_addr_random(ndev);
>>>>+		err = register_netdev(ndev);
>>>
>>>I don't follow. You just create netdevices, no devlink ports. That is
>>>inconsistent with your documentation above.
>>Creation on devlink port is implemented in patch 10 " octeontx2-pf: Add
>devlink port support".
>
>So adjust the docs here to be consistent with the code and add the parts of
>documentation alonside with the support in patch 10.
Ok. As suggested will correct the documentation in next version. 
>
>
>>>
>>>
>>>>+		if (err) {
>>>>+			NL_SET_ERR_MSG_MOD(extack,
>>>>+					   "PFVF reprentator registration
>>>failed");
>>>>+			free_netdev(ndev);
>>>>+			goto exit;
>>>>+		}
>>>>+	}
>>>>+	err = rvu_rep_napi_init(priv, extack);
>>>>+	if (err)
>>>>+		goto exit;
>>>>+
>>>>+	return 0;
>>>>+exit:
>>>>+	while (--rep_id >= 0) {
>>>>+		rep = priv->reps[rep_id];
>>>>+		unregister_netdev(rep->netdev);
>>>>+		free_netdev(rep->netdev);
>>>>+	}
>>>>+	kfree(priv->reps);
>>>>+	return err;
>>>>+}
>>>>+
>>>> static void rvu_rep_rsrc_free(struct otx2_nic *priv)  {
>>>> 	struct otx2_qset *qset = &priv->qset; @@ -167,6 +325,10 @@ static
>>>>int rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>>> 	if (err)
>>>> 		goto err_detach_rsrc;
>>>>
>>>>+	err = otx2_register_dl(priv);
>>>>+	if (err)
>>>>+		goto err_detach_rsrc;
>>>>+
>>>> 	return 0;
>>>>
>>>> err_detach_rsrc:
>>>>@@ -188,6 +350,9 @@ static void rvu_rep_remove(struct pci_dev *pdev)  {
>>>> 	struct otx2_nic *priv = pci_get_drvdata(pdev);
>>>>
>>>>+	otx2_unregister_dl(priv);
>>>>+	if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
>>>>+		rvu_rep_destroy(priv);
>>>> 	rvu_rep_rsrc_free(priv);
>>>> 	otx2_detach_resources(&priv->mbox);
>>>> 	if (priv->hw.lmt_info)
>>>>diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>>b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>>index 565e75628df2..c04874c4d4c6 100644
>>>>--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>>+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
>>>>@@ -28,4 +28,7 @@ static inline bool otx2_rep_dev(struct pci_dev
>>>>*pdev) {
>>>> 	return pdev->device == PCI_DEVID_RVU_REP;  }
>>>>+
>>>>+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack
>>>>+*extack); void rvu_rep_destroy(struct otx2_nic *priv);
>>>> #endif /* REP_H */
>>>>--
>>>>2.25.1
>>>>
>>>>
diff mbox series

Patch

diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
index 1e196cb9ce25..4eb4e6788ffc 100644
--- a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
+++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
@@ -14,6 +14,7 @@  Contents
 - `Basic packet flow`_
 - `Devlink health reporters`_
 - `Quality of service`_
+- `RVU representors`_
 
 Overview
 ========
@@ -340,3 +341,87 @@  Setup HTB offload
         # tc class add dev <interface> parent 1: classid 1:2 htb rate 10Gbit prio 2 quantum 188416
 
         # tc class add dev <interface> parent 1: classid 1:3 htb rate 10Gbit prio 2 quantum 32768
+
+
+RVU Representors
+================
+
+RVU representor driver adds support for creation of representor devices for
+RVU PFs' VFs in the system. Representor devices are created when user enables
+the switchdev mode.
+Switchdev mode can be enabled either before or after setting up SRIOV numVFs.
+All representor devices share a single NIXLF but each has a dedicated queue
+(ie RQ/SQ. RVU PF representor driver registers a separate netdev for each
+RQ/SQ queue pair.
+
+HW doesn't have a in-built switch which can do L2 learning and forward pkts
+between representee and representor. Hence packet patch between representee
+and it's representor is achieved by setting up appropriate NPC MCAM filters.
+Transmit packets matching these filters will be loopbacked through hardware
+loopback channel/interface (ie instead of sending them out of MAC interface).
+Which will again match the installed filters and will be forwarded.
+This way representee => representor and representor => representee packet
+path is achieved.These rules get installed when representors are created
+and gets active/deactivate based on the representor/representee interface state.
+
+Usage example:
+
+ - List of devices on the system before vfs are created::
+
+	# devlink dev
+	pci/0002:02:00.0
+	pci/0002:1c:00.0
+
+- Change device to switchdev mode::
+	# devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
+
+ - List the devices on the system::
+
+	# ip link show
+
+Sample output::
+
+	# ip link show
+	eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7e:58:2d:b6:97:51 brd ff:ff:ff:ff:ff:ff
+	r0p1v0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7e:5a:66:ea:fe:d6 brd ff:ff:ff:ff:ff:ff
+	r1p1v1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether de:29:be:10:9e:bf brd ff:ff:ff:ff:ff:ff
+	r2p1v2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 4a:12:c7:a2:66:ad brd ff:ff:ff:ff:ff:ff
+	r3p1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether c2:b8:a8:0e:73:fd brd ff:ff:ff:ff:ff:ff
+
+
+RVU representors can be managed using devlink ports
+(see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.
+
+ - Show devlink ports of representors::
+
+	# devlink port
+
+Sample output::
+
+	pci/0002:1c:00.0/0: type eth netdev r0p1v0 flavour pcipf controller 0 pfnum 1 vfnum 0 external false splittable false
+	pci/0002:1c:00.0/1: type eth netdev r1p1v1 flavour pcivf controller 0 pfnum 1 vfnum 1 external false splittable false
+	pci/0002:1c:00.0/2: type eth netdev r2p1v2 flavour pcivf controller 0 pfnum 1 vfnum 2 external false splittable false
+	pci/0002:1c:00.0/3: type eth netdev r3p1v3 flavour pcivf controller 0 pfnum 1 vfnum 3 external false splittable false
+
+Function attributes
+===================
+
+The RVU representor support function attributes for representors
+Port function configuration of the representors are supported through devlink eswitch port.
+
+MAC address setup
+-----------------
+
+RVU representor driver support devlink port function attr mechanism to setup MAC
+address. (refer to Documentation/networking/devlink/devlink-port.rst)
+
+ - To setup MAC address for port 2::
+
+	# devlink port function set  pci/0002:1c:00.0/2 hw_addr 5c:a1:1b:5e:43:11 state active
+
+
+To remove the representors from the system. Change the device to legacy mode.
+
+ - Change device to legacy mode::
+
+	# devlink dev eswitch set pci/0002:1c:00.0 mode legacy
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
index 53f14aa944bd..33ec9a7f7c03 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
@@ -141,7 +141,56 @@  static const struct devlink_param otx2_dl_params[] = {
 			     otx2_dl_ucast_flt_cnt_validate),
 };
 
+#ifdef CONFIG_RVU_ESWITCH
+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
+{
+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
+	struct otx2_nic *pfvf = otx2_dl->pfvf;
+
+	if (!otx2_rep_dev(pfvf->pdev))
+		return -EOPNOTSUPP;
+
+	*mode = pfvf->esw_mode;
+
+	return 0;
+}
+
+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
+					 struct netlink_ext_ack *extack)
+{
+	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
+	struct otx2_nic *pfvf = otx2_dl->pfvf;
+	int ret = 0;
+
+	if (!otx2_rep_dev(pfvf->pdev))
+		return -EOPNOTSUPP;
+
+	if (pfvf->esw_mode == mode)
+		return 0;
+
+	switch (mode) {
+	case DEVLINK_ESWITCH_MODE_LEGACY:
+		rvu_rep_destroy(pfvf);
+		break;
+	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
+		ret = rvu_rep_create(pfvf, extack);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!ret)
+		pfvf->esw_mode = mode;
+
+	return ret;
+}
+#endif
+
 static const struct devlink_ops otx2_devlink_ops = {
+#ifdef CONFIG_RVU_ESWITCH
+	.eswitch_mode_get = otx2_devlink_eswitch_mode_get,
+	.eswitch_mode_set = otx2_devlink_eswitch_mode_set,
+#endif
 };
 
 int otx2_register_dl(struct otx2_nic *pfvf)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
index b0a0080e50d7..6ea5b4904a7c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
@@ -28,6 +28,164 @@  MODULE_DESCRIPTION(DRV_STRING);
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, rvu_rep_id_table);
 
+static int rvu_rep_napi_init(struct otx2_nic *priv,
+			     struct netlink_ext_ack *extack)
+{
+	struct otx2_qset *qset = &priv->qset;
+	struct otx2_cq_poll *cq_poll = NULL;
+	struct otx2_hw *hw = &priv->hw;
+	int err = 0, qidx, vec;
+	char *irq_name;
+
+	qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
+	if (!qset->napi)
+		return -ENOMEM;
+
+	/* Register NAPI handler */
+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
+		cq_poll = &qset->napi[qidx];
+		cq_poll->cint_idx = qidx;
+		cq_poll->cq_ids[CQ_RX] =
+			(qidx <  hw->rx_queues) ? qidx : CINT_INVALID_CQ;
+		cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
+					  qidx + hw->rx_queues :
+					  CINT_INVALID_CQ;
+		cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
+		cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
+
+		cq_poll->dev = (void *)priv;
+		netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
+			       otx2_napi_handler);
+		napi_enable(&cq_poll->napi);
+	}
+	/* Register CQ IRQ handlers */
+	vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
+	for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
+		irq_name = &hw->irq_name[vec * NAME_SIZE];
+
+		snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
+
+		err = request_irq(pci_irq_vector(priv->pdev, vec),
+				  otx2_cq_intr_handler, 0, irq_name,
+				  &qset->napi[qidx]);
+		if (err) {
+			NL_SET_ERR_MSG_FMT_MOD(extack,
+					       "RVU REP IRQ registration failed for CQ%d",
+					       qidx);
+			goto err_free_cints;
+		}
+		vec++;
+
+		/* Enable CQ IRQ */
+		otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
+	}
+	priv->flags &= ~OTX2_FLAG_INTF_DOWN;
+	return 0;
+
+err_free_cints:
+	otx2_free_cints(priv, qidx);
+	otx2_disable_napi(priv);
+	return err;
+}
+
+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv)
+{
+	struct otx2_qset *qset = &priv->qset;
+	struct otx2_cq_poll *cq_poll = NULL;
+	int qidx, vec;
+
+	/* Cleanup CQ NAPI and IRQ */
+	vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
+	for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
+		/* Disable interrupt */
+		otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0));
+
+		synchronize_irq(pci_irq_vector(priv->pdev, vec));
+
+		cq_poll = &qset->napi[qidx];
+		napi_synchronize(&cq_poll->napi);
+		vec++;
+	}
+	otx2_free_cints(priv, priv->hw.cint_cnt);
+	otx2_disable_napi(priv);
+}
+
+void rvu_rep_destroy(struct otx2_nic *priv)
+{
+	struct rep_dev *rep;
+	int rep_id;
+
+	priv->flags |= OTX2_FLAG_INTF_DOWN;
+	rvu_rep_free_cq_rsrc(priv);
+	for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
+		rep = priv->reps[rep_id];
+		unregister_netdev(rep->netdev);
+		free_netdev(rep->netdev);
+	}
+	kfree(priv->reps);
+}
+
+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack)
+{
+	int rep_cnt = priv->rep_cnt;
+	struct net_device *ndev;
+	struct rep_dev *rep;
+	int rep_id, err;
+	u16 pcifunc;
+
+	priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
+	if (!priv->reps)
+		return -ENOMEM;
+
+	for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
+		ndev = alloc_etherdev(sizeof(*rep));
+		if (!ndev) {
+			NL_SET_ERR_MSG_FMT_MOD(extack,
+					       "PFVF representor:%d creation failed",
+					       rep_id);
+			err = -ENOMEM;
+			goto exit;
+		}
+
+		rep = netdev_priv(ndev);
+		priv->reps[rep_id] = rep;
+		rep->mdev = priv;
+		rep->netdev = ndev;
+		rep->rep_id = rep_id;
+
+		ndev->min_mtu = OTX2_MIN_MTU;
+		ndev->max_mtu = priv->hw.max_mtu;
+		pcifunc = priv->rep_pf_map[rep_id];
+		rep->pcifunc = pcifunc;
+
+		snprintf(ndev->name, sizeof(ndev->name), "r%dp%d", rep_id,
+			 rvu_get_pf(pcifunc));
+
+		eth_hw_addr_random(ndev);
+		err = register_netdev(ndev);
+		if (err) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "PFVF reprentator registration failed");
+			free_netdev(ndev);
+			goto exit;
+		}
+	}
+	err = rvu_rep_napi_init(priv, extack);
+	if (err)
+		goto exit;
+
+	return 0;
+exit:
+	while (--rep_id >= 0) {
+		rep = priv->reps[rep_id];
+		unregister_netdev(rep->netdev);
+		free_netdev(rep->netdev);
+	}
+	kfree(priv->reps);
+	return err;
+}
+
 static void rvu_rep_rsrc_free(struct otx2_nic *priv)
 {
 	struct otx2_qset *qset = &priv->qset;
@@ -167,6 +325,10 @@  static int rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (err)
 		goto err_detach_rsrc;
 
+	err = otx2_register_dl(priv);
+	if (err)
+		goto err_detach_rsrc;
+
 	return 0;
 
 err_detach_rsrc:
@@ -188,6 +350,9 @@  static void rvu_rep_remove(struct pci_dev *pdev)
 {
 	struct otx2_nic *priv = pci_get_drvdata(pdev);
 
+	otx2_unregister_dl(priv);
+	if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
+		rvu_rep_destroy(priv);
 	rvu_rep_rsrc_free(priv);
 	otx2_detach_resources(&priv->mbox);
 	if (priv->hw.lmt_info)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
index 565e75628df2..c04874c4d4c6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
@@ -28,4 +28,7 @@  static inline bool otx2_rep_dev(struct pci_dev *pdev)
 {
 	return pdev->device == PCI_DEVID_RVU_REP;
 }
+
+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack);
+void rvu_rep_destroy(struct otx2_nic *priv);
 #endif /* REP_H */