From: Tariq Toukan <tariqt@nvidia.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, <netdev@vger.kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Carolina Jubran <cjubran@nvidia.com>, Chris Mi <cmi@nvidia.com>,
"Cosmin Ratiu" <cratiu@nvidia.com>, Gal Pressman <gal@nvidia.com>,
Kees Cook <kees@kernel.org>, Leon Romanovsky <leon@kernel.org>,
<linux-kernel@vger.kernel.org>, <linux-rdma@vger.kernel.org>,
Mark Bloch <mbloch@nvidia.com>, Moshe Shemesh <moshe@nvidia.com>,
Parav Pandit <parav@nvidia.com>,
Saeed Mahameed <saeedm@nvidia.com>, Shay Drori <shayd@nvidia.com>,
Tariq Toukan <tariqt@nvidia.com>, Vu Pham <vuhuong@nvidia.com>
Subject: [PATCH net] net/mlx5: SF, Handle function changed event
Date: Wed, 29 Jul 2026 10:16:22 +0300 [thread overview]
Message-ID: <20260729071622.2423270-1-tariqt@nvidia.com> (raw)
From: Chris Mi <cmi@nvidia.com>
When host is powered off, firmware does not send vhca_state event
for every probed host SF on the DPU because it may have deployed
thousands of SFs to the host. Instead it sends a function changed
event. Currently, only VFs handle this event. This commit extends
support to SFs.
When DPU user deactivates[1] SFs, mlx5 expects vhca_state event
and leaves the SF in dangling state[2].
When DPU user deletes[3] SFs, mlx5 also expects vhca_state event
and destroys the SF resources[4].
Fix it by changing SF to the right state and freeing SF resources
when the function changed event is received.
When this event is received, driver checks all SF states.
- If state is in_use, change it to active.
- If state is teardown_request, change it to allocated.
And SF hardware table entry is freed if it is pending for delete.
[1]
# devlink port function set en3f0c1pf0sf0 state inactive
[2]
# devlink port function set en3f0c1pf0sf0 state active
Error: mlx5_core: SF is inactivated but it is still attached.
kernel answers: Device or resource busy
[3]
# devlink port show
pci/0000:03:00.0/229376: type eth netdev en3f0c1pf0sf0 \
flavour pcisf controller 1 pfnum 0 sfnum 0 splittable false
function:
hw_addr 00:00:00:00:00:00 state active opstate attached \
roce enable trust off max_uc_macs 4096 max_io_eqs 8
# devlink port del en3f0c1pf0sf0
[4]
# devlink port add pci/0000:03:00.0 flavour pcisf pfnum 0 sfnum 0 \
controller 1
Error: mlx5_core: SF already exist. Choose different sfnum.
kernel answers: File exists
Fixes: 6a3273217469 ("net/mlx5: SF, Port function state change support")
Signed-off-by: Chris Mi <cmi@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../mellanox/mlx5/core/eswitch_offloads.c | 10 +++++--
.../ethernet/mellanox/mlx5/core/sf/devlink.c | 29 +++++++++++++++++++
.../mlx5/core/sf/diag/sf_tracepoint.h | 8 +++++
.../ethernet/mellanox/mlx5/core/sf/hw_table.c | 22 ++++++++++++++
.../net/ethernet/mellanox/mlx5/core/sf/sf.h | 12 ++++++++
5 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 907ee83a722d..247e5d85ec36 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -3986,7 +3986,7 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
mutex_destroy(&esw->fdb_table.offloads.vports.lock);
}
-static void esw_vfs_changed_event_handler(struct mlx5_eswitch *esw)
+static void esw_changed_event_handler(struct mlx5_eswitch *esw)
{
struct mlx5_esw_pf_info host_pf_info;
u16 new_num_vfs;
@@ -3999,6 +3999,11 @@ static void esw_vfs_changed_event_handler(struct mlx5_eswitch *esw)
host_pf_info = mlx5_esw_get_host_pf_info(esw->dev, out);
new_num_vfs = host_pf_info.num_of_vfs;
+ if (host_pf_info.pf_disabled) {
+ mlx5_sf_table_esw_changed_event_handler(esw->dev);
+ mlx5_sf_hw_table_esw_changed_event_handler(esw->dev);
+ }
+
if (new_num_vfs == esw->esw_funcs.num_vfs || host_pf_info.pf_disabled)
goto free;
@@ -4091,8 +4096,7 @@ int mlx5_esw_funcs_changed_handler(struct notifier_block *nb,
esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
- ret = mlx5_esw_add_work(esw, esw_vfs_changed_event_handler,
- GFP_ATOMIC);
+ ret = mlx5_esw_add_work(esw, esw_changed_event_handler, GFP_ATOMIC);
if (ret)
return NOTIFY_DONE;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
index b6cecbcc392d..4564d460416b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
@@ -561,3 +561,32 @@ bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev)
return xa_empty(&table->function_ids);
}
+
+void mlx5_sf_table_esw_changed_event_handler(struct mlx5_core_dev *dev)
+{
+ struct mlx5_sf_table *table = dev->priv.sf_table;
+ unsigned long index;
+ struct mlx5_sf *sf;
+
+ trace_mlx5_sf_host_pf_disabled(dev);
+
+ if (!table)
+ return;
+
+ mutex_lock(&table->sf_state_lock);
+ xa_for_each(&table->function_ids, index, sf) {
+ if (!sf->controller)
+ continue;
+
+ if (sf->hw_state == MLX5_VHCA_STATE_IN_USE)
+ sf->hw_state = MLX5_VHCA_STATE_ACTIVE;
+ else if (sf->hw_state == MLX5_VHCA_STATE_TEARDOWN_REQUEST)
+ sf->hw_state = MLX5_VHCA_STATE_ALLOCATED;
+ else
+ continue;
+ trace_mlx5_sf_update_state(table->dev, sf->port_index,
+ sf->controller, sf->hw_fn_id,
+ sf->hw_state);
+ }
+ mutex_unlock(&table->sf_state_lock);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h
index 302ce00da5a9..9dc88a7e30ca 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h
@@ -11,6 +11,14 @@
#include <linux/mlx5/driver.h>
#include "sf/vhca_event.h"
+TRACE_EVENT(mlx5_sf_host_pf_disabled,
+ TP_PROTO(const struct mlx5_core_dev *dev),
+ TP_ARGS(dev),
+ TP_STRUCT__entry(__string(devname, dev_name(dev->device))),
+ TP_fast_assign(__assign_str(devname);),
+ TP_printk("(%s)\n", __get_str(devname))
+);
+
TRACE_EVENT(mlx5_sf_add,
TP_PROTO(const struct mlx5_core_dev *dev,
unsigned int port_index,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
index 0bc9146a3598..95a8b1e64ba4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
@@ -459,3 +459,25 @@ bool mlx5_sf_hw_table_supported(const struct mlx5_core_dev *dev)
{
return !!dev->priv.sf_hw_table;
}
+
+void mlx5_sf_hw_table_esw_changed_event_handler(struct mlx5_core_dev *dev)
+{
+ struct mlx5_sf_hw_table *table;
+ struct mlx5_sf_hwc_table *hwc;
+ int i;
+
+ table = dev->priv.sf_hw_table;
+ if (!table)
+ return;
+
+ mutex_lock(&table->table_lock);
+ hwc = &table->hwc[MLX5_SF_HWC_EXT_HOST];
+ for (i = 0; i < hwc->max_fn; i++) {
+ struct mlx5_sf_hw *sf_hw;
+
+ sf_hw = &hwc->sfs[i];
+ if (sf_hw->allocated && sf_hw->pending_delete)
+ mlx5_sf_hw_table_hwc_sf_free(dev, hwc, i);
+ }
+ mutex_unlock(&table->table_lock);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
index d8a934a0e968..ed784682b9b1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
@@ -15,12 +15,14 @@ void mlx5_sf_hw_table_cleanup(struct mlx5_core_dev *dev);
int mlx5_sf_hw_notifier_init(struct mlx5_core_dev *dev);
void mlx5_sf_hw_notifier_cleanup(struct mlx5_core_dev *dev);
void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev);
+void mlx5_sf_hw_table_esw_changed_event_handler(struct mlx5_core_dev *dev);
int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev);
int mlx5_sf_table_init(struct mlx5_core_dev *dev);
void mlx5_sf_notifiers_cleanup(struct mlx5_core_dev *dev);
void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev);
bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev);
+void mlx5_sf_table_esw_changed_event_handler(struct mlx5_core_dev *dev);
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *add_attr,
@@ -60,6 +62,11 @@ static inline void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev)
{
}
+static inline void
+mlx5_sf_hw_table_esw_changed_event_handler(struct mlx5_core_dev *dev)
+{
+}
+
static inline int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev)
{
return 0;
@@ -83,6 +90,11 @@ static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev)
return true;
}
+static inline void
+mlx5_sf_table_esw_changed_event_handler(struct mlx5_core_dev *dev)
+{
+}
+
#endif
#endif
base-commit: 3bd438a58e910db5dc369aa25dfed1fc95f1b596
--
2.44.0
next reply other threads:[~2026-07-29 7:16 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-29 7:16 Tariq Toukan [this message]
2026-08-01 1:40 ` [PATCH net] net/mlx5: SF, Handle function changed event 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=20260729071622.2423270-1-tariqt@nvidia.com \
--to=tariqt@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=cjubran@nvidia.com \
--cc=cmi@nvidia.com \
--cc=cratiu@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gal@nvidia.com \
--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=pabeni@redhat.com \
--cc=parav@nvidia.com \
--cc=saeedm@nvidia.com \
--cc=shayd@nvidia.com \
--cc=vuhuong@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