can: kvaser_usb: Simplify identification of physical CAN interfaces
cover can: kvaser_usb: Simplify identification of physical CAN interfaces
This patch series simplifies the process of identifying which network interface (can0..canX) corresponds to which physical CAN channel on Kvaser USB based CAN interfaces.
Jimmy Assarsson (9):
can: kvaser_usb: Add support to control CAN LEDs on device
can: kvaser_usb: Add support for ethtool set_phys_id()
can: kvaser_usb: Add intermediate variables
can: kvaser_usb: Move comment regarding max_tx_urbs
can: kvaser_usb: Store the different firmware version components in a
struct
can: kvaser_usb: Store additional device information
can: kvaser_usb: Add devlink support
can: kvaser_usb: Expose device information via devlink info_get()
can: kvaser_usb: Add devlink port support
drivers/net/can/usb/Kconfig | 1 + drivers/net/can/usb/kvaser_usb/Makefile | 2 +- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 33 +++- .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 144 +++++++++++++----- .../can/usb/kvaser_usb/kvaser_usb_devlink.c | 88 +++++++++++ .../net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 63 +++++++- .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 75 ++++++++- 7 files changed, 359 insertions(+), 47 deletions(-) create mode 100644 drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c
Signature · 1 line
2.49.0
PATCH 1/9 can: kvaser_usb: Add support to control CAN LEDs on device
Add support to turn on/off CAN LEDs on device.
--- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 9 ++++ .../net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 51 ++++++++++++++++++ .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 54 +++++++++++++++++++ 3 files changed, 114 insertions(+)
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +9 -0
@@ -54,6 +54,11 @@ enum kvaser_usb_leaf_family { KVASER_USBCAN, }; +enum kvaser_usb_led_state { +KVASER_USB_LED_ON =0 , +KVASER_USB_LED_OFF =1 , +}; +#define KVASER_USB_HYDRA_MAX_CMD_LEN 128struct kvaser_usb_dev_card_data_hydra {u8 channel_to_he[KVASER_USB_MAX_NET_DEVICES ];
@@ -149,6 +154,7 @@ struct kvaser_usb_net_priv {* @dev_get_software_details: get software details * @dev_get_card_info: get card info * @dev_get_capabilities: discover device capabilities +* @dev_set_led: turn on/off device LED * * @dev_set_opt_mode: set ctrlmod * @dev_start_chip: start the CAN controller
@@ -176,6 +182,9 @@ struct kvaser_usb_dev_ops {int (*dev_get_software_details)(struct kvaser_usb *dev);int (*dev_get_card_info)(struct kvaser_usb *dev);int (*dev_get_capabilities)(struct kvaser_usb *dev); +int (*dev_set_led)(struct kvaser_usb_net_priv *priv, +enum kvaser_usb_led_state state, +u16 duration_ms);int (*dev_set_opt_mode)(const struct kvaser_usb_net_priv *priv);int (*dev_start_chip)(struct kvaser_usb_net_priv *priv);int (*dev_stop_chip)(struct kvaser_usb_net_priv *priv);
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +51 -0
93 lines not on this page · raw message
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +54 -0
108 lines not on this page · raw message
Signature · 1 line
2.49.0
PATCH 2/9 can: kvaser_usb: Add support for ethtool set_phys_id()
In reply to Jimmy AssarssonAdd support for ethtool set_phys_id(), to physically locate devices by flashing a LED on the device.
--- .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+)
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +29 -0
@@ -753,6 +753,34 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,return ret; } +static int kvaser_usb_set_phys_id (struct net_device *netdev, +enum ethtool_phys_id_state state) +{ +struct kvaser_usb_net_priv *priv =netdev_priv (netdev); +const struct kvaser_usb_dev_ops *ops = priv->dev->driver_info->ops; +int ret =0 ; + +switch (state) { +case ETHTOOL_ID_ACTIVE : +return 3 ;/* 3 On/Off cycles per second */ +case ETHTOOL_ID_ON : + ret = ops->dev_set_led (priv,KVASER_USB_LED_ON ,1000 ); +break ; +case ETHTOOL_ID_OFF : + ret = ops->dev_set_led (priv,KVASER_USB_LED_OFF ,1000 ); +break ; +case ETHTOOL_ID_INACTIVE : +/* Turn LED off and restore standard function after 1ms */ + ret = ops->dev_set_led (priv,KVASER_USB_LED_OFF ,1 ); +break ; +default : + ret = -EINVAL ; +break ; + } + +return ret; +} +static const struct net_device_ops kvaser_usb_netdev_ops = { .ndo_open = kvaser_usb_open, .ndo_stop = kvaser_usb_close,
@@ -763,6 +791,7 @@ static const struct net_device_ops kvaser_usb_netdev_ops = {static const struct ethtool_ops kvaser_usb_ethtool_ops = { .get_ts_info = can_ethtool_op_get_ts_info_hwts, + .set_phys_id = kvaser_usb_set_phys_id, };static void kvaser_usb_remove_interfaces (struct kvaser_usb *dev)
Signature · 1 line
2.49.0
PATCH 3/9 can: kvaser_usb: Add intermediate variables
In reply to Jimmy AssarssonAdd intermediate variables, for readability and to simplify future patches.
--- .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +13 -7
@@ -364,10 +364,13 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) err =usb_submit_urb (urb,GFP_ATOMIC );if (err == -ENODEV ) {for (i =0 ; i < dev->nchannels; i++) { -if (!dev->nets[i]) +struct kvaser_usb_net_priv *priv; + + priv = dev->nets[i]; +if (!priv)continue ; -netif_device_detach (dev->nets[i]->netdev); +netif_device_detach (priv->netdev); } }else if (err) { dev_err(&dev->intf->dev,
@@ -798,24 +801,27 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) {const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;int i; +struct kvaser_usb_net_priv *priv;for (i =0 ; i < dev->nchannels; i++) { -if (!dev->nets[i]) + priv = dev->nets[i]; +if (!priv)continue ; -unregister_candev (dev->nets[i]->netdev); +unregister_candev (priv->netdev); }kvaser_usb_unlink_all_urbs (dev);for (i =0 ; i < dev->nchannels; i++) { -if (!dev->nets[i]) + priv = dev->nets[i]; +if (!priv)continue ;if (ops->dev_remove_channel) - ops->dev_remove_channel (dev->nets[i]); + ops->dev_remove_channel (priv); -free_candev (dev->nets[i]->netdev); +free_candev (priv->netdev); } }
Signature · 1 line
2.49.0
PATCH 4/9 can: kvaser_usb: Move comment regarding max_tx_urbs
In reply to Jimmy AssarssonMove comment regarding max_tx_urbs, to where the struct member is declared.
--- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +2 -2
@@ -101,12 +101,12 @@ struct kvaser_usb {struct usb_endpoint_descriptor *bulk_in, *bulk_out;struct usb_anchor rx_submitted; +u32 fw_version; +unsigned int nchannels;/* @max_tx_urbs: Firmware-reported maximum number of outstanding, * not yet ACKed, transmissions on this device. This value is * also used as a sentinel for marking free tx contexts. */ -u32 fw_version; -unsigned int nchannels;unsigned int max_tx_urbs;struct kvaser_usb_dev_card_data card_data;
Signature · 1 line
2.49.0
PATCH 5/9 can: kvaser_usb: Store the different firmware version components in a struct
In reply to Jimmy AssarssonStore firmware version in kvaser_usb_fw_version struct, specifying the different components of the version number.
--- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 12 +++++++++++- drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 8 ++++---- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 6 +++++- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 15 +++++++++++++-- 4 files changed, 33 insertions(+), 8 deletions(-)
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +11 -1
@@ -47,6 +47,10 @@#define KVASER_USB_CAP_EXT_CAP 0x02#define KVASER_USB_HYDRA_CAP_EXT_CMD 0x04 +#define KVASER_USB_SW_VERSION_MAJOR_MASK GENMASK(31, 24) +#define KVASER_USB_SW_VERSION_MINOR_MASK GENMASK(23, 16) +#define KVASER_USB_SW_VERSION_BUILD_MASK GENMASK(15, 0) +struct kvaser_usb_dev_cfg ;enum kvaser_usb_leaf_family {
@@ -83,6 +87,12 @@ struct kvaser_usb_tx_urb_context {u32 echo_index; }; +struct kvaser_usb_fw_version { +u8 major; +u8 minor; +u16 build; +}; +struct kvaser_usb_busparams {__le32 bitrate;u8 tseg1;
@@ -101,7 +111,7 @@ struct kvaser_usb {struct usb_endpoint_descriptor *bulk_in, *bulk_out;struct usb_anchor rx_submitted; -u32 fw_version; +struct kvaser_usb_fw_version fw_version;unsigned int nchannels;/* @max_tx_urbs: Firmware-reported maximum number of outstanding, * not yet ACKed, transmissions on this device. This value is
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +4 -4
@@ -965,10 +965,10 @@ static int kvaser_usb_probe(struct usb_interface *intf,if (WARN_ON (!dev->cfg))return -ENODEV ; -dev_dbg (&intf->dev,"Firmware version: %d.%d.%d\n" , - ((dev->fw_version >>24 ) &0xff ), - ((dev->fw_version >>16 ) &0xff ), - (dev->fw_version &0xffff )); +dev_dbg (&intf->dev,"Firmware version: %u.%u.%u\n" , + dev->fw_version.major, + dev->fw_version.minor, + dev->fw_version.build);dev_dbg (&intf->dev,"Max outstanding tx = %d URBs\n" , dev->max_tx_urbs);
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +5 -1
@@ -1839,6 +1839,7 @@ static int kvaser_usb_hydra_get_software_details(struct kvaser_usb *dev)size_t cmd_len;int err;u32 flags; +u32 fw_version;struct kvaser_usb_dev_card_data *card_data = &dev->card_data; cmd =kzalloc (sizeof (*cmd),GFP_KERNEL );
@@ -1863,7 +1864,10 @@ static int kvaser_usb_hydra_get_software_details(struct kvaser_usb *dev)if (err) goto end; - dev->fw_version =le32_to_cpu (cmd->sw_detail_res.sw_version); + fw_version =le32_to_cpu (cmd->sw_detail_res.sw_version); + dev->fw_version.major =FIELD_GET (KVASER_USB_SW_VERSION_MAJOR_MASK , fw_version); + dev->fw_version.minor =FIELD_GET (KVASER_USB_SW_VERSION_MINOR_MASK , fw_version); + dev->fw_version.build =FIELD_GET (KVASER_USB_SW_VERSION_BUILD_MASK , fw_version); flags =le32_to_cpu (cmd->sw_detail_res.sw_flags);if (flags &KVASER_USB_HYDRA_SW_FLAG_FW_BAD ) {
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +13 -2
@@ -741,9 +741,13 @@ static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev,static void kvaser_usb_leaf_get_software_info_leaf (struct kvaser_usb *dev,const struct leaf_cmd_softinfo *softinfo) { +u32 fw_version;u32 sw_options =le32_to_cpu (softinfo->sw_options); - dev->fw_version =le32_to_cpu (softinfo->fw_version); + fw_version =le32_to_cpu (softinfo->fw_version); + dev->fw_version.major =FIELD_GET (KVASER_USB_SW_VERSION_MAJOR_MASK , fw_version); + dev->fw_version.minor =FIELD_GET (KVASER_USB_SW_VERSION_MINOR_MASK , fw_version); + dev->fw_version.build =FIELD_GET (KVASER_USB_SW_VERSION_BUILD_MASK , fw_version); dev->max_tx_urbs =le16_to_cpu (softinfo->max_outstanding_tx);if (sw_options &KVASER_USB_LEAF_SWOPTION_EXT_CAP )
@@ -784,6 +788,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) {struct kvaser_cmd cmd;int err; +u32 fw_version; err =kvaser_usb_leaf_send_simple_cmd (dev,CMD_GET_SOFTWARE_INFO ,0 );if (err)
@@ -798,7 +803,13 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)kvaser_usb_leaf_get_software_info_leaf (dev, &cmd.u.leaf.softinfo);break ;case KVASER_USBCAN : - dev->fw_version =le32_to_cpu (cmd.u.usbcan.softinfo.fw_version); + fw_version =le32_to_cpu (cmd.u.usbcan.softinfo.fw_version); + dev->fw_version.major =FIELD_GET (KVASER_USB_SW_VERSION_MAJOR_MASK , + fw_version); + dev->fw_version.minor =FIELD_GET (KVASER_USB_SW_VERSION_MINOR_MASK , + fw_version); + dev->fw_version.build =FIELD_GET (KVASER_USB_SW_VERSION_BUILD_MASK , + fw_version); dev->max_tx_urbs =le16_to_cpu (cmd.u.usbcan.softinfo.max_outstanding_tx); dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg;
Signature · 1 line
2.49.0
PATCH 6/9 can: kvaser_usb: Store additional device information
In reply to Jimmy AssarssonStore additional device information; EAN (product number), serial_number and hardware revision.
--- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 3 +++ drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 6 +++++- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-)
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +3 -0
@@ -111,7 +111,10 @@ struct kvaser_usb {struct usb_endpoint_descriptor *bulk_in, *bulk_out;struct usb_anchor rx_submitted; +u32 ean[2 ]; +u32 serial_number;struct kvaser_usb_fw_version fw_version; +u8 hw_revision;unsigned int nchannels;/* @max_tx_urbs: Firmware-reported maximum number of outstanding, * not yet ACKed, transmissions on this device. This value is
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +5 -1
@@ -114,7 +114,7 @@ struct kvaser_cmd_card_info {__le32 clock_res;__le32 mfg_date;__le32 ean[2 ]; -u8 hw_version; +u8 hw_revision;u8 usb_mode;u8 hw_type;u8 reserved0;
@@ -1918,6 +1918,10 @@ static int kvaser_usb_hydra_get_card_info(struct kvaser_usb *dev) err =kvaser_usb_hydra_wait_cmd (dev,CMD_GET_CARD_INFO_RESP , &cmd);if (err)return err; + dev->ean[1 ] =le32_to_cpu (cmd.card_info.ean[1 ]); + dev->ean[0 ] =le32_to_cpu (cmd.card_info.ean[0 ]); + dev->serial_number =le32_to_cpu (cmd.card_info.serial_number); + dev->hw_revision = cmd.card_info.hw_revision; dev->nchannels = cmd.card_info.nchannels;if (dev->nchannels >KVASER_USB_MAX_NET_DEVICES )
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +5 -1
@@ -138,7 +138,7 @@ struct kvaser_cmd_cardinfo {__le32 padding0;__le32 clock_resolution;__le32 mfgdate; -u8 ean[8 ]; +__le32 ean[2 ];u8 hw_revision; union { struct {
@@ -854,6 +854,10 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) (dev->driver_info->family ==KVASER_USBCAN && dev->nchannels > MAX_USBCAN_NET_DEVICES)) return -EINVAL; + dev->ean[1 ] =le32_to_cpu (cmd.u.cardinfo.ean[1 ]); + dev->ean[0 ] =le32_to_cpu (cmd.u.cardinfo.ean[0 ]); + dev->serial_number =le32_to_cpu (cmd.u.cardinfo.serial_number); + dev->hw_revision = cmd.u.cardinfo.hw_revision;return 0 ; }
Signature · 1 line
2.49.0
PATCH 7/9 can: kvaser_usb: Add devlink support
In reply to Jimmy AssarssonAdd devlink support at device level.
Example output:
$ devlink dev usb/1-1.3:1.0
$ devlink dev info usb/1-1.3:1.0: driver kvaser_usb
--- drivers/net/can/usb/Kconfig | 1 + drivers/net/can/usb/kvaser_usb/Makefile | 2 +- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 3 + .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 72 ++++++++++++------- .../can/usb/kvaser_usb/kvaser_usb_devlink.c | 10 +++ 5 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c
drivers/net/can/usb/Kconfig +1 -0
@@ -66,6 +66,7 @@ config CAN_GS_USB config CAN_KVASER_USB tristate "Kvaser CAN/USB interface" + select NET_DEVLINK help This driver adds support for Kvaser CAN/USB devices like Kvaser Leaf Light, Kvaser USBcan II and Kvaser Memorator Pro 5xHS.
drivers/net/can/usb/kvaser_usb/Makefile +1 -1
@@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o -kvaser_usb-y = kvaser_usb_core.o kvaser_usb_leaf.o kvaser_usb_hydra.o +kvaser_usb-y = kvaser_usb_core.o kvaser_usb_devlink.o kvaser_usb_leaf.o kvaser_usb_hydra.o
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +3 -0
@@ -27,6 +27,7 @@#include <linux/spinlock.h> #include <linux/types.h> #include <linux/usb.h> +#include <net/devlink.h> #include <linux/can.h> #include <linux/can/dev.h>
@@ -226,6 +227,8 @@ struct kvaser_usb_dev_cfg {extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops;extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops; +extern const struct devlink_ops kvaser_usb_devlink_ops; +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,
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +47 -25
128 lines not on this page · raw message
drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c new file +10 -0
@@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +/* kvaser_usb devlink functions +* +* Copyright (C) 2025 KVASER AB, Sweden. All rights reserved. +*/ + +#include <net/devlink.h> + +const struct devlink_ops kvaser_usb_devlink_ops = { +};
Signature · 1 line
2.49.0
PATCH 8/9 can: kvaser_usb: Expose device information via devlink info_get()
In reply to Jimmy AssarssonExpose device information via devlink info_get():
* Serial number
* Firmware version
* Hardware revision
* EAN (product number)
Example output:
$ devlink dev usb/1-1.2:1.0
$ devlink dev info
usb/1-1.2:1.0:
driver kvaser_usb
serial_number 1020
versions:
fixed:
board.rev 1
board.id 7330130009653
running:
fw 3.22.527--- .../can/usb/kvaser_usb/kvaser_usb_devlink.c | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+)
drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c +53 -0
@@ -6,5 +6,58 @@#include <net/devlink.h> +#include "kvaser_usb.h" + +#define KVASER_USB_EAN_MSB 0x00073301 + +static int kvaser_usb_devlink_info_get (struct devlink *devlink, +struct devlink_info_req *req, +struct netlink_ext_ack *extack) +{ +struct kvaser_usb *dev =devlink_priv (devlink); +char buf[16 ];/* 73301XXXXXXXXXX */ +int ret; + +if (dev->serial_number) { +snprintf (buf,sizeof (buf),"%u" , dev->serial_number); + ret =devlink_info_serial_number_put (req, buf); +if (ret) +return ret; + } + +if (dev->fw_version.major) { +snprintf (buf,sizeof (buf),"%u.%u.%u" , + dev->fw_version.major, + dev->fw_version.minor, + dev->fw_version.build); + ret =devlink_info_version_running_put (req, +DEVLINK_INFO_VERSION_GENERIC_FW , + buf); +if (ret) +return ret; + } + +if (dev->hw_revision) { +snprintf (buf,sizeof (buf),"%u" , dev->hw_revision); + ret =devlink_info_version_fixed_put (req, +DEVLINK_INFO_VERSION_GENERIC_BOARD_REV , + buf); +if (ret) +return ret; + } + +if (dev->ean[1 ] ==KVASER_USB_EAN_MSB ) { +snprintf (buf,sizeof (buf),"%x%08x" , dev->ean[1 ], dev->ean[0 ]); + ret =devlink_info_version_fixed_put (req, +DEVLINK_INFO_VERSION_GENERIC_BOARD_ID , + buf); +if (ret) +return ret; + } + +return 0 ; +} +const struct devlink_ops kvaser_usb_devlink_ops = { + .info_get = kvaser_usb_devlink_info_get, };
Signature · 1 line
2.49.0
PATCH 9/9 can: kvaser_usb: Add devlink port support
In reply to Jimmy AssarssonRegister 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
--- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 4 +++ .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 15 ++++++++--- .../can/usb/kvaser_usb/kvaser_usb_devlink.c | 25 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-)
drivers/net/can/usb/kvaser_usb/kvaser_usb.h +4 -0
@@ -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,
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +12 -3
@@ -821,6 +821,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); } }
@@ -893,20 +894,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;
drivers/net/can/usb/kvaser_usb/kvaser_usb_devlink.c +25 -0
@@ -4,6 +4,7 @@* Copyright (C) 2025 KVASER AB, Sweden. All rights reserved. */ +#include <linux/netdevice.h> #include <net/devlink.h> #include "kvaser_usb.h"
@@ -61,3 +62,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); +}
Signature · 1 line
2.49.0
Quoted 3 lines · Jimmy Assarsson
This patch series simplifies the process of identifying which network interface (can0..canX) corresponds to which physical CAN channel on Kvaser USB based CAN interfaces.
This series mirrors the kvaser_pciefd one, so I will not repeat the same comment twice. I let you manage it directly :)
One last comment for both the kvaser_pciefd and the kvaser_usb: you may want to add an entry to the devlink documentation. Something like this:
- https://git.kernel.org/torvalds/c/9f63f96aac92
- https://git.kernel.org/torvalds/c/115dd5469019
Yours sincerely,
Vincent Mailhol
Quoted 8 lines · Vincent Mailhol
Quoted 3 lines · Jimmy Assarsson
This patch series simplifies the process of identifying which network interface (can0..canX) corresponds to which physical CAN channel on Kvaser USB based CAN interfaces.
This series mirrors the
kvaser_pciefdone, so I will not repeat the same comment twice. I let you manage it directly :)
Quoted 8 lines
One last comment for both the
kvaser_pciefdand thekvaser_usb: you may want to add an entry to the devlink documentation. Something like this:- https://git.kernel.org/torvalds/c/9f63f96aac92
- https://git.kernel.org/torvalds/c/115dd5469019Yours sincerely,
Vincent Mailhol
Hi Vincent,
Thanks for great review comments!
I think I've fixed all of them for kvaser_pciefd in v2 [1].
I'll send v2 of the kvaser_usb series once we've straighten out the usage of netdev.dev_{id,port}.
[1] https://lore.kernel.org/linux-can/[email protected]/T/#m8f7fa76d70b4c7c32c69f74035663cdb330fdf02
Best regards,
jimmy