Skip to content

Commit a254c26

Browse files
Moshe Shemeshkuba-moo
authored andcommitted
devlink: Add reload stats
Add reload stats to hold the history per reload action type and limit. For example, the number of times fw_activate has been performed on this device since the driver module was added or if the firmware activation was performed with or without reset. Add devlink notification on stats update. Expose devlink reload stats to the user through devlink dev get command. Examples: $ devlink dev show pci/0000:82:00.0: stats: reload: driver_reinit 2 fw_activate 1 fw_activate_no_reset 0 pci/0000:82:00.1: stats: reload: driver_reinit 1 fw_activate 0 fw_activate_no_reset 0 $ devlink dev show -jp { "dev": { "pci/0000:82:00.0": { "stats": { "reload": { "driver_reinit": 2, "fw_activate": 1, "fw_activate_no_reset": 0 } } }, "pci/0000:82:00.1": { "stats": { "reload": { "driver_reinit": 1, "fw_activate": 0, "fw_activate_no_reset": 0 } } } } } Signed-off-by: Moshe Shemesh <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent dc64cc7 commit a254c26

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

include/net/devlink.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
#include <uapi/linux/devlink.h>
2121
#include <linux/xarray.h>
2222

23+
#define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
24+
(__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
25+
26+
struct devlink_dev_stats {
27+
u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
28+
};
29+
2330
struct devlink_ops;
2431

2532
struct devlink {
@@ -38,6 +45,7 @@ struct devlink {
3845
struct list_head trap_policer_list;
3946
const struct devlink_ops *ops;
4047
struct xarray snapshot_ids;
48+
struct devlink_dev_stats stats;
4149
struct device *dev;
4250
possible_net_t _net;
4351
struct mutex lock; /* Serializes access to devlink instance specific objects such as

include/uapi/linux/devlink.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,12 @@ enum devlink_attr {
520520
DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, /* bitfield32 */
521521
DEVLINK_ATTR_RELOAD_LIMITS, /* bitfield32 */
522522

523+
DEVLINK_ATTR_DEV_STATS, /* nested */
524+
DEVLINK_ATTR_RELOAD_STATS, /* nested */
525+
DEVLINK_ATTR_RELOAD_STATS_ENTRY, /* nested */
526+
DEVLINK_ATTR_RELOAD_STATS_LIMIT, /* u8 */
527+
DEVLINK_ATTR_RELOAD_STATS_VALUE, /* u32 */
528+
523529
/* add new attributes above here, update the policy in devlink.c */
524530

525531
__DEVLINK_ATTR_MAX,

net/core/devlink.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,10 +517,66 @@ devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_l
517517
return test_bit(limit, &devlink->ops->reload_limits);
518518
}
519519

520+
static int devlink_reload_stat_put(struct sk_buff *msg, enum devlink_reload_action action,
521+
enum devlink_reload_limit limit, u32 value)
522+
{
523+
struct nlattr *reload_stats_entry;
524+
525+
reload_stats_entry = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS_ENTRY);
526+
if (!reload_stats_entry)
527+
return -EMSGSIZE;
528+
529+
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, action) ||
530+
nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
531+
nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
532+
goto nla_put_failure;
533+
nla_nest_end(msg, reload_stats_entry);
534+
return 0;
535+
536+
nla_put_failure:
537+
nla_nest_cancel(msg, reload_stats_entry);
538+
return -EMSGSIZE;
539+
}
540+
541+
static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink)
542+
{
543+
struct nlattr *reload_stats_attr;
544+
int i, j, stat_idx;
545+
u32 value;
546+
547+
reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS);
548+
549+
if (!reload_stats_attr)
550+
return -EMSGSIZE;
551+
552+
for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
553+
if (j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
554+
!devlink_reload_limit_is_supported(devlink, j))
555+
continue;
556+
for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
557+
if (!devlink_reload_action_is_supported(devlink, i) ||
558+
devlink_reload_combination_is_invalid(i, j))
559+
continue;
560+
561+
stat_idx = j * __DEVLINK_RELOAD_ACTION_MAX + i;
562+
value = devlink->stats.reload_stats[stat_idx];
563+
if (devlink_reload_stat_put(msg, i, j, value))
564+
goto nla_put_failure;
565+
}
566+
}
567+
nla_nest_end(msg, reload_stats_attr);
568+
return 0;
569+
570+
nla_put_failure:
571+
nla_nest_cancel(msg, reload_stats_attr);
572+
return -EMSGSIZE;
573+
}
574+
520575
static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
521576
enum devlink_command cmd, u32 portid,
522577
u32 seq, int flags)
523578
{
579+
struct nlattr *dev_stats;
524580
void *hdr;
525581

526582
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
@@ -532,9 +588,19 @@ static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
532588
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
533589
goto nla_put_failure;
534590

591+
dev_stats = nla_nest_start(msg, DEVLINK_ATTR_DEV_STATS);
592+
if (!dev_stats)
593+
goto nla_put_failure;
594+
595+
if (devlink_reload_stats_put(msg, devlink))
596+
goto dev_stats_nest_cancel;
597+
598+
nla_nest_end(msg, dev_stats);
535599
genlmsg_end(msg, hdr);
536600
return 0;
537601

602+
dev_stats_nest_cancel:
603+
nla_nest_cancel(msg, dev_stats);
538604
nla_put_failure:
539605
genlmsg_cancel(msg, hdr);
540606
return -EMSGSIZE;
@@ -3021,6 +3087,29 @@ bool devlink_is_reload_failed(const struct devlink *devlink)
30213087
}
30223088
EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
30233089

3090+
static void
3091+
__devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
3092+
enum devlink_reload_limit limit, u32 actions_performed)
3093+
{
3094+
unsigned long actions = actions_performed;
3095+
int stat_idx;
3096+
int action;
3097+
3098+
for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
3099+
stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
3100+
reload_stats[stat_idx]++;
3101+
}
3102+
devlink_notify(devlink, DEVLINK_CMD_NEW);
3103+
}
3104+
3105+
static void
3106+
devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
3107+
u32 actions_performed)
3108+
{
3109+
__devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
3110+
actions_performed);
3111+
}
3112+
30243113
static int devlink_reload(struct devlink *devlink, struct net *dest_net,
30253114
enum devlink_reload_action action, enum devlink_reload_limit limit,
30263115
u32 *actions_performed, struct netlink_ext_ack *extack)
@@ -3043,6 +3132,7 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
30433132
return err;
30443133

30453134
WARN_ON(!(*actions_performed & BIT(action)));
3135+
devlink_reload_stats_update(devlink, limit, *actions_performed);
30463136
return 0;
30473137
}
30483138

0 commit comments

Comments
 (0)