devlink: introduce line card info get message
Allow the driver to provide per line card info get op to fill-up info, similar to the "devlink dev info". Example: $ devlink lc info pci/0000:01:00.0 lc 8 pci/0000:01:00.0: lc 8 versions: fixed: hw.revision 0 running: ini.version 4 Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8d92e4fbcf
commit
276910aecc
|
@ -14,6 +14,7 @@ system. Following operations are provided:
|
||||||
* Get a list of supported line card types.
|
* Get a list of supported line card types.
|
||||||
* Provision of a slot with specific line card type.
|
* Provision of a slot with specific line card type.
|
||||||
* Get and monitor of line card state and its change.
|
* Get and monitor of line card state and its change.
|
||||||
|
* Get information about line card versions.
|
||||||
|
|
||||||
Line card according to the type may contain one or more gearboxes
|
Line card according to the type may contain one or more gearboxes
|
||||||
to mux the lanes with certain speed to multiple ports with lanes
|
to mux the lanes with certain speed to multiple ports with lanes
|
||||||
|
@ -120,3 +121,6 @@ Example usage
|
||||||
|
|
||||||
# Set slot 8 to be unprovisioned:
|
# Set slot 8 to be unprovisioned:
|
||||||
$ devlink lc set pci/0000:01:00.0 lc 8 notype
|
$ devlink lc set pci/0000:01:00.0 lc 8 notype
|
||||||
|
|
||||||
|
# Set info for slot 8:
|
||||||
|
$ devlink lc info pci/0000:01:00.0 lc 8
|
||||||
|
|
|
@ -150,6 +150,8 @@ struct devlink_port_new_attrs {
|
||||||
sfnum_valid:1;
|
sfnum_valid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct devlink_info_req;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct devlink_linecard_ops - Linecard operations
|
* struct devlink_linecard_ops - Linecard operations
|
||||||
* @provision: callback to provision the linecard slot with certain
|
* @provision: callback to provision the linecard slot with certain
|
||||||
|
@ -168,6 +170,7 @@ struct devlink_port_new_attrs {
|
||||||
* provisioned.
|
* provisioned.
|
||||||
* @types_count: callback to get number of supported types
|
* @types_count: callback to get number of supported types
|
||||||
* @types_get: callback to get next type in list
|
* @types_get: callback to get next type in list
|
||||||
|
* @info_get: callback to get linecard info
|
||||||
*/
|
*/
|
||||||
struct devlink_linecard_ops {
|
struct devlink_linecard_ops {
|
||||||
int (*provision)(struct devlink_linecard *linecard, void *priv,
|
int (*provision)(struct devlink_linecard *linecard, void *priv,
|
||||||
|
@ -182,6 +185,9 @@ struct devlink_linecard_ops {
|
||||||
void (*types_get)(struct devlink_linecard *linecard,
|
void (*types_get)(struct devlink_linecard *linecard,
|
||||||
void *priv, unsigned int index, const char **type,
|
void *priv, unsigned int index, const char **type,
|
||||||
const void **type_priv);
|
const void **type_priv);
|
||||||
|
int (*info_get)(struct devlink_linecard *linecard, void *priv,
|
||||||
|
struct devlink_info_req *req,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct devlink_sb_pool_info {
|
struct devlink_sb_pool_info {
|
||||||
|
@ -628,7 +634,6 @@ struct devlink_flash_update_params {
|
||||||
#define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1)
|
#define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1)
|
||||||
|
|
||||||
struct devlink_region;
|
struct devlink_region;
|
||||||
struct devlink_info_req;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct devlink_region_ops - Region operations
|
* struct devlink_region_ops - Region operations
|
||||||
|
|
|
@ -136,6 +136,8 @@ enum devlink_command {
|
||||||
DEVLINK_CMD_LINECARD_NEW,
|
DEVLINK_CMD_LINECARD_NEW,
|
||||||
DEVLINK_CMD_LINECARD_DEL,
|
DEVLINK_CMD_LINECARD_DEL,
|
||||||
|
|
||||||
|
DEVLINK_CMD_LINECARD_INFO_GET, /* can dump */
|
||||||
|
|
||||||
/* add new commands above here */
|
/* add new commands above here */
|
||||||
__DEVLINK_CMD_MAX,
|
__DEVLINK_CMD_MAX,
|
||||||
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
|
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
|
||||||
|
|
|
@ -2424,6 +2424,125 @@ static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct devlink_info_req {
|
||||||
|
struct sk_buff *msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||||
|
struct devlink_linecard *linecard,
|
||||||
|
enum devlink_command cmd, u32 portid,
|
||||||
|
u32 seq, int flags, struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct devlink_info_req req;
|
||||||
|
void *hdr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
|
||||||
|
if (!hdr)
|
||||||
|
return -EMSGSIZE;
|
||||||
|
|
||||||
|
err = -EMSGSIZE;
|
||||||
|
if (devlink_nl_put_handle(msg, devlink))
|
||||||
|
goto nla_put_failure;
|
||||||
|
if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
req.msg = msg;
|
||||||
|
err = linecard->ops->info_get(linecard, linecard->priv, &req, extack);
|
||||||
|
if (err)
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
genlmsg_end(msg, hdr);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nla_put_failure:
|
||||||
|
genlmsg_cancel(msg, hdr);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int devlink_nl_cmd_linecard_info_get_doit(struct sk_buff *skb,
|
||||||
|
struct genl_info *info)
|
||||||
|
{
|
||||||
|
struct devlink_linecard *linecard = info->user_ptr[1];
|
||||||
|
struct devlink *devlink = linecard->devlink;
|
||||||
|
struct sk_buff *msg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!linecard->ops->info_get)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
|
if (!msg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mutex_lock(&linecard->state_lock);
|
||||||
|
err = devlink_nl_linecard_info_fill(msg, devlink, linecard,
|
||||||
|
DEVLINK_CMD_LINECARD_INFO_GET,
|
||||||
|
info->snd_portid, info->snd_seq, 0,
|
||||||
|
info->extack);
|
||||||
|
mutex_unlock(&linecard->state_lock);
|
||||||
|
if (err) {
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return genlmsg_reply(msg, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int devlink_nl_cmd_linecard_info_get_dumpit(struct sk_buff *msg,
|
||||||
|
struct netlink_callback *cb)
|
||||||
|
{
|
||||||
|
struct devlink_linecard *linecard;
|
||||||
|
struct devlink *devlink;
|
||||||
|
int start = cb->args[0];
|
||||||
|
unsigned long index;
|
||||||
|
int idx = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
mutex_lock(&devlink_mutex);
|
||||||
|
xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) {
|
||||||
|
if (!devlink_try_get(devlink))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
|
||||||
|
goto retry;
|
||||||
|
|
||||||
|
mutex_lock(&devlink->linecards_lock);
|
||||||
|
list_for_each_entry(linecard, &devlink->linecard_list, list) {
|
||||||
|
if (idx < start || !linecard->ops->info_get) {
|
||||||
|
idx++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mutex_lock(&linecard->state_lock);
|
||||||
|
err = devlink_nl_linecard_info_fill(msg, devlink, linecard,
|
||||||
|
DEVLINK_CMD_LINECARD_INFO_GET,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
NLM_F_MULTI,
|
||||||
|
cb->extack);
|
||||||
|
mutex_unlock(&linecard->state_lock);
|
||||||
|
if (err) {
|
||||||
|
mutex_unlock(&devlink->linecards_lock);
|
||||||
|
devlink_put(devlink);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
mutex_unlock(&devlink->linecards_lock);
|
||||||
|
retry:
|
||||||
|
devlink_put(devlink);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
mutex_unlock(&devlink_mutex);
|
||||||
|
|
||||||
|
if (err != -EMSGSIZE)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
cb->args[0] = idx;
|
||||||
|
return msg->len;
|
||||||
|
}
|
||||||
|
|
||||||
static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
|
static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||||
struct devlink_sb *devlink_sb,
|
struct devlink_sb *devlink_sb,
|
||||||
enum devlink_command cmd, u32 portid,
|
enum devlink_command cmd, u32 portid,
|
||||||
|
@ -6416,10 +6535,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct devlink_info_req {
|
|
||||||
struct sk_buff *msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
|
int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
|
||||||
{
|
{
|
||||||
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
|
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
|
||||||
|
@ -9139,6 +9254,13 @@ static const struct genl_small_ops devlink_nl_ops[] = {
|
||||||
.flags = GENL_ADMIN_PERM,
|
.flags = GENL_ADMIN_PERM,
|
||||||
.internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
|
.internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.cmd = DEVLINK_CMD_LINECARD_INFO_GET,
|
||||||
|
.doit = devlink_nl_cmd_linecard_info_get_doit,
|
||||||
|
.dumpit = devlink_nl_cmd_linecard_info_get_dumpit,
|
||||||
|
.internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
|
||||||
|
/* can be retrieved by unprivileged users */
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.cmd = DEVLINK_CMD_SB_GET,
|
.cmd = DEVLINK_CMD_SB_GET,
|
||||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||||
|
|
Loading…
Reference in New Issue