Wed, Jan 30, 2019 at 08:05:13PM CET, jakub.kicin...@netronome.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.kicin...@netronome.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
>

Reply via email to