]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
can: kvaser_usb: Add devlink port support
authorJimmy Assarsson <extja@kvaser.com>
Fri, 25 Jul 2025 12:34:51 +0000 (14:34 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 25 Jul 2025 16:01:22 +0000 (18:01 +0200)
Register each CAN channel of the device as an devlink physical port.
This makes it easier to get device information for a given network
interface (i.e. can2).

Example output:
  $ devlink dev
  usb/1-1.3:1.0

  $ devlink port
  usb/1-1.3:1.0/0: type eth netdev can0 flavour physical port 0 splittable false
  usb/1-1.3:1.0/1: type eth netdev can1 flavour physical port 1 splittable false

  $ devlink port show can1
  usb/1-1.3:1.0/1: type eth netdev can1 flavour physical port 0 splittable false

  $ devlink dev info
  usb/1-1.3:1.0:
    driver kvaser_usb
    serial_number 1020
    versions:
        fixed:
          board.rev 1
          board.id 7330130009653
        running:
          fw 3.22.527

  $ ethtool -i can1
  driver: kvaser_usb
  version: 6.12.10-arch1-1
  firmware-version: 3.22.527
  expansion-rom-version:
  bus-info: 1-1.3:1.0
  supports-statistics: no
  supports-test: no
  supports-eeprom-access: no
  supports-register-dump: no
  supports-priv-flags: no

Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
Link: https://patch.msgid.link/20250725123452.41-11-extja@kvaser.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/kvaser_usb/kvaser_usb.h
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c

index d5f913ac9b440e6b21e7294e9af458f89116da1f..46a1b6907a500ec7769f2b632e525b89571a1e57 100644 (file)
@@ -131,6 +131,7 @@ struct kvaser_usb {
 
 struct kvaser_usb_net_priv {
        struct can_priv can;
+       struct devlink_port devlink_port;
        struct can_berr_counter bec;
 
        /* subdriver-specific data */
@@ -229,6 +230,9 @@ extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops;
 
 extern const struct devlink_ops kvaser_usb_devlink_ops;
 
+int kvaser_usb_devlink_port_register(struct kvaser_usb_net_priv *priv);
+void kvaser_usb_devlink_port_unregister(struct kvaser_usb_net_priv *priv);
+
 void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv);
 
 int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len,
index b9b2e120a5cd2e9912b860a4bdb06db5beec91ef..90e77fa0ff4a58b25eec33e0f9ffcb54dab97438 100644 (file)
@@ -818,6 +818,7 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
                if (ops->dev_remove_channel)
                        ops->dev_remove_channel(priv);
 
+               kvaser_usb_devlink_port_unregister(priv);
                free_candev(priv->netdev);
        }
 }
@@ -891,20 +892,28 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
        if (ops->dev_init_channel) {
                err = ops->dev_init_channel(priv);
                if (err)
-                       goto err;
+                       goto candev_free;
+       }
+
+       err = kvaser_usb_devlink_port_register(priv);
+       if (err) {
+               dev_err(&dev->intf->dev, "Failed to register devlink port\n");
+               goto candev_free;
        }
 
        err = register_candev(netdev);
        if (err) {
                dev_err(&dev->intf->dev, "Failed to register CAN device\n");
-               goto err;
+               goto unregister_devlink_port;
        }
 
        netdev_dbg(netdev, "device registered\n");
 
        return 0;
 
-err:
+unregister_devlink_port:
+       kvaser_usb_devlink_port_unregister(priv);
+candev_free:
        free_candev(netdev);
        dev->nets[channel] = NULL;
        return err;
index aa06bd1fa12530c41b9c84a12fc7113c0b4a6a1f..e838b82298ae36dcd05dde8ab46ec63a7b100660 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "kvaser_usb.h"
 
+#include <linux/netdevice.h>
 #include <net/devlink.h>
 
 #define KVASER_USB_EAN_MSB 0x00073301
@@ -60,3 +61,27 @@ static int kvaser_usb_devlink_info_get(struct devlink *devlink,
 const struct devlink_ops kvaser_usb_devlink_ops = {
        .info_get = kvaser_usb_devlink_info_get,
 };
+
+int kvaser_usb_devlink_port_register(struct kvaser_usb_net_priv *priv)
+{
+       int ret;
+       struct devlink_port_attrs attrs = {
+               .flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL,
+               .phys.port_number = priv->channel,
+       };
+       devlink_port_attrs_set(&priv->devlink_port, &attrs);
+
+       ret = devlink_port_register(priv_to_devlink(priv->dev),
+                                   &priv->devlink_port, priv->channel);
+       if (ret)
+               return ret;
+
+       SET_NETDEV_DEVLINK_PORT(priv->netdev, &priv->devlink_port);
+
+       return 0;
+}
+
+void kvaser_usb_devlink_port_unregister(struct kvaser_usb_net_priv *priv)
+{
+       devlink_port_unregister(&priv->devlink_port);
+}