Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: kvaser_pciefd: Add devlink port support

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
pci/0000:07:00.0
pci/0000:08:00.0
pci/0000:09:00.0

$ devlink port
pci/0000:07:00.0/0: type eth netdev can0 flavour physical port 0 splittable false
pci/0000:07:00.0/1: type eth netdev can1 flavour physical port 1 splittable false
pci/0000:07:00.0/2: type eth netdev can2 flavour physical port 2 splittable false
pci/0000:07:00.0/3: type eth netdev can3 flavour physical port 3 splittable false
pci/0000:08:00.0/0: type eth netdev can4 flavour physical port 0 splittable false
pci/0000:08:00.0/1: type eth netdev can5 flavour physical port 1 splittable false
pci/0000:09:00.0/0: type eth netdev can6 flavour physical port 0 splittable false
pci/0000:09:00.0/1: type eth netdev can7 flavour physical port 1 splittable false
pci/0000:09:00.0/2: type eth netdev can8 flavour physical port 2 splittable false
pci/0000:09:00.0/3: type eth netdev can9 flavour physical port 3 splittable false

$ devlink port show can2
pci/0000:07:00.0/2: type eth netdev can2 flavour physical port 2 splittable false

$ devlink dev info
pci/0000:07:00.0:
driver kvaser_pciefd
versions:
running:
fw 1.3.75
pci/0000:08:00.0:
driver kvaser_pciefd
versions:
running:
fw 2.4.29
pci/0000:09:00.0:
driver kvaser_pciefd
versions:
running:
fw 1.3.72

$ sudo ethtool -i can2
driver: kvaser_pciefd
version: 6.8.0-40-generic
firmware-version: 1.3.75
expansion-rom-version:
bus-info: 0000:07:00.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/20250725123230.8-10-extja@kvaser.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Jimmy Assarsson and committed by
Marc Kleine-Budde
6271c8b8 3d68ecf4

+37
+4
drivers/net/can/kvaser_pciefd/kvaser_pciefd.h
··· 59 59 60 60 struct kvaser_pciefd_can { 61 61 struct can_priv can; 62 + struct devlink_port devlink_port; 62 63 struct kvaser_pciefd *kv_pcie; 63 64 void __iomem *reg_base; 64 65 struct can_berr_counter bec; ··· 90 89 }; 91 90 92 91 extern const struct devlink_ops kvaser_pciefd_devlink_ops; 92 + 93 + int kvaser_pciefd_devlink_port_register(struct kvaser_pciefd_can *can); 94 + void kvaser_pciefd_devlink_port_unregister(struct kvaser_pciefd_can *can); 93 95 #endif /* _KVASER_PCIEFD_H */
+8
drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
··· 943 943 struct net_device *netdev; 944 944 struct kvaser_pciefd_can *can; 945 945 u32 status, tx_nr_packets_max; 946 + int ret; 946 947 947 948 netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), 948 949 roundup_pow_of_two(KVASER_PCIEFD_CAN_TX_MAX_COUNT)); ··· 1014 1013 1015 1014 pcie->can[i] = can; 1016 1015 kvaser_pciefd_pwm_start(can); 1016 + ret = kvaser_pciefd_devlink_port_register(can); 1017 + if (ret) { 1018 + dev_err(&pcie->pci->dev, "Failed to register devlink port\n"); 1019 + return ret; 1020 + } 1017 1021 } 1018 1022 1019 1023 return 0; ··· 1738 1732 if (can) { 1739 1733 iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 1740 1734 kvaser_pciefd_pwm_stop(can); 1735 + kvaser_pciefd_devlink_port_unregister(can); 1741 1736 free_candev(can->can.dev); 1742 1737 } 1743 1738 } ··· 1881 1874 unregister_candev(can->can.dev); 1882 1875 timer_delete(&can->bec_poll_timer); 1883 1876 kvaser_pciefd_pwm_stop(can); 1877 + kvaser_pciefd_devlink_port_unregister(can); 1884 1878 } 1885 1879 1886 1880 kvaser_pciefd_disable_irq_srcs(pcie);
+25
drivers/net/can/kvaser_pciefd/kvaser_pciefd_devlink.c
··· 5 5 */ 6 6 #include "kvaser_pciefd.h" 7 7 8 + #include <linux/netdevice.h> 8 9 #include <net/devlink.h> 9 10 10 11 static int kvaser_pciefd_devlink_info_get(struct devlink *devlink, ··· 34 33 const struct devlink_ops kvaser_pciefd_devlink_ops = { 35 34 .info_get = kvaser_pciefd_devlink_info_get, 36 35 }; 36 + 37 + int kvaser_pciefd_devlink_port_register(struct kvaser_pciefd_can *can) 38 + { 39 + int ret; 40 + struct devlink_port_attrs attrs = { 41 + .flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL, 42 + .phys.port_number = can->can.dev->dev_port, 43 + }; 44 + devlink_port_attrs_set(&can->devlink_port, &attrs); 45 + 46 + ret = devlink_port_register(priv_to_devlink(can->kv_pcie), 47 + &can->devlink_port, can->can.dev->dev_port); 48 + if (ret) 49 + return ret; 50 + 51 + SET_NETDEV_DEVLINK_PORT(can->can.dev, &can->devlink_port); 52 + 53 + return 0; 54 + } 55 + 56 + void kvaser_pciefd_devlink_port_unregister(struct kvaser_pciefd_can *can) 57 + { 58 + devlink_port_unregister(&can->devlink_port); 59 + }