devlink: Add dump support for device-level resources

Add dumpit handler for resource-dump command to iterate over all devlink
devices and show their resources.

  $ devlink resource show
  pci/0000:08:00.0:
    name local_max_SFs size 508 unit entry
    name external_max_SFs size 508 unit entry
  pci/0000:08:00.1:
    name local_max_SFs size 508 unit entry
    name external_max_SFs size 508 unit entry

Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260407194107.148063-6-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Or Har-Toov
2026-04-07 22:41:00 +03:00
committed by Jakub Kicinski
parent 085b234b28
commit 11636b550e
4 changed files with 102 additions and 5 deletions

View File

@@ -1764,13 +1764,17 @@ operations:
- bus-name
- dev-name
- index
reply:
reply: &resource-dump-reply
value: 36
attributes:
- bus-name
- dev-name
- index
- resource-list
dump:
request:
attributes: *dev-id-attrs
reply: *resource-dump-reply
-
name: reload

View File

@@ -305,7 +305,14 @@ static const struct nla_policy devlink_resource_set_nl_policy[DEVLINK_ATTR_INDEX
};
/* DEVLINK_CMD_RESOURCE_DUMP - do */
static const struct nla_policy devlink_resource_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
static const struct nla_policy devlink_resource_dump_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
};
/* DEVLINK_CMD_RESOURCE_DUMP - dump */
static const struct nla_policy devlink_resource_dump_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
@@ -680,7 +687,7 @@ static const struct nla_policy devlink_notify_filter_set_nl_policy[DEVLINK_ATTR_
};
/* Ops table for devlink */
const struct genl_split_ops devlink_nl_ops[74] = {
const struct genl_split_ops devlink_nl_ops[75] = {
{
.cmd = DEVLINK_CMD_GET,
.validate = GENL_DONT_VALIDATE_STRICT,
@@ -958,10 +965,17 @@ const struct genl_split_ops devlink_nl_ops[74] = {
.pre_doit = devlink_nl_pre_doit,
.doit = devlink_nl_resource_dump_doit,
.post_doit = devlink_nl_post_doit,
.policy = devlink_resource_dump_nl_policy,
.policy = devlink_resource_dump_do_nl_policy,
.maxattr = DEVLINK_ATTR_INDEX,
.flags = GENL_CMD_CAP_DO,
},
{
.cmd = DEVLINK_CMD_RESOURCE_DUMP,
.dumpit = devlink_nl_resource_dump_dumpit,
.policy = devlink_resource_dump_dump_nl_policy,
.maxattr = DEVLINK_ATTR_INDEX,
.flags = GENL_CMD_CAP_DUMP,
},
{
.cmd = DEVLINK_CMD_RELOAD,
.validate = GENL_DONT_VALIDATE_STRICT,

View File

@@ -18,7 +18,7 @@ extern const struct nla_policy devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_
extern const struct nla_policy devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_ID_FLASH + 1];
/* Ops table for devlink */
extern const struct genl_split_ops devlink_nl_ops[74];
extern const struct genl_split_ops devlink_nl_ops[75];
int devlink_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info);
@@ -80,6 +80,8 @@ int devlink_nl_dpipe_table_counters_set_doit(struct sk_buff *skb,
struct genl_info *info);
int devlink_nl_resource_set_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
struct netlink_callback *cb);
int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_param_get_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_param_get_dumpit(struct sk_buff *skb,

View File

@@ -223,6 +223,31 @@ static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
return -EMSGSIZE;
}
static int devlink_resource_list_fill(struct sk_buff *skb,
struct devlink *devlink,
struct list_head *resource_list_head,
int *idx)
{
struct devlink_resource *resource;
int i = 0;
int err;
list_for_each_entry(resource, resource_list_head, list) {
if (i < *idx) {
i++;
continue;
}
err = devlink_resource_put(devlink, skb, resource);
if (err) {
*idx = i;
return err;
}
i++;
}
*idx = 0;
return 0;
}
static int devlink_resource_fill(struct genl_info *info,
enum devlink_command cmd, int flags)
{
@@ -302,6 +327,58 @@ int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info)
return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
}
static int
devlink_nl_resource_dump_one(struct sk_buff *skb, struct devlink *devlink,
struct netlink_callback *cb, int flags)
{
struct devlink_nl_dump_state *state = devlink_dump_state(cb);
struct nlattr *resources_attr;
int start_idx = state->idx;
void *hdr;
int err;
if (list_empty(&devlink->resource_list))
return 0;
err = -EMSGSIZE;
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&devlink_nl_family, flags, DEVLINK_CMD_RESOURCE_DUMP);
if (!hdr)
return err;
if (devlink_nl_put_handle(skb, devlink))
goto nla_put_failure;
resources_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE_LIST);
if (!resources_attr)
goto nla_put_failure;
err = devlink_resource_list_fill(skb, devlink,
&devlink->resource_list, &state->idx);
if (err) {
if (state->idx == start_idx)
goto resource_list_cancel;
nla_nest_end(skb, resources_attr);
genlmsg_end(skb, hdr);
return err;
}
nla_nest_end(skb, resources_attr);
genlmsg_end(skb, hdr);
return 0;
resource_list_cancel:
nla_nest_cancel(skb, resources_attr);
nla_put_failure:
genlmsg_cancel(skb, hdr);
return err;
}
int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
struct netlink_callback *cb)
{
return devlink_nl_dumpit(skb, cb, devlink_nl_resource_dump_one);
}
int devlink_resources_validate(struct devlink *devlink,
struct devlink_resource *resource,
struct genl_info *info)