Implement support for devlink health reporters on per-port basis. First
part in the series prepares common functions parts for health reporter
implementation. Second introduces required API to devlink-health and
mlx5e ones demonstrate its usage and effectively implement the feature
for mlx5 driver.
The per-port reporter functionality is achieved by adding a list of
devlink_health_reporters to devlink_port struct in a manner similar to
existing device infrastructure. This is the only major difference and
it makes possible to fully reuse device reporters operations.
The effect will be seen in conjunction with iproute2 additions and
will affect all devlink health commands. User can distinguish between
device and port reporters by looking at a devlink handle. Port reporters
have a port index at the end of the address and such addresses can be
provided as a parameter in every place where devlink-health accepted it.
These can be obtained from devlink port show command.
For example:
$ devlink health show
pci/0000:00:0a.0:
reporter fw
state healthy error 0 recover 0 auto_dump true
pci/0000:00:0a.0/1:
reporter tx
state healthy error 0 recover 0 grace_period 500 auto_recover true auto_dump true
$ devlink health set pci/0000:00:0a.0/1 reporter tx grace_period 1000 \
auto_recover false auto_dump false
$ devlink health show pci/0000:00:0a.0/1 reporter tx
pci/0000:00:0a.0/1:
reporter tx
state healthy error 0 recover 0 grace_period 1000 auto_recover flase auto_dump false
Changes v1 -> v2:
Fixed functions comment to match parameters list.
Vladyslav Tarasiuk (7):
devlink: Refactor devlink health reporter constructor
devlink: Rework devlink health reporter destructor
devlink: Create generic devlink health reporter search function
devlink: Implement devlink health reporters on per-port basis
devlink: Add devlink health port reporters API
net/mlx5e: Move devlink port register and unregister calls
net/mlx5e: Move devlink-health rx and tx reporters to devlink port
.../ethernet/mellanox/mlx5/core/en/reporter_rx.c | 9 +-
.../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 13 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 +-
include/net/devlink.h | 11 +
net/core/devlink.c | 244 ++++++++++++++++-----
5 files changed, 216 insertions(+), 76 deletions(-)
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Prepare a common routine in devlink_health_reporter_create() for usage
in similar functions for devlink port health reporters.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
net/core/devlink.c | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 6ae3680..dfd7fe2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5295,6 +5295,31 @@ struct devlink_health_reporter {
return NULL;
}
+static struct devlink_health_reporter *
+__devlink_health_reporter_create(struct devlink *devlink,
+ const struct devlink_health_reporter_ops *ops,
+ u64 graceful_period, void *priv)
+{
+ struct devlink_health_reporter *reporter;
+
+ if (WARN_ON(graceful_period && !ops->recover))
+ return ERR_PTR(-EINVAL);
+
+ reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
+ if (!reporter)
+ return ERR_PTR(-ENOMEM);
+
+ reporter->priv = priv;
+ reporter->ops = ops;
+ reporter->devlink = devlink;
+ reporter->graceful_period = graceful_period;
+ reporter->auto_recover = !!ops->recover;
+ reporter->auto_dump = !!ops->dump;
+ mutex_init(&reporter->dump_lock);
+ refcount_set(&reporter->refcount, 1);
+ return reporter;
+}
+
/**
* devlink_health_reporter_create - create devlink health reporter
*
@@ -5316,25 +5341,11 @@ struct devlink_health_reporter *
goto unlock;
}
- if (WARN_ON(graceful_period && !ops->recover)) {
- reporter = ERR_PTR(-EINVAL);
+ reporter = __devlink_health_reporter_create(devlink, ops,
+ graceful_period, priv);
+ if (IS_ERR(reporter))
goto unlock;
- }
-
- reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
- if (!reporter) {
- reporter = ERR_PTR(-ENOMEM);
- goto unlock;
- }
- reporter->priv = priv;
- reporter->ops = ops;
- reporter->devlink = devlink;
- reporter->graceful_period = graceful_period;
- reporter->auto_recover = !!ops->recover;
- reporter->auto_dump = !!ops->dump;
- mutex_init(&reporter->dump_lock);
- refcount_set(&reporter->refcount, 1);
list_add_tail(&reporter->list, &devlink->reporter_list);
unlock:
mutex_unlock(&devlink->reporters_lock);
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Utilize new devlink-health port reporters API to move rx and tx
reporters from device to port.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c | 9 +++------
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 13 ++++---------
2 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
index c209579..35df79d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
@@ -565,13 +565,10 @@ void mlx5e_reporter_icosq_cqe_err(struct mlx5e_icosq *icosq)
int mlx5e_reporter_rx_create(struct mlx5e_priv *priv)
{
- struct devlink *devlink = priv_to_devlink(priv->mdev);
struct devlink_health_reporter *reporter;
- reporter = devlink_health_reporter_create(devlink,
- &mlx5_rx_reporter_ops,
- MLX5E_REPORTER_RX_GRACEFUL_PERIOD,
- priv);
+ reporter = devlink_port_health_reporter_create(&priv->dl_port, &mlx5_rx_reporter_ops,
+ MLX5E_REPORTER_RX_GRACEFUL_PERIOD, priv);
if (IS_ERR(reporter)) {
netdev_warn(priv->netdev, "Failed to create rx reporter, err = %ld\n",
PTR_ERR(reporter));
@@ -586,5 +583,5 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
if (!priv->rx_reporter)
return;
- devlink_health_reporter_destroy(priv->rx_reporter);
+ devlink_port_health_reporter_destroy(priv->rx_reporter);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
index 9805fc0..917aef9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
@@ -409,14 +409,9 @@ int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq)
int mlx5e_reporter_tx_create(struct mlx5e_priv *priv)
{
struct devlink_health_reporter *reporter;
- struct mlx5_core_dev *mdev = priv->mdev;
- struct devlink *devlink;
-
- devlink = priv_to_devlink(mdev);
- reporter =
- devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops,
- MLX5_REPORTER_TX_GRACEFUL_PERIOD,
- priv);
+
+ reporter = devlink_port_health_reporter_create(&priv->dl_port, &mlx5_tx_reporter_ops,
+ MLX5_REPORTER_TX_GRACEFUL_PERIOD, priv);
if (IS_ERR(reporter)) {
netdev_warn(priv->netdev,
"Failed to create tx reporter, err = %ld\n",
@@ -432,5 +427,5 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
if (!priv->tx_reporter)
return;
- devlink_health_reporter_destroy(priv->tx_reporter);
+ devlink_port_health_reporter_destroy(priv->tx_reporter);
}
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Add devlink-health reporter support on per-port basis.
The main difference existing devlink-health is that port reporters are
stored in per-devlink_port lists. Upon creation of such health reporter the
reference to a port it belongs to is stored in reporter struct.
Fill the port index attribute in devlink-health response to
allow devlink userspace utility to distinguish between device and port
reporters.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
include/net/devlink.h | 2 ++
net/core/devlink.c | 94 +++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 79 insertions(+), 17 deletions(-)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 428f55f..d3ac152 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -91,6 +91,8 @@ struct devlink_port {
void *type_dev;
struct devlink_port_attrs attrs;
struct delayed_work type_warn_dw;
+ struct list_head reporter_list;
+ struct mutex reporters_lock; /* Protects reporter_list */
};
struct devlink_sb_pool_info {
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 98e6911..8aedd20 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -386,19 +386,21 @@ struct devlink_snapshot {
return NULL;
}
-#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
-#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
-#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
+#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
+#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
+#define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(2)
+#define DEVLINK_NL_FLAG_NEED_SB BIT(3)
/* The per devlink instance lock is taken by default in the pre-doit
* operation, yet several commands do not require this. The global
* devlink lock is taken and protects from disruption by user-calls.
*/
-#define DEVLINK_NL_FLAG_NO_LOCK BIT(3)
+#define DEVLINK_NL_FLAG_NO_LOCK BIT(4)
static int devlink_nl_pre_doit(const struct genl_ops *ops,
struct sk_buff *skb, struct genl_info *info)
{
+ struct devlink_port *devlink_port;
struct devlink *devlink;
int err;
@@ -413,14 +415,17 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops,
if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
info->user_ptr[0] = devlink;
} else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
- struct devlink_port *devlink_port;
-
devlink_port = devlink_port_get_from_info(devlink, info);
if (IS_ERR(devlink_port)) {
err = PTR_ERR(devlink_port);
goto unlock;
}
info->user_ptr[0] = devlink_port;
+ } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT) {
+ info->user_ptr[0] = devlink;
+ devlink_port = devlink_port_get_from_info(devlink, info);
+ if (!IS_ERR(devlink_port))
+ info->user_ptr[1] = devlink_port;
}
if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
struct devlink_sb *devlink_sb;
@@ -5261,6 +5266,7 @@ struct devlink_health_reporter {
void *priv;
const struct devlink_health_reporter_ops *ops;
struct devlink *devlink;
+ struct devlink_port *devlink_port;
struct devlink_fmsg *dump_fmsg;
struct mutex dump_lock; /* lock parallel read/write from dump buffers */
u64 graceful_period;
@@ -5306,6 +5312,15 @@ struct devlink_health_reporter {
}
static struct devlink_health_reporter *
+devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
+ const char *reporter_name)
+{
+ return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
+ &devlink_port->reporters_lock,
+ reporter_name);
+}
+
+static struct devlink_health_reporter *
__devlink_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
@@ -5417,6 +5432,10 @@ struct devlink_health_reporter *
if (devlink_nl_put_handle(msg, devlink))
goto genlmsg_cancel;
+ if (reporter->devlink_port) {
+ if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, reporter->devlink_port->index))
+ goto genlmsg_cancel;
+ }
reporter_attr = nla_nest_start_noflag(msg,
DEVLINK_ATTR_HEALTH_REPORTER);
if (!reporter_attr)
@@ -5624,17 +5643,28 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
struct nlattr **attrs)
{
struct devlink_health_reporter *reporter;
+ struct devlink_port *devlink_port;
char *reporter_name;
if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
return NULL;
reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
- mutex_lock(&devlink->reporters_lock);
- reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
- if (reporter)
- refcount_inc(&reporter->refcount);
- mutex_unlock(&devlink->reporters_lock);
+ devlink_port = devlink_port_get_from_attrs(devlink, attrs);
+ if (IS_ERR(devlink_port)) {
+ mutex_lock(&devlink->reporters_lock);
+ reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
+ if (reporter)
+ refcount_inc(&reporter->refcount);
+ mutex_unlock(&devlink->reporters_lock);
+ } else {
+ mutex_lock(&devlink_port->reporters_lock);
+ reporter = devlink_port_health_reporter_find_by_name(devlink_port, reporter_name);
+ if (reporter)
+ refcount_inc(&reporter->refcount);
+ mutex_unlock(&devlink_port->reporters_lock);
+ }
+
return reporter;
}
@@ -5722,6 +5752,7 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
struct netlink_callback *cb)
{
struct devlink_health_reporter *reporter;
+ struct devlink_port *port;
struct devlink *devlink;
int start = cb->args[0];
int idx = 0;
@@ -5752,6 +5783,31 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
}
mutex_unlock(&devlink->reporters_lock);
}
+
+ list_for_each_entry(devlink, &devlink_list, list) {
+ if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+ continue;
+ list_for_each_entry(port, &devlink->port_list, list) {
+ mutex_lock(&port->reporters_lock);
+ list_for_each_entry(reporter, &port->reporter_list, list) {
+ if (idx < start) {
+ idx++;
+ continue;
+ }
+ err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
+ DEVLINK_CMD_HEALTH_REPORTER_GET,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ NLM_F_MULTI);
+ if (err) {
+ mutex_unlock(&port->reporters_lock);
+ goto out;
+ }
+ idx++;
+ }
+ mutex_unlock(&port->reporters_lock);
+ }
+ }
out:
mutex_unlock(&devlink_mutex);
@@ -7131,7 +7187,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_get_doit,
.dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
/* can be retrieved by unprivileged users */
},
@@ -7140,7 +7196,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_set_doit,
.flags = GENL_ADMIN_PERM,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{
@@ -7148,7 +7204,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_recover_doit,
.flags = GENL_ADMIN_PERM,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{
@@ -7156,7 +7212,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_diagnose_doit,
.flags = GENL_ADMIN_PERM,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{
@@ -7165,7 +7221,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
GENL_DONT_VALIDATE_DUMP_STRICT,
.dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
.flags = GENL_ADMIN_PERM,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{
@@ -7173,7 +7229,7 @@ static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
.flags = GENL_ADMIN_PERM,
- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{
@@ -7433,6 +7489,8 @@ int devlink_port_register(struct devlink *devlink,
list_add_tail(&devlink_port->list, &devlink->port_list);
INIT_LIST_HEAD(&devlink_port->param_list);
mutex_unlock(&devlink->lock);
+ INIT_LIST_HEAD(&devlink_port->reporter_list);
+ mutex_init(&devlink_port->reporters_lock);
INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
devlink_port_type_warn_schedule(devlink_port);
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
@@ -7449,6 +7507,8 @@ void devlink_port_unregister(struct devlink_port *devlink_port)
{
struct devlink *devlink = devlink_port->devlink;
+ WARN_ON(!list_empty(&devlink_port->reporter_list));
+ mutex_destroy(&devlink_port->reporters_lock);
devlink_port_type_warn_cancel(devlink_port);
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
mutex_lock(&devlink->lock);
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Devlink keeps its own reference to every reporter in a list and inits
refcount to 1 upon reporter's creation. Existing destructor waits to
free the memory indefinitely using msleep() until all references except
devlink's own are put.
Rework this mechanism by moving memory free routine to a separate
function, which is called when the last reporter reference is put.
Besides, it allows to call __devlink_health_reporter_destroy() while
locked on a reporters list mutex in symmetry to
__devlink_health_reporter_create(), which is required in follow-up
patch.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
net/core/devlink.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index dfd7fe2..dcf8006 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5353,6 +5353,29 @@ struct devlink_health_reporter *
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
+static void
+devlink_health_reporter_free(struct devlink_health_reporter *reporter)
+{
+ mutex_destroy(&reporter->dump_lock);
+ if (reporter->dump_fmsg)
+ devlink_fmsg_free(reporter->dump_fmsg);
+ kfree(reporter);
+}
+
+static void
+devlink_health_reporter_put(struct devlink_health_reporter *reporter)
+{
+ if (refcount_dec_and_test(&reporter->refcount))
+ devlink_health_reporter_free(reporter);
+}
+
+static void
+__devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
+{
+ list_del(&reporter->list);
+ devlink_health_reporter_put(reporter);
+}
+
/**
* devlink_health_reporter_destroy - destroy devlink health reporter
*
@@ -5362,14 +5385,8 @@ struct devlink_health_reporter *
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
mutex_lock(&reporter->devlink->reporters_lock);
- list_del(&reporter->list);
+ __devlink_health_reporter_destroy(reporter);
mutex_unlock(&reporter->devlink->reporters_lock);
- while (refcount_read(&reporter->refcount) > 1)
- msleep(100);
- mutex_destroy(&reporter->dump_lock);
- if (reporter->dump_fmsg)
- devlink_fmsg_free(reporter->dump_fmsg);
- kfree(reporter);
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
@@ -5639,12 +5656,6 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
return NULL;
}
-static void
-devlink_health_reporter_put(struct devlink_health_reporter *reporter)
-{
- refcount_dec(&reporter->refcount);
-}
-
void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state)
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
In order to use new devlink port health reporters infrastructure, add
corresponding constructor and destructor functions.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
include/net/devlink.h | 9 +++++++++
net/core/devlink.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index d3ac152..2082062 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1336,9 +1336,18 @@ struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv);
+
+struct devlink_health_reporter *
+devlink_port_health_reporter_create(struct devlink_port *port,
+ const struct devlink_health_reporter_ops *ops,
+ u64 graceful_period, void *priv);
+
void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter);
+void
+devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter);
+
void *
devlink_health_reporter_priv(struct devlink_health_reporter *reporter);
int devlink_health_report(struct devlink_health_reporter *reporter,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 8aedd20..b7aa194 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5346,6 +5346,42 @@ struct devlink_health_reporter {
}
/**
+ * devlink_port_health_reporter_create - create devlink health reporter for
+ * specified port instance
+ *
+ * @port: devlink_port which should contain the new reporter
+ * @ops: ops
+ * @graceful_period: to avoid recovery loops, in msecs
+ * @priv: priv
+ */
+struct devlink_health_reporter *
+devlink_port_health_reporter_create(struct devlink_port *port,
+ const struct devlink_health_reporter_ops *ops,
+ u64 graceful_period, void *priv)
+{
+ struct devlink_health_reporter *reporter;
+
+ mutex_lock(&port->reporters_lock);
+ if (__devlink_health_reporter_find_by_name(&port->reporter_list,
+ &port->reporters_lock, ops->name)) {
+ reporter = ERR_PTR(-EEXIST);
+ goto unlock;
+ }
+
+ reporter = __devlink_health_reporter_create(port->devlink, ops,
+ graceful_period, priv);
+ if (IS_ERR(reporter))
+ goto unlock;
+
+ reporter->devlink_port = port;
+ list_add_tail(&reporter->list, &port->reporter_list);
+unlock:
+ mutex_unlock(&port->reporters_lock);
+ return reporter;
+}
+EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
+
+/**
* devlink_health_reporter_create - create devlink health reporter
*
* @devlink: devlink
@@ -5415,6 +5451,20 @@ struct devlink_health_reporter *
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
+/**
+ * devlink_port_health_reporter_destroy - destroy devlink port health reporter
+ *
+ * @reporter: devlink health reporter to destroy
+ */
+void
+devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter)
+{
+ mutex_lock(&reporter->devlink_port->reporters_lock);
+ __devlink_health_reporter_destroy(reporter);
+ mutex_unlock(&reporter->devlink_port->reporters_lock);
+}
+EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy);
+
static int
devlink_nl_health_reporter_fill(struct sk_buff *msg,
struct devlink *devlink,
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Register devlink ports upon NIC init. TX and RX health reporters handle
errors which may occur early on at driver initialization. And because
these reporters are to be moved to port context, they require devlink
ports to be already registered.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 046cfb0..f080c5a4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -5096,6 +5096,9 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
if (err)
mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
mlx5e_build_nic_netdev(netdev);
+ err = mlx5e_devlink_port_register(priv);
+ if (err)
+ mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
mlx5e_health_create_reporters(priv);
return 0;
@@ -5104,6 +5107,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
{
mlx5e_health_destroy_reporters(priv);
+ mlx5e_devlink_port_unregister(priv);
mlx5e_tls_cleanup(priv);
mlx5e_ipsec_cleanup(priv);
mlx5e_netdev_cleanup(priv->netdev, priv);
@@ -5536,16 +5540,10 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
goto err_destroy_netdev;
}
- err = mlx5e_devlink_port_register(priv);
- if (err) {
- mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
- goto err_detach;
- }
-
err = register_netdev(netdev);
if (err) {
mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
- goto err_devlink_port_unregister;
+ goto err_detach;
}
mlx5e_devlink_port_type_eth_set(priv);
@@ -5553,8 +5551,6 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
mlx5e_dcbnl_init_app(priv);
return priv;
-err_devlink_port_unregister:
- mlx5e_devlink_port_unregister(priv);
err_detach:
mlx5e_detach(mdev, priv);
err_destroy_netdev:
@@ -5575,7 +5571,6 @@ static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
priv = vpriv;
mlx5e_dcbnl_delete_app(priv);
unregister_netdev(priv->netdev);
- mlx5e_devlink_port_unregister(priv);
mlx5e_detach(mdev, vpriv);
mlx5e_destroy_netdev(priv);
}
--
1.8.3.1
From: Vladyslav Tarasiuk <[email protected]>
Add a generic __devlink_health_reporter_find_by_name() that can be used
with arbitrary devlink health reporter list.
Signed-off-by: Vladyslav Tarasiuk <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
---
net/core/devlink.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index dcf8006..98e6911 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5283,19 +5283,29 @@ struct devlink_health_reporter {
EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
static struct devlink_health_reporter *
-devlink_health_reporter_find_by_name(struct devlink *devlink,
- const char *reporter_name)
+__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
+ struct mutex *list_lock,
+ const char *reporter_name)
{
struct devlink_health_reporter *reporter;
- lockdep_assert_held(&devlink->reporters_lock);
- list_for_each_entry(reporter, &devlink->reporter_list, list)
+ lockdep_assert_held(list_lock);
+ list_for_each_entry(reporter, reporter_list, list)
if (!strcmp(reporter->ops->name, reporter_name))
return reporter;
return NULL;
}
static struct devlink_health_reporter *
+devlink_health_reporter_find_by_name(struct devlink *devlink,
+ const char *reporter_name)
+{
+ return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
+ &devlink->reporters_lock,
+ reporter_name);
+}
+
+static struct devlink_health_reporter *
__devlink_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
--
1.8.3.1
On Fri, 3 Jul 2020 06:27:31 +0300 Moshe Shemesh wrote:
> Implement support for devlink health reporters on per-port basis. First
> part in the series prepares common functions parts for health reporter
> implementation. Second introduces required API to devlink-health and
> mlx5e ones demonstrate its usage and effectively implement the feature
> for mlx5 driver.
> The per-port reporter functionality is achieved by adding a list of
> devlink_health_reporters to devlink_port struct in a manner similar to
> existing device infrastructure. This is the only major difference and
> it makes possible to fully reuse device reporters operations.
> The effect will be seen in conjunction with iproute2 additions and
> will affect all devlink health commands. User can distinguish between
> device and port reporters by looking at a devlink handle. Port reporters
> have a port index at the end of the address and such addresses can be
> provided as a parameter in every place where devlink-health accepted it.
> These can be obtained from devlink port show command.
> For example:
> $ devlink health show
> pci/0000:00:0a.0:
> reporter fw
> state healthy error 0 recover 0 auto_dump true
> pci/0000:00:0a.0/1:
> reporter tx
> state healthy error 0 recover 0 grace_period 500 auto_recover true auto_dump true
> $ devlink health set pci/0000:00:0a.0/1 reporter tx grace_period 1000 \
> auto_recover false auto_dump false
> $ devlink health show pci/0000:00:0a.0/1 reporter tx
> pci/0000:00:0a.0/1:
> reporter tx
> state healthy error 0 recover 0 grace_period 1000 auto_recover flase auto_dump false
What's the motivation, though?
This patch series achieves nothing that couldn't be previously achieved.
Is there no concern of uAPI breakage with moving the existing health
reporters in patch 7?
Sat, Jul 04, 2020 at 01:44:39AM CEST, [email protected] wrote:
>On Fri, 3 Jul 2020 06:27:31 +0300 Moshe Shemesh wrote:
>> Implement support for devlink health reporters on per-port basis. First
>> part in the series prepares common functions parts for health reporter
>> implementation. Second introduces required API to devlink-health and
>> mlx5e ones demonstrate its usage and effectively implement the feature
>> for mlx5 driver.
>> The per-port reporter functionality is achieved by adding a list of
>> devlink_health_reporters to devlink_port struct in a manner similar to
>> existing device infrastructure. This is the only major difference and
>> it makes possible to fully reuse device reporters operations.
>> The effect will be seen in conjunction with iproute2 additions and
>> will affect all devlink health commands. User can distinguish between
>> device and port reporters by looking at a devlink handle. Port reporters
>> have a port index at the end of the address and such addresses can be
>> provided as a parameter in every place where devlink-health accepted it.
>> These can be obtained from devlink port show command.
>> For example:
>> $ devlink health show
>> pci/0000:00:0a.0:
>> reporter fw
>> state healthy error 0 recover 0 auto_dump true
>> pci/0000:00:0a.0/1:
>> reporter tx
>> state healthy error 0 recover 0 grace_period 500 auto_recover true auto_dump true
>> $ devlink health set pci/0000:00:0a.0/1 reporter tx grace_period 1000 \
>> auto_recover false auto_dump false
>> $ devlink health show pci/0000:00:0a.0/1 reporter tx
>> pci/0000:00:0a.0/1:
>> reporter tx
>> state healthy error 0 recover 0 grace_period 1000 auto_recover flase auto_dump false
>
>What's the motivation, though?
>
>This patch series achieves nothing that couldn't be previously achieved.
Well, not really. If you have 2 ports, you have 2 set's of tx/rx health
reporters. Cannot achieve that w/o per-port health reporters.
>
>Is there no concern of uAPI breakage with moving the existing health
>reporters in patch 7?
No. This is bug by design that we are fixing now. No other way around :/
This is mlx5 only.
On Sat, 4 Jul 2020 16:16:42 +0200 Jiri Pirko wrote:
> Sat, Jul 04, 2020 at 01:44:39AM CEST, [email protected] wrote:
> >On Fri, 3 Jul 2020 06:27:31 +0300 Moshe Shemesh wrote:
> >> Implement support for devlink health reporters on per-port basis. First
> >> part in the series prepares common functions parts for health reporter
> >> implementation. Second introduces required API to devlink-health and
> >> mlx5e ones demonstrate its usage and effectively implement the feature
> >> for mlx5 driver.
> >> The per-port reporter functionality is achieved by adding a list of
> >> devlink_health_reporters to devlink_port struct in a manner similar to
> >> existing device infrastructure. This is the only major difference and
> >> it makes possible to fully reuse device reporters operations.
> >> The effect will be seen in conjunction with iproute2 additions and
> >> will affect all devlink health commands. User can distinguish between
> >> device and port reporters by looking at a devlink handle. Port reporters
> >> have a port index at the end of the address and such addresses can be
> >> provided as a parameter in every place where devlink-health accepted it.
> >> These can be obtained from devlink port show command.
> >> For example:
> >> $ devlink health show
> >> pci/0000:00:0a.0:
> >> reporter fw
> >> state healthy error 0 recover 0 auto_dump true
> >> pci/0000:00:0a.0/1:
> >> reporter tx
> >> state healthy error 0 recover 0 grace_period 500 auto_recover true auto_dump true
> >> $ devlink health set pci/0000:00:0a.0/1 reporter tx grace_period 1000 \
> >> auto_recover false auto_dump false
> >> $ devlink health show pci/0000:00:0a.0/1 reporter tx
> >> pci/0000:00:0a.0/1:
> >> reporter tx
> >> state healthy error 0 recover 0 grace_period 1000 auto_recover flase auto_dump false
> >
> >What's the motivation, though?
> >
> >This patch series achieves nothing that couldn't be previously achieved.
>
> Well, not really. If you have 2 ports, you have 2 set's of tx/rx health
> reporters. Cannot achieve that w/o per-port health reporters.
Which mlx5 doesn't. Each port has its own instance of devlink today.
> >Is there no concern of uAPI breakage with moving the existing health
> >reporters in patch 7?
>
> No. This is bug by design that we are fixing now. No other way around :/
> This is mlx5 only.
Please repost including in the cover letter a proper an explanation of
why the change is necessary, what benefits it will bring us, what are
next steps, and why it doesn't matter much that the health reporters
move for mlx5.
The cover letter describes code not reasoning, which is IMHO
unacceptable for patches that "change" uAPI.
On 7/5/2020 7:48 PM, Jakub Kicinski wrote:
> On Sat, 4 Jul 2020 16:16:42 +0200 Jiri Pirko wrote:
>> Sat, Jul 04, 2020 at 01:44:39AM CEST, [email protected] wrote:
>>> On Fri, 3 Jul 2020 06:27:31 +0300 Moshe Shemesh wrote:
>>>> Implement support for devlink health reporters on per-port basis. First
>>>> part in the series prepares common functions parts for health reporter
>>>> implementation. Second introduces required API to devlink-health and
>>>> mlx5e ones demonstrate its usage and effectively implement the feature
>>>> for mlx5 driver.
>>>> The per-port reporter functionality is achieved by adding a list of
>>>> devlink_health_reporters to devlink_port struct in a manner similar to
>>>> existing device infrastructure. This is the only major difference and
>>>> it makes possible to fully reuse device reporters operations.
>>>> The effect will be seen in conjunction with iproute2 additions and
>>>> will affect all devlink health commands. User can distinguish between
>>>> device and port reporters by looking at a devlink handle. Port reporters
>>>> have a port index at the end of the address and such addresses can be
>>>> provided as a parameter in every place where devlink-health accepted it.
>>>> These can be obtained from devlink port show command.
>>>> For example:
>>>> $ devlink health show
>>>> pci/0000:00:0a.0:
>>>> reporter fw
>>>> state healthy error 0 recover 0 auto_dump true
>>>> pci/0000:00:0a.0/1:
>>>> reporter tx
>>>> state healthy error 0 recover 0 grace_period 500 auto_recover true auto_dump true
>>>> $ devlink health set pci/0000:00:0a.0/1 reporter tx grace_period 1000 \
>>>> auto_recover false auto_dump false
>>>> $ devlink health show pci/0000:00:0a.0/1 reporter tx
>>>> pci/0000:00:0a.0/1:
>>>> reporter tx
>>>> state healthy error 0 recover 0 grace_period 1000 auto_recover flase auto_dump false
>>> What's the motivation, though?
>>>
>>> This patch series achieves nothing that couldn't be previously achieved.
>> Well, not really. If you have 2 ports, you have 2 set's of tx/rx health
>> reporters. Cannot achieve that w/o per-port health reporters.
> Which mlx5 doesn't. Each port has its own instance of devlink today.
That's right for mlx5, but in the general case Tx and Rx should be per
port and not per device.
Better to fix the API before more drivers use it for such reporters.
>>> Is there no concern of uAPI breakage with moving the existing health
>>> reporters in patch 7?
>> No. This is bug by design that we are fixing now. No other way around :/
>> This is mlx5 only.
> Please repost including in the cover letter a proper an explanation of
> why the change is necessary, what benefits it will bring us, what are
> next steps, and why it doesn't matter much that the health reporters
> move for mlx5.
>
> The cover letter describes code not reasoning, which is IMHO
> unacceptable for patches that "change" uAPI.
Sure, will fix and resend.