Thread (37 messages) flat view 37 messages, 5 authors, 2022-11-28

Re: [RFC PATCH] net: devlink: devlink_nl_info_fill: populate default information

From: Jiri Pirko <hidden>
Date: 2022-11-23 16:27:01
Also in: lkml

Wed, Nov 23, 2022 at 05:08:10PM CET, mailhol.vincent@wanadoo.fr wrote:
On Wed. 23 Nov. 2022 at 21:10, Jiri Pirko [off-list ref] wrote:
quoted
Wed, Nov 23, 2022 at 12:00:44PM CET, mailhol.vincent@wanadoo.fr wrote:
quoted
On Wed. 23 nov. 2022 à 18:46, Jiri Pirko [off-list ref] wrote:
quoted
Tue, Nov 22, 2022 at 04:49:34PM CET, mailhol.vincent@wanadoo.fr wrote:
quoted
Some piece of information are common to the vast majority of the
devices. Examples are:

 * the driver name.
 * the serial number of a USB device.

Modify devlink_nl_info_fill() to retrieve those information so that
the drivers do not have to. Rationale: factorize code.

Signed-off-by: Vincent Mailhol <redacted>
---
I am sending this as an RFC because I just started to study devlink.

I can see a parallel with ethtool for which the core will fill
whatever it can. c.f.:
commit f20a0a0519f3 ("ethtool: doc: clarify what drivers can implement in their get_drvinfo()")
Link: https://git.kernel.org/netdev/net-next/c/f20a0a0519f3

I think that devlink should do the same.

Right now, I identified two fields. If this RFC receive positive
feedback, I will iron it up and try to see if there is more that can
be filled by default.

Thank you for your comments.
---
net/core/devlink.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 7f789bbcbbd7..1908b360caf7 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -18,6 +18,7 @@
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#include <linux/refcount.h>
+#include <linux/usb.h>
#include <linux/workqueue.h>
#include <linux/u64_stats_sync.h>
#include <linux/timekeeping.h>
@@ -6685,12 +6686,37 @@ int devlink_info_version_running_put_ext(struct devlink_info_req *req,
}
EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);

+static int devlink_nl_driver_info_get(struct device_driver *drv,
+                                    struct devlink_info_req *req)
+{
+      if (!drv)
+              return 0;
+
+      if (drv->name[0])
+              return devlink_info_driver_name_put(req, drv->name);
Make sure that this provides the same value for all existing drivers
using devlink.
There are 21 drivers so far which reports the driver name through devlink. c.f.:
 $ git grep "devlink_info_driver_name_put(" drivers | wc -l

Out of those 21, there is only one: the mlxsw which seems to report
something different than device_driver::name. Instead it reports some
bus_info:
 https://elixir.bootlin.com/linux/v6.1-rc1/source/drivers/net/ethernet/mellanox/mlxsw/core.c#L1462
 https://elixir.bootlin.com/linux/v6.1-rc1/source/drivers/net/ethernet/mellanox/mlxsw/core.h#L504

I am not sure what the bus_info is here, but it looks like a misuse of
the field here.
When you are not sure, look into the code to find out :) I see no misue.
What exactly do you mean by that?
I mean that device_kind, it does not sound like a field that would
hold the driver name.

Looking deeper in the code, I got the confirmation.
bus_info::device_kind is initialized here (among other):
https://elixir.bootlin.com/linux/v6.1-rc1/source/drivers/net/ethernet/mellanox/mlxsw/i2c.c#L714

and it uses ic2_client::name which indicate the type of the device
(e.g. chip name):
https://elixir.bootlin.com/linux/v6.1-rc1/source/include/linux/i2c.h#L317

So I confirm that this is a misuse. This driver does not report the
driver's name.
Okay, I think that is a bug of mlxsw_i2c implementation. You can fix it
along the way.

quoted
quoted
quoted
quoted
+
+      return 0;
+}
+
+static int devlink_nl_usb_info_get(struct usb_device *udev,
+                                 struct devlink_info_req *req)
+{
+      if (!udev)
+              return 0;
+
+      if (udev->serial[0])
+              return devlink_info_serial_number_put(req, udev->serial);
+
+      return 0;
+}
+
static int
devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
                   enum devlink_command cmd, u32 portid,
                   u32 seq, int flags, struct netlink_ext_ack *extack)
{
      struct devlink_info_req req = {};
+      struct device *dev = devlink_to_dev(devlink);
      void *hdr;
      int err;
@@ -6707,6 +6733,16 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
      if (err)
              goto err_cancel_msg;

+      err = devlink_nl_driver_info_get(dev->driver, &req);
+      if (err)
+              goto err_cancel_msg;
+
+      if (!strcmp(dev->parent->type->name, "usb_device")) {
Comparing to string does not seem correct here.
There is a is_usb_device() which does the check:
 https://elixir.bootlin.com/linux/v6.1-rc1/source/drivers/usb/core/usb.h#L152

but this macro is not exposed outside of the usb core. The string
comparison was the only solution I found.
Find a different one. String check here is wrong.
quoted
Do you have any other ideas? If not and if this goes further than the
RFC stage, I will ask the USB folks if there is a better way.
quoted
quoted
+              err = devlink_nl_usb_info_get(to_usb_device(dev->parent), &req);
As Jakub pointed out, you have to make sure that driver does not put the
same attrs again. You have to introduce this functionality with removing
the fill-ups in drivers atomically, in a single patch.
Either this, either track if the attribute is already set. I would
prefer to remove all drivers fill-ups but this is not feasible for the
serial number. c.f. my reply to Jacub in this thread:
 https://lore.kernel.org/netdev/CAMZ6RqJ8_=h1SS7WmBeEB=75wsvVUZrb-8ELCDtpZb0gSs=2+A@mail.gmail.com/ (local)
Sure, but for the driver name it is. Let's start there.
I will do a first patch only for the driver name and think again of
the USB serial later on.
Yep, thanks!


Yours sincerely,
Vincent Mailhol
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help