Commit b4740e3a authored by Moshe Shemesh's avatar Moshe Shemesh Committed by Jakub Kicinski

devlink: Split out health reporter create code

Move devlink health reporter create/destroy and related dev code to new
file health.c. This file shall include all callbacks and functionality
that are related to devlink health.

In addition, fix kdoc indentation and make reporter create/destroy kdoc
more clear. No functional change in this patch.
Signed-off-by: default avatarMoshe Shemesh <moshe@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b6a4103c
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-y := leftover.o core.o netlink.o dev.o obj-y := leftover.o core.o netlink.o dev.o health.o
...@@ -198,6 +198,34 @@ int devlink_resources_validate(struct devlink *devlink, ...@@ -198,6 +198,34 @@ int devlink_resources_validate(struct devlink *devlink,
struct devlink_resource *resource, struct devlink_resource *resource,
struct genl_info *info); struct genl_info *info);
/* Health */
struct devlink_health_reporter {
struct list_head list;
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;
bool auto_recover;
bool auto_dump;
u8 health_state;
u64 dump_ts;
u64 dump_real_ts;
u64 error_count;
u64 recovery_count;
u64 last_recovery_ts;
};
struct devlink_health_reporter *
devlink_health_reporter_find_by_name(struct devlink *devlink,
const char *reporter_name);
struct devlink_health_reporter *
devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
const char *reporter_name);
void devlink_fmsg_free(struct devlink_fmsg *fmsg);
/* Line cards */ /* Line cards */
struct devlink_linecard; struct devlink_linecard;
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
*/
#include <net/genetlink.h>
#include "devl_internal.h"
void *
devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
{
return reporter->priv;
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
static struct devlink_health_reporter *
__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
const char *reporter_name)
{
struct devlink_health_reporter *reporter;
list_for_each_entry(reporter, reporter_list, list)
if (!strcmp(reporter->ops->name, reporter_name))
return reporter;
return NULL;
}
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,
reporter_name);
}
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,
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)
{
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);
return reporter;
}
/**
* devl_port_health_reporter_create() - create devlink health reporter for
* specified port instance
*
* @port: devlink_port to which health reports will relate
* @ops: devlink health reporter ops
* @graceful_period: min time (in msec) between recovery attempts
* @priv: driver priv pointer
*/
struct devlink_health_reporter *
devl_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;
devl_assert_locked(port->devlink);
if (__devlink_health_reporter_find_by_name(&port->reporter_list,
ops->name))
return ERR_PTR(-EEXIST);
reporter = __devlink_health_reporter_create(port->devlink, ops,
graceful_period, priv);
if (IS_ERR(reporter))
return reporter;
reporter->devlink_port = port;
list_add_tail(&reporter->list, &port->reporter_list);
return reporter;
}
EXPORT_SYMBOL_GPL(devl_port_health_reporter_create);
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;
struct devlink *devlink = port->devlink;
devl_lock(devlink);
reporter = devl_port_health_reporter_create(port, ops,
graceful_period, priv);
devl_unlock(devlink);
return reporter;
}
EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
/**
* devl_health_reporter_create - create devlink health reporter
*
* @devlink: devlink instance which the health reports will relate
* @ops: devlink health reporter ops
* @graceful_period: min time (in msec) between recovery attempts
* @priv: driver priv pointer
*/
struct devlink_health_reporter *
devl_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
{
struct devlink_health_reporter *reporter;
devl_assert_locked(devlink);
if (devlink_health_reporter_find_by_name(devlink, ops->name))
return ERR_PTR(-EEXIST);
reporter = __devlink_health_reporter_create(devlink, ops,
graceful_period, priv);
if (IS_ERR(reporter))
return reporter;
list_add_tail(&reporter->list, &devlink->reporter_list);
return reporter;
}
EXPORT_SYMBOL_GPL(devl_health_reporter_create);
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;
devl_lock(devlink);
reporter = devl_health_reporter_create(devlink, ops,
graceful_period, priv);
devl_unlock(devlink);
return 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);
}
/**
* devl_health_reporter_destroy() - destroy devlink health reporter
*
* @reporter: devlink health reporter to destroy
*/
void
devl_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
devl_assert_locked(reporter->devlink);
list_del(&reporter->list);
devlink_health_reporter_free(reporter);
}
EXPORT_SYMBOL_GPL(devl_health_reporter_destroy);
void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
struct devlink *devlink = reporter->devlink;
devl_lock(devlink);
devl_health_reporter_destroy(reporter);
devl_unlock(devlink);
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
...@@ -5403,7 +5403,7 @@ static struct devlink_fmsg *devlink_fmsg_alloc(void) ...@@ -5403,7 +5403,7 @@ static struct devlink_fmsg *devlink_fmsg_alloc(void)
return fmsg; return fmsg;
} }
static void devlink_fmsg_free(struct devlink_fmsg *fmsg) void devlink_fmsg_free(struct devlink_fmsg *fmsg)
{ {
struct devlink_fmsg_item *item, *tmp; struct devlink_fmsg_item *item, *tmp;
...@@ -5963,213 +5963,6 @@ static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb, ...@@ -5963,213 +5963,6 @@ static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
return err; return err;
} }
struct devlink_health_reporter {
struct list_head list;
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;
bool auto_recover;
bool auto_dump;
u8 health_state;
u64 dump_ts;
u64 dump_real_ts;
u64 error_count;
u64 recovery_count;
u64 last_recovery_ts;
};
void *
devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
{
return reporter->priv;
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
static struct devlink_health_reporter *
__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
const char *reporter_name)
{
struct devlink_health_reporter *reporter;
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,
reporter_name);
}
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,
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)
{
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);
return reporter;
}
/**
* devl_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 *
devl_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;
devl_assert_locked(port->devlink);
if (__devlink_health_reporter_find_by_name(&port->reporter_list,
ops->name))
return ERR_PTR(-EEXIST);
reporter = __devlink_health_reporter_create(port->devlink, ops,
graceful_period, priv);
if (IS_ERR(reporter))
return reporter;
reporter->devlink_port = port;
list_add_tail(&reporter->list, &port->reporter_list);
return reporter;
}
EXPORT_SYMBOL_GPL(devl_port_health_reporter_create);
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;
struct devlink *devlink = port->devlink;
devl_lock(devlink);
reporter = devl_port_health_reporter_create(port, ops,
graceful_period, priv);
devl_unlock(devlink);
return reporter;
}
EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
/**
* devl_health_reporter_create - create devlink health reporter
*
* @devlink: devlink
* @ops: ops
* @graceful_period: to avoid recovery loops, in msecs
* @priv: priv
*/
struct devlink_health_reporter *
devl_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
{
struct devlink_health_reporter *reporter;
devl_assert_locked(devlink);
if (devlink_health_reporter_find_by_name(devlink, ops->name))
return ERR_PTR(-EEXIST);
reporter = __devlink_health_reporter_create(devlink, ops,
graceful_period, priv);
if (IS_ERR(reporter))
return reporter;
list_add_tail(&reporter->list, &devlink->reporter_list);
return reporter;
}
EXPORT_SYMBOL_GPL(devl_health_reporter_create);
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;
devl_lock(devlink);
reporter = devl_health_reporter_create(devlink, ops,
graceful_period, priv);
devl_unlock(devlink);
return 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);
}
/**
* devl_health_reporter_destroy - destroy devlink health reporter
*
* @reporter: devlink health reporter to destroy
*/
void
devl_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
devl_assert_locked(reporter->devlink);
list_del(&reporter->list);
devlink_health_reporter_free(reporter);
}
EXPORT_SYMBOL_GPL(devl_health_reporter_destroy);
void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
struct devlink *devlink = reporter->devlink;
devl_lock(devlink);
devl_health_reporter_destroy(reporter);
devl_unlock(devlink);
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
static int static int
devlink_nl_health_reporter_fill(struct sk_buff *msg, devlink_nl_health_reporter_fill(struct sk_buff *msg,
struct devlink_health_reporter *reporter, struct devlink_health_reporter *reporter,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment