sonic-buildimage/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch

316 lines
9.9 KiB
Diff

From 7a39de95203f7dc033bdc81703989d627f2ca0de Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
Date: Wed, 22 Dec 2021 15:11:36 +0000
Subject: [PATCH] devlink: introduce linecard info get message
Allow the driver to provide per line card info get op to fill-up info,
similar to the "devlink dev info".
devlink: introduce line card devices support
Line card can contain a device. For example, this can be a gearbox with
flash. This flash could be updated. Provide the driver possibility to
attach such devices to a line card and expose those to user. Leverage
the existing devlink flash update mechanism and allow driver to pass a
custom "component name" string identifying the line card device to
flash.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
include/net/devlink.h | 12 +++
include/uapi/linux/devlink.h | 4 +
net/core/devlink.c | 166 +++++++++++++++++++++++++++++++++++
3 files changed, 182 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 059bed6ae..06b61c1d7 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -160,9 +160,11 @@ struct devlink_linecard {
struct devlink_linecard_type *types;
unsigned int types_count;
bool active;
+ struct list_head device_list;
};
struct devlink_info_req;
+struct devlink_linecard_device;
/**
* struct devlink_linecard_ops - Linecard operations
@@ -188,6 +190,9 @@ struct devlink_linecard_ops {
int (*info_get)(struct devlink_linecard *linecard, void *priv,
struct devlink_info_req *req,
struct netlink_ext_ack *extack);
+ int (*device_info_get)(struct devlink_linecard_device *device,
+ void *priv, struct devlink_info_req *req,
+ struct netlink_ext_ack *extack);
};
struct devlink_sb_pool_info {
@@ -1459,6 +1464,13 @@ struct devlink_linecard *
devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
const struct devlink_linecard_ops *ops, void *priv);
void devlink_linecard_destroy(struct devlink_linecard *linecard);
+struct devlink_linecard_device *
+devlink_linecard_device_create(struct devlink_linecard *linecard,
+ unsigned int device_index,
+ const char *flash_component, void *priv);
+void
+devlink_linecard_device_destroy(struct devlink_linecard *linecard,
+ struct devlink_linecard_device *linecard_device);
void devlink_linecard_provision_set(struct devlink_linecard *linecard,
const char *type);
void devlink_linecard_provision_clear(struct devlink_linecard *linecard);
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 2c9f7d584..bac94c3c1 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -569,6 +569,10 @@ enum devlink_attr {
DEVLINK_ATTR_LINECARD_TYPE, /* string */
DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */
DEVLINK_ATTR_LINECARD_INFO, /* nested */
+ DEVLINK_ATTR_LINECARD_DEVICE_LIST, /* nested */
+ DEVLINK_ATTR_LINECARD_DEVICE, /* nested */
+ DEVLINK_ATTR_LINECARD_DEVICE_INDEX, /* u32 */
+ DEVLINK_ATTR_LINECARD_DEVICE_INFO, /* nested */
/* add new attributes above here, update the policy in devlink.c */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 04f8038f8..ca014f40a 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -1249,6 +1249,59 @@ struct devlink_info_req {
struct sk_buff *msg;
};
+struct devlink_linecard_device {
+ struct list_head list;
+ unsigned int index;
+ const char *flash_component;
+ void *priv;
+};
+
+static int
+devlink_nl_linecard_device_fill(struct sk_buff *msg,
+ struct devlink_linecard *linecard,
+ struct devlink_linecard_device *linecard_device)
+{
+ struct nlattr *attr;
+
+ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE);
+ if (!attr)
+ return -EMSGSIZE;
+ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_DEVICE_INDEX,
+ linecard_device->index))
+ return -EMSGSIZE;
+ if (linecard_device->flash_component &&
+ nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
+ linecard_device->flash_component))
+ return -EMSGSIZE;
+ nla_nest_end(msg, attr);
+
+ return 0;
+}
+
+static int devlink_nl_linecard_devices_fill(struct sk_buff *msg,
+ struct devlink_linecard *linecard)
+{
+ struct devlink_linecard_device *linecard_device;
+ struct nlattr *attr;
+ int err;
+
+ if (list_empty(&linecard->device_list))
+ return 0;
+
+ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_LIST);
+ if (!attr)
+ return -EMSGSIZE;
+ list_for_each_entry(linecard_device, &linecard->device_list, list) {
+ err = devlink_nl_linecard_device_fill(msg, linecard,
+ linecard_device);
+ if (err)
+ return err;
+ }
+ nla_nest_end(msg, attr);
+
+ return 0;
+}
+
static int devlink_nl_linecard_fill(struct sk_buff *msg,
struct devlink *devlink,
struct devlink_linecard *linecard,
@@ -1259,6 +1312,7 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg,
struct devlink_linecard_type *linecard_type;
struct nlattr *attr;
void *hdr;
+ int err;
int i;
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
@@ -1289,6 +1343,10 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg,
nla_nest_end(msg, attr);
}
+ err = devlink_nl_linecard_devices_fill(msg, linecard);
+ if (err)
+ goto nla_put_failure;
+
genlmsg_end(msg, hdr);
return 0;
@@ -1546,6 +1604,66 @@ static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb,
return 0;
}
+static int
+devlink_nl_linecard_device_info_fill(struct sk_buff *msg,
+ struct devlink_linecard *linecard,
+ struct devlink_linecard_device *linecard_device,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *attr, *attr2;
+
+ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE);
+ if (!attr)
+ return -EMSGSIZE;
+ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_DEVICE_INDEX,
+ linecard_device->index))
+ return -EMSGSIZE;
+ if (linecard->ops->device_info_get) {
+ struct devlink_info_req req;
+ int err;
+
+ attr2 = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_INFO);
+ if (!attr2)
+ return -EMSGSIZE;
+ req.msg = msg;
+ err = linecard->ops->device_info_get(linecard_device,
+ linecard_device->priv,
+ &req, extack);
+ if (err)
+ return -EMSGSIZE;
+ nla_nest_end(msg, attr2);
+ }
+ nla_nest_end(msg, attr);
+
+ return 0;
+}
+
+static int devlink_nl_linecard_devices_info_fill(struct sk_buff *msg,
+ struct devlink_linecard *linecard,
+ struct netlink_ext_ack *extack)
+{
+ struct devlink_linecard_device *linecard_device;
+ struct nlattr *attr;
+ int err;
+
+ if (list_empty(&linecard->device_list))
+ return 0;
+
+ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_LIST);
+ if (!attr)
+ return -EMSGSIZE;
+ list_for_each_entry(linecard_device, &linecard->device_list, list) {
+ err = devlink_nl_linecard_device_info_fill(msg, linecard,
+ linecard_device,
+ extack);
+ if (err)
+ return err;
+ }
+ nla_nest_end(msg, attr);
+
+ return 0;
+}
+
static int
devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink,
struct devlink_linecard *linecard,
@@ -1576,6 +1694,10 @@ devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink,
goto nla_put_failure;
nla_nest_end(msg, attr);
+ err = devlink_nl_linecard_devices_info_fill(msg, linecard, extack);
+ if (err)
+ goto nla_put_failure;
+
genlmsg_end(msg, hdr);
return 0;
@@ -9068,6 +9190,7 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
linecard->priv = priv;
linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
mutex_init(&linecard->state_lock);
+ INIT_LIST_HEAD(&linecard->device_list);
err = devlink_linecard_types_init(linecard);
if (err) {
@@ -9096,6 +9219,7 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard)
devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
devlink_linecard_types_fini(linecard);
+ WARN_ON(!list_empty(&linecard->device_list));
mutex_lock(&devlink->linecards_lock);
list_del(&linecard->list);
mutex_unlock(&devlink->linecards_lock);
@@ -9103,6 +9227,47 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard)
}
EXPORT_SYMBOL_GPL(devlink_linecard_destroy);
+/**
+ * devlink_linecard_device_create - Create a device on linecard
+ *
+ * @devlink_linecard: devlink linecard
+ * @device_index: index of the linecard device
+ * @flash_component: name of flash update component,
+ * NULL if unable to flash
+ */
+struct devlink_linecard_device *
+devlink_linecard_device_create(struct devlink_linecard *linecard,
+ unsigned int device_index,
+ const char *flash_component, void *priv)
+{
+ struct devlink_linecard_device *linecard_device;
+
+ linecard_device = kzalloc(sizeof(*linecard_device), GFP_KERNEL);
+ if (!linecard_device)
+ return ERR_PTR(-ENOMEM);
+ linecard_device->index = device_index;
+ linecard_device->flash_component = flash_component;
+ linecard_device->priv = priv;
+ mutex_lock(&linecard->devlink->lock);
+ list_add_tail(&linecard_device->list, &linecard->device_list);
+ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
+ mutex_unlock(&linecard->devlink->lock);
+ return linecard_device;
+}
+EXPORT_SYMBOL_GPL(devlink_linecard_device_create);
+
+void
+devlink_linecard_device_destroy(struct devlink_linecard *linecard,
+ struct devlink_linecard_device *linecard_device)
+{
+ mutex_lock(&linecard->devlink->lock);
+ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
+ list_del(&linecard_device->list);
+ mutex_unlock(&linecard->devlink->lock);
+ kfree(linecard_device);
+}
+EXPORT_SYMBOL_GPL(devlink_linecard_device_destroy);
+
/**
* devlink_linecard_provision_set - Set provisioning on linecard
*
@@ -9129,6 +9294,7 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_set);
void devlink_linecard_provision_clear(struct devlink_linecard *linecard)
{
mutex_lock(&linecard->state_lock);
+ WARN_ON(!list_empty(&linecard->device_list));
linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
linecard->type = NULL;
devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
--
2.30.2