[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190130221225.GE349@nanopsycho.orion>
Date: Wed, 30 Jan 2019 23:12:25 +0100
From: Jiri Pirko <jiri@...nulli.us>
To: Jakub Kicinski <jakub.kicinski@...ronome.com>
Cc: davem@...emloft.net, netdev@...r.kernel.org,
oss-drivers@...ronome.com, andrew@...n.ch, f.fainelli@...il.com,
mkubecek@...e.cz, eugenem@...com, jonathan.lemon@...il.com
Subject: Re: [PATCH net-next v2 7/7] ethtool: add compat for devlink info
Wed, Jan 30, 2019 at 08:05:13PM CET, jakub.kicinski@...ronome.com wrote:
>If driver did not fill the fw_version field, try to call into
>the new devlink get_info op and collect the versions that way.
>We assume ethtool was always reporting running versions.
>
>Signed-off-by: Jakub Kicinski <jakub.kicinski@...ronome.com>
>---
> include/net/devlink.h | 7 ++++++
> net/core/devlink.c | 52 ++++++++++++++++++++++++++++++++++++++++++-
> net/core/ethtool.c | 7 ++++++
> 3 files changed, 65 insertions(+), 1 deletion(-)
>
>diff --git a/include/net/devlink.h b/include/net/devlink.h
>index c678ed0cb099..b4750e93303a 100644
>--- a/include/net/devlink.h
>+++ b/include/net/devlink.h
>@@ -640,6 +640,8 @@ int devlink_info_report_version(struct devlink_info_req *req,
> enum devlink_version_type type,
> const char *version_name,
> const char *version_value);
>+void devlink_compat_running_versions(struct net_device *dev,
>+ char *buf, size_t len);
>
> #else
>
>@@ -957,6 +959,11 @@ devlink_info_report_version(struct devlink_info_req *req,
> {
> return 0;
> }
>+
>+static inline void
>+devlink_compat_running_versions(struct net_device *dev, char *buf, size_t len)
>+{
>+}
> #endif
>
> #endif /* _NET_DEVLINK_H_ */
>diff --git a/net/core/devlink.c b/net/core/devlink.c
>index e2027d3a5e40..5313e5918ee2 100644
>--- a/net/core/devlink.c
>+++ b/net/core/devlink.c
>@@ -3715,12 +3715,18 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
> }
>
> struct devlink_info_req {
>+ bool compat;
> struct sk_buff *msg;
>+ /* For compat call */
>+ char *buf;
union?
>+ size_t len;
> };
>
> int devlink_info_report_driver_name(struct devlink_info_req *req,
> const char *name)
> {
>+ if (req->compat)
>+ return 0;
> return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRV_NAME, name);
> }
> EXPORT_SYMBOL_GPL(devlink_info_report_driver_name);
>@@ -3728,6 +3734,8 @@ EXPORT_SYMBOL_GPL(devlink_info_report_driver_name);
> int devlink_info_report_serial_number(struct devlink_info_req *req,
> const char *sn)
> {
>+ if (req->compat)
>+ return 0;
> return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
> }
> EXPORT_SYMBOL_GPL(devlink_info_report_serial_number);
>@@ -3743,7 +3751,15 @@ int devlink_info_report_version(struct devlink_info_req *req,
> [DEVLINK_VERSION_RUNNING] = DEVLINK_ATTR_INFO_VERSION_RUNNING,
> };
> struct nlattr *nest;
>- int err;
>+ int len, err;
>+
>+ if (req->compat) {
>+ if (type == DEVLINK_VERSION_RUNNING) {
>+ len = strlcpy(req->buf, version_value, req->len);
If you have multiple running versions, shouldn't you concat them into a
single string for compat?
>+ req->len = max_t(size_t, 0, req->len - len);
>+ }
>+ return 0;
>+ }
>
> if (type >= ARRAY_SIZE(type2attr) || !type2attr[type])
> return -EINVAL;
>@@ -3789,6 +3805,7 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
> if (devlink_nl_put_handle(msg, devlink))
> goto err_cancel_msg;
>
>+ memset(&req, 0, sizeof(req));
> req.msg = msg;
> err = devlink->ops->info_get(devlink, &req, extack);
> if (err)
>@@ -5263,6 +5280,39 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
> }
> EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
>
>+void devlink_compat_running_versions(struct net_device *dev,
Why "versionS?"
>+ char *buf, size_t len)
>+{
>+ struct devlink_port *devlink_port;
>+ struct devlink_info_req req;
>+ struct devlink *devlink;
>+ bool found = false;
>+
>+ mutex_lock(&devlink_mutex);
>+ list_for_each_entry(devlink, &devlink_list, list) {
>+ mutex_lock(&devlink->lock);
>+ list_for_each_entry(devlink_port, &devlink->port_list, list) {
>+ if (devlink_port->type == DEVLINK_PORT_TYPE_ETH ||
>+ devlink_port->type_dev == dev) {
>+ mutex_unlock(&devlink->lock);
>+ found = true;
>+ goto out;
>+ }
>+ }
>+ mutex_unlock(&devlink->lock);
>+ }
>+out:
>+ if (found && devlink->ops->info_get) {
>+ memset(&req, 0, sizeof(req));
>+ req.compat = true;
>+ req.buf = buf;
>+ req.len = len;
>+
>+ devlink->ops->info_get(devlink, &req, NULL);
I don't really like this compat bool and check in "put" functions.
I would rather like to run info_get() in case of both compat and
non-compat in the same way. Then for compat just pickup the info
which is needed and put to buf.
I don't see problem in using netlink skb for that direcly.
>+ }
>+ mutex_unlock(&devlink_mutex);
>+}
>+
> static int __init devlink_module_init(void)
> {
> return genl_register_family(&devlink_nl_family);
>diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>index 158264f7cfaf..176b17d11f08 100644
>--- a/net/core/ethtool.c
>+++ b/net/core/ethtool.c
>@@ -27,6 +27,7 @@
> #include <linux/rtnetlink.h>
> #include <linux/sched/signal.h>
> #include <linux/net.h>
>+#include <net/devlink.h>
> #include <net/xdp_sock.h>
>
> /*
>@@ -803,6 +804,12 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
> if (ops->get_eeprom_len)
> info.eedump_len = ops->get_eeprom_len(dev);
>
>+ rtnl_unlock();
>+ if (!info.fw_version[0])
>+ devlink_compat_running_versions(dev, info.fw_version,
>+ ARRAY_SIZE(info.fw_version));
ARRAY_SIZE looks odd here. "sizeof()" would be better I think.
>+ rtnl_lock();
>+
> if (copy_to_user(useraddr, &info, sizeof(info)))
> return -EFAULT;
> return 0;
>--
>2.19.2
>
Powered by blists - more mailing lists