From: Tariq Toukan <tariqt@nvidia.com>
To: Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>
Cc: Saeed Mahameed <saeedm@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
"Simon Horman" <horms@kernel.org>,
Adithya Jayachandran <ajayachandra@nvidia.com>,
Jiri Pirko <jiri@resnulli.us>, Moshe Shemesh <moshe@nvidia.com>,
Or Har-Toov <ohartoov@nvidia.com>, Shay Drori <shayd@nvidia.com>,
Parav Pandit <parav@nvidia.com>,
Daniel Jurgens <danielj@nvidia.com>, Kees Cook <kees@kernel.org>,
Cosmin Ratiu <cratiu@nvidia.com>,
Carolina Jubran <cjubran@nvidia.com>, <netdev@vger.kernel.org>,
<linux-rdma@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
Gal Pressman <gal@nvidia.com>
Subject: [PATCH net-next 01/12] net/mlx5: Add satellite PF vport support
Date: Thu, 21 May 2026 14:08:32 +0300 [thread overview]
Message-ID: <20260521110843.367329-2-tariqt@nvidia.com> (raw)
In-Reply-To: <20260521110843.367329-1-tariqt@nvidia.com>
From: Moshe Shemesh <moshe@nvidia.com>
Discover satellite PFs from query_esw_functions output and allocate
eswitch vports for them. For each satellite PF, create a vport via the
CREATE_ESW_VPORT command using its vhca_id and allocate it in the
eswitch vport table.
When enabling switchdev mode, the ECPF acting as the eswitch manager
activates each satellite PF with enable_hca, loads its vport and adds
a representor. Since satellite PF devlink ports are registered in a
later patch, guard mlx5_esw_offloads_devlink_port() against vports
with no devlink port to avoid NULL dereference during representor
attach.
Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../mellanox/mlx5/core/esw/adj_vport.c | 6 +-
.../mellanox/mlx5/core/esw/devlink_port.c | 7 +-
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 159 +++++++++++++++++-
.../net/ethernet/mellanox/mlx5/core/eswitch.h | 10 ++
4 files changed, 171 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
index 250af09b5af2..ca249b50f830 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
@@ -23,7 +23,7 @@ int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
return mlx5_cmd_exec_in(dev, modify_vport_state, in);
}
-static void mlx5_esw_destroy_esw_vport(struct mlx5_core_dev *dev, u16 vport)
+void mlx5_esw_destroy_esw_vport(struct mlx5_core_dev *dev, u16 vport)
{
u32 in[MLX5_ST_SZ_DW(destroy_esw_vport_in)] = {};
@@ -34,8 +34,8 @@ static void mlx5_esw_destroy_esw_vport(struct mlx5_core_dev *dev, u16 vport)
mlx5_cmd_exec_in(dev, destroy_esw_vport, in);
}
-static int mlx5_esw_create_esw_vport(struct mlx5_core_dev *dev, u16 vhca_id,
- u16 *vport_num)
+int mlx5_esw_create_esw_vport(struct mlx5_core_dev *dev, u16 vhca_id,
+ u16 *vport_num)
{
u32 out[MLX5_ST_SZ_DW(create_esw_vport_out)] = {};
u32 in[MLX5_ST_SZ_DW(create_esw_vport_in)] = {};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index 8a79764345e7..0730f0c883fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -253,5 +253,10 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1
struct mlx5_vport *vport;
vport = mlx5_eswitch_get_vport(esw, vport_num);
- return IS_ERR(vport) ? ERR_CAST(vport) : &vport->dl_port->dl_port;
+ if (IS_ERR(vport))
+ return ERR_CAST(vport);
+ if (!vport->dl_port)
+ return ERR_PTR(-ENODEV);
+
+ return &vport->dl_port->dl_port;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 206911817a04..e75925a99852 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1517,8 +1517,11 @@ int
mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
enum mlx5_eswitch_vport_event enabled_events)
{
+ struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs;
bool pf_needed;
+ u16 vport_num;
int ret;
+ int i;
pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) ||
esw->mode == MLX5_ESWITCH_LEGACY;
@@ -1548,14 +1551,14 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
/* Enable ECVF vports */
if (mlx5_core_ec_sriov_enabled(esw->dev)) {
ret = mlx5_eswitch_load_ec_vf_vports(esw,
- esw->esw_funcs.num_ec_vfs,
+ esw_funcs->num_ec_vfs,
enabled_events);
if (ret)
goto ec_vf_err;
}
/* Enable VF vports */
- ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
+ ret = mlx5_eswitch_load_vf_vports(esw, esw_funcs->num_vfs,
enabled_events);
if (ret)
goto vf_err;
@@ -1565,13 +1568,36 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
if (ret)
goto unload_vf_vports;
+ /* Enable satellite PF vports */
+ for (i = 0; i < esw_funcs->num_spfs; i++) {
+ vport_num = esw_funcs->spfs[i].vport_num;
+
+ ret = mlx5_eswitch_load_pf_vf_vport(esw, vport_num,
+ enabled_events);
+ if (ret)
+ goto spf_err;
+
+ ret = mlx5_esw_pf_enable_hca(esw->dev, vport_num);
+ if (ret) {
+ mlx5_eswitch_unload_pf_vf_vport(esw, vport_num);
+ goto spf_err;
+ }
+ }
+
return 0;
+spf_err:
+ while (i-- > 0) {
+ vport_num = esw_funcs->spfs[i].vport_num;
+ mlx5_esw_pf_disable_hca(esw->dev, vport_num);
+ mlx5_eswitch_unload_pf_vf_vport(esw, vport_num);
+ }
+ mlx5_eswitch_unload_adj_vf_vports(esw);
unload_vf_vports:
- mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
+ mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs);
vf_err:
if (mlx5_core_ec_sriov_enabled(esw->dev))
- mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs);
ec_vf_err:
if (mlx5_ecpf_vport_exists(esw->dev))
mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
@@ -1589,13 +1615,22 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
*/
void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
{
+ struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs;
+ u16 vport_num;
+ int i;
+
+ for (i = 0; i < esw_funcs->num_spfs; i++) {
+ vport_num = esw_funcs->spfs[i].vport_num;
+ mlx5_esw_pf_disable_hca(esw->dev, vport_num);
+ mlx5_eswitch_unload_pf_vf_vport(esw, vport_num);
+ }
+
mlx5_eswitch_unload_adj_vf_vports(esw);
- mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
+ mlx5_eswitch_unload_vf_vports(esw, esw_funcs->num_vfs);
if (mlx5_core_ec_sriov_enabled(esw->dev))
- mlx5_eswitch_unload_ec_vf_vports(esw,
- esw->esw_funcs.num_ec_vfs);
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw_funcs->num_ec_vfs);
if (mlx5_ecpf_vport_exists(esw->dev)) {
mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
@@ -2065,11 +2100,105 @@ void mlx5_esw_vport_free(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
kfree(vport);
}
+static void mlx5_esw_spfs_cleanup(struct mlx5_eswitch *esw)
+{
+ struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs;
+ int i;
+
+ for (i = 0; i < esw_funcs->num_spfs; i++)
+ mlx5_esw_destroy_esw_vport(esw->dev,
+ esw_funcs->spfs[i].vport_num);
+
+ kfree(esw_funcs->spfs);
+ esw_funcs->spfs = NULL;
+ esw_funcs->num_spfs = 0;
+}
+
+static int mlx5_esw_spfs_init(struct mlx5_eswitch *esw)
+{
+ struct mlx5_esw_functions *esw_funcs = &esw->esw_funcs;
+ struct mlx5_core_dev *dev = esw->dev;
+ int num_entries;
+ const u8 *entry;
+ const u32 *out;
+ int err = 0;
+ int pf_type;
+ u16 vhca_id;
+ int i;
+
+ if (!MLX5_CAP_GEN(dev, query_host_net_function_v1))
+ return 0;
+
+ out = mlx5_esw_query_functions(dev);
+ if (IS_ERR(out))
+ return PTR_ERR(out);
+
+ num_entries = MLX5_GET(query_esw_functions_out, out, net_function_num);
+ if (!num_entries)
+ goto out_free;
+
+ esw_funcs->spfs = kcalloc(num_entries, sizeof(*esw_funcs->spfs),
+ GFP_KERNEL);
+ if (!esw_funcs->spfs) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ entry = MLX5_ADDR_OF(query_esw_functions_out, out, net_function_params);
+
+ for (i = 0; i < num_entries; i++) {
+ u16 vport_num;
+
+ pf_type = MLX5_GET(network_function_params, entry, pci_pf_type);
+ if (pf_type != MLX5_PCI_PF_TYPE_SATELLITE_PF) {
+ entry += MLX5_UN_SZ_BYTES(net_function_params);
+ continue;
+ }
+
+ if (!MLX5_GET(network_function_params, entry,
+ esw_vport_manual)) {
+ esw_warn(dev, "Satellite PF without esw_vport_manual is not supported\n");
+ entry += MLX5_UN_SZ_BYTES(net_function_params);
+ continue;
+ }
+
+ vhca_id = MLX5_GET(network_function_params, entry, vhca_id);
+
+ err = mlx5_esw_create_esw_vport(dev, vhca_id, &vport_num);
+ if (err) {
+ esw_warn(dev, "Failed to create satellite PF vport for vhca_id 0x%x, err %d\n",
+ vhca_id, err);
+ goto spfs_cleanup;
+ }
+
+ esw_funcs->spfs[esw_funcs->num_spfs].vport_num = vport_num;
+ esw_funcs->spfs[esw_funcs->num_spfs].vhca_id = vhca_id;
+ esw_funcs->num_spfs++;
+
+ entry += MLX5_UN_SZ_BYTES(net_function_params);
+ }
+
+ if (!esw_funcs->num_spfs) {
+ kfree(esw_funcs->spfs);
+ esw_funcs->spfs = NULL;
+ }
+
+ kvfree(out);
+ return 0;
+
+spfs_cleanup:
+ mlx5_esw_spfs_cleanup(esw);
+out_free:
+ kvfree(out);
+ return err;
+}
+
static void mlx5_esw_vports_cleanup(struct mlx5_eswitch *esw)
{
struct mlx5_vport *vport;
unsigned long i;
+ mlx5_esw_spfs_cleanup(esw);
mlx5_esw_for_each_vport(esw, i, vport)
mlx5_esw_vport_free(esw, vport);
xa_destroy(&esw->vports);
@@ -2123,6 +2252,22 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
idx++;
}
+ err = mlx5_esw_spfs_init(esw);
+ if (err)
+ goto err;
+
+ for (i = 0; i < esw->esw_funcs.num_spfs; i++) {
+ struct mlx5_vport *vport;
+ u16 vport_num;
+
+ vport_num = esw->esw_funcs.spfs[i].vport_num;
+ err = mlx5_esw_vport_alloc(esw, idx++, vport_num);
+ if (err)
+ goto err;
+ vport = mlx5_eswitch_get_vport(esw, vport_num);
+ vport->vhca_id = esw->esw_funcs.spfs[i].vhca_id;
+ }
+
if (mlx5_core_ec_sriov_enabled(esw->dev)) {
int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index a5f832ed2251..19419799a26d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -349,11 +349,18 @@ struct mlx5_host_work {
void (*func)(struct mlx5_eswitch *esw);
};
+struct mlx5_esw_spf {
+ u16 vport_num;
+ u16 vhca_id;
+};
+
struct mlx5_esw_functions {
struct mlx5_nb nb;
bool host_funcs_disabled;
u16 num_vfs;
u16 num_ec_vfs;
+ struct mlx5_esw_spf *spfs;
+ int num_spfs;
};
enum {
@@ -666,6 +673,9 @@ void mlx5_esw_adjacent_vhcas_setup(struct mlx5_eswitch *esw);
void mlx5_esw_adjacent_vhcas_cleanup(struct mlx5_eswitch *esw);
int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
bool connect);
+int mlx5_esw_create_esw_vport(struct mlx5_core_dev *dev, u16 vhca_id,
+ u16 *vport_num);
+void mlx5_esw_destroy_esw_vport(struct mlx5_core_dev *dev, u16 vport);
#define MLX5_DEBUG_ESWITCH_MASK BIT(3)
--
2.44.0
next prev parent reply other threads:[~2026-05-21 11:11 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 11:08 [PATCH net-next 00/12] net/mlx5: Add satellite PF support Tariq Toukan
2026-05-21 11:08 ` Tariq Toukan [this message]
2026-05-21 11:08 ` [PATCH net-next 02/12] net/mlx5: Introduce generic helper for PF SFs info Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 03/12] net/mlx5: Initialize host PF host number earlier Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 04/12] net/mlx5: Initialize satellite PF SF vports Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 05/12] net/mlx5: Support SPF SFs in SF hardware table Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 06/12] net/mlx5: Expose PF number from query_esw_functions Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 07/12] net/mlx5: Map SF controller to pfnum for satellite PFs Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 08/12] net/mlx5: Register devlink ports " Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 09/12] net/mlx5: Register SF resource on satellite PF ports Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 10/12] net/mlx5: Support state get/set for " Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 11/12] net/mlx5: Add FDB peer miss rules for satellite PFs Tariq Toukan
2026-05-21 11:08 ` [PATCH net-next 12/12] net/mlx5: Add SPF function type for page management Tariq Toukan
2026-05-25 21:10 ` [PATCH net-next 00/12] net/mlx5: Add satellite PF support patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260521110843.367329-2-tariqt@nvidia.com \
--to=tariqt@nvidia.com \
--cc=ajayachandra@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=cjubran@nvidia.com \
--cc=cratiu@nvidia.com \
--cc=danielj@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gal@nvidia.com \
--cc=horms@kernel.org \
--cc=jiri@resnulli.us \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=mbloch@nvidia.com \
--cc=moshe@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=ohartoov@nvidia.com \
--cc=pabeni@redhat.com \
--cc=parav@nvidia.com \
--cc=saeedm@nvidia.com \
--cc=shayd@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox