[PATCH net-next 7/7] ethtool: add compat for devlink info
From: Jakub Kicinski <hidden>
Date: 2019-01-29 03:34:54
Subsystem:
devlink, networking [general], the rest · Maintainers:
Jiri Pirko, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted> --- 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 14da3632e8fc..b047360b88a9 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h@@ -616,6 +616,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
@@ -896,6 +898,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 f0c5f9bd96b7..99037bf15fb8 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c@@ -3598,12 +3598,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; + 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);
@@ -3611,6 +3617,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);
@@ -3626,7 +3634,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); + req->len = max_t(size_t, 0, req->len - len); + } + return 0; + } if (type >= ARRAY_SIZE(type2attr) || !type2attr[type]) return -EINVAL;
@@ -3672,6 +3688,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)
@@ -4962,6 +4979,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, + 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); + } + 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)); + rtnl_lock(); + if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT; return 0;
--
2.19.2