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.
|
||||
* Provision of a slot with specific line card type.
|
||||
* 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
|
||||
to mux the lanes with certain speed to multiple ports with lanes
|
||||
|
@ -120,3 +121,6 @@ Example usage
|
|||
|
||||
# Set slot 8 to be unprovisioned:
|
||||
$ 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;
|
||||
};
|
||||
|
||||
struct devlink_info_req;
|
||||
|
||||
/**
|
||||
* struct devlink_linecard_ops - Linecard operations
|
||||
* @provision: callback to provision the linecard slot with certain
|
||||
|
@ -168,6 +170,7 @@ struct devlink_port_new_attrs {
|
|||
* provisioned.
|
||||
* @types_count: callback to get number of supported types
|
||||
* @types_get: callback to get next type in list
|
||||
* @info_get: callback to get linecard info
|
||||
*/
|
||||
struct devlink_linecard_ops {
|
||||
int (*provision)(struct devlink_linecard *linecard, void *priv,
|
||||
|
@ -182,6 +185,9 @@ struct devlink_linecard_ops {
|
|||
void (*types_get)(struct devlink_linecard *linecard,
|
||||
void *priv, unsigned int index, const char **type,
|
||||
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 {
|
||||
|
@ -628,7 +634,6 @@ struct devlink_flash_update_params {
|
|||
#define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1)
|
||||
|
||||
struct devlink_region;
|
||||
struct devlink_info_req;
|
||||
|
||||
/**
|
||||
* struct devlink_region_ops - Region operations
|
||||
|
|
|
@ -136,6 +136,8 @@ enum devlink_command {
|
|||
DEVLINK_CMD_LINECARD_NEW,
|
||||
DEVLINK_CMD_LINECARD_DEL,
|
||||
|
||||
DEVLINK_CMD_LINECARD_INFO_GET, /* can dump */
|
||||
|
||||
/* add new commands above here */
|
||||
__DEVLINK_CMD_MAX,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct devlink_sb *devlink_sb,
|
||||
enum devlink_command cmd, u32 portid,
|
||||
|
@ -6416,10 +6535,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
struct devlink_info_req {
|
||||
struct sk_buff *msg;
|
||||
};
|
||||
|
||||
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);
|
||||
|
@ -9139,6 +9254,13 @@ static const struct genl_small_ops devlink_nl_ops[] = {
|
|||
.flags = GENL_ADMIN_PERM,
|
||||
.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,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
|
|
Loading…
Reference in New Issue