can: virtio: Add virtio CAN driver
Subsystems (3)
Matias Ezequiel Vara Larsen
maintainerPATCH v8 1/1 can: virtio: Add virtio CAN driver
Add virtio CAN driver based on Virtio 1.4 specification (see
https://github.com/oasis-tcs/virtio-spec/tree/virtio-1.4). The driver implements a complete CAN bus interface over Virtio transport, supporting both CAN Classic and CAN-FD Ids. In term of frames, it supports classic and CAN FD. RTR frames are only supported with classic CAN.
Usage:
- "ip link set up can0" - start controller
- "ip link set down can0" - stop controller
- "candump can0" - receive frames
- "cansend can0 123#DEADBEEF" - send frames
---
V8:
* Address nits
V7:
* Address nits
* Remove unnecessary comments
* Remove io_callbacks[]
* Use guard() syntax
* Remove kicking for each inbuf
* replace sdu_len with rpkt_len
* Use devm_kzalloc()
* Use scoped_guard() to protect virtqueue_add_sgs() and virtqueue_kicks() for tx queue
* Tested with vhost-device-can
(see https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-can) and Qemu (942b0d3) with [1]. A reviewer observed that the device stops to work after flooding from host. This issue is still present.
[1]
https://lore.kernel.org/qemu-devel/[email protected]/
V6:
* Address nits
* Check for error during register_virtio_can()
* Remove virtio_device_ready()
* Allocate virtio_can_rx rpkt[] at probe
* Define virtio_can_control struct
* Return VIRTIO_CAN_RESULT_NOT_OK after unlocking
* Define sdu[] as a flex array for both tx and rx. For rx, use VIRTIO_CAN_F_CAN_FD to figure out the max len for sdu
* Fix statistics in virtio_can_read_tx_queue() and
how we indicate error to the user when getting VIRTIO_CAN_RESULT_NOT_OK
* Fix syntax of virtio_find_vqs()
* Drop tx_list
* Fix values of VIRTIO_CAN_F_LATE_TX_ACK and VIRTIO_CAN_F_RTR_FRAMES
* Tested with vhost-device-can
(see
https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-can)
and qemu (see
https://github.com/virtualopensystems/qemu/tree/vhu-can-rfc)
V5:
* Re-base on top of linux-next (next-20240103)
* Tested with https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3
RFC V4:
* Apply reverse Christmas tree style
* Add member *classic_dlc to RX and TX CAN frames
* Fix race causing a NETDEV_TX_BUSY return
* Fix TX queue going stuck on -ENOMEM
* Update stats.tx_dropped on kzalloc() failure
* Replace "(err != 0)" with "(unlikely(err))"
* Use "ARRAY_SIZE(sgs)"
* Refactor SGs in virtio_can_send_ctrl_msg()
* Tested with https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3
RFC V3:
* Incorporate patch "[PATCH] can: virtio-can: cleanups" from
https://lore.kernel.org/all/[email protected]/
* Add missing can_free_echo_skb()
* Replace home-brewed ID allocator with the standard one from kernel
* Simplify flow control
* Tested with https://github.com/OpenSynergy/qemu/tree/virtio-can-spec-rfc-v3
RFC V2:
* Remove the event indication queue and use the config space instead, to indicate a bus off condition
* Rework RX and TX messages having a length field and some more fields for CAN EXT
--- MAINTAINERS | 8 + drivers/net/can/Kconfig | 12 + drivers/net/can/Makefile | 1 + drivers/net/can/virtio_can.c | 951 ++++++++++++++++++++++++++++++++ include/uapi/linux/virtio_can.h | 78 +++ 5 files changed, 1050 insertions(+) create mode 100644 drivers/net/can/virtio_can.c create mode 100644 include/uapi/linux/virtio_can.h
MAINTAINERS +8 -0
@@ -27068,6 +27068,14 @@ F: drivers/scsi/virtio_scsi.c F: include/uapi/linux/virtio_blk.h F: include/uapi/linux/virtio_scsi.h +VIRTIO CAN DRIVER +M: "Harald Mommer" <[email protected]> +L: [email protected] +L: [email protected] +S: Maintained +F: drivers/net/can/virtio_can.c +F: include/uapi/linux/virtio_can.h + VIRTIO CONSOLE DRIVER M: Amit Shah <[email protected]> L: [email protected]
drivers/net/can/Kconfig +12 -0
@@ -217,6 +217,18 @@ config CAN_XILINXCAN Xilinx CAN driver. This driver supports both soft AXI CAN IP and Zynq CANPS IP. +config CAN_VIRTIO_CAN + depends on VIRTIO + tristate "Virtio CAN device support" + default n + help + Say Y here if you want to support for Virtio CAN. + + To compile this driver as a module, choose M here: the + module will be called virtio-can. + + If unsure, say N. + source "drivers/net/can/c_can/Kconfig" source "drivers/net/can/cc770/Kconfig" source "drivers/net/can/ctucanfd/Kconfig"
drivers/net/can/Makefile +1 -0
@@ -32,6 +32,7 @@ obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/ obj-$(CONFIG_CAN_SJA1000) += sja1000/ obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o +obj-$(CONFIG_CAN_VIRTIO_CAN) += virtio_can.o obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
drivers/net/can/virtio_can.c new file +951 -0
951 lines not on this page · raw message
include/uapi/linux/virtio_can.h new file +78 -0
78 lines not on this page · raw message
base-commit: 0d97f2067c166eb495771fede9f7b73999c67f66
Signature · 1 line
2.42.0
Hi Matias,
If an additional version is foreseen, consider dropping some more note-like comments, as in future they might become dangling.
E.g.:
On Tue, Jan 20, 2026 at 07:05:38PM +0100, Matias Ezequiel Vara Larsen wrote:
[...]
Quoted 7 lines
drivers/net/can/virtio_can.c new file +7
-0+ +/* Poll TX used queue for sent CAN messages +* See https://wiki.linuxfoundation.org/networking/napi function +* int (*poll)(struct napi_struct *napi, int budget); +*/ +static int virtio_can_tx_poll (struct napi_struct *napi,int quota) +{
[...]
Quoted 3 lines
drivers/net/can/virtio_can.c new file +3
-0+/* See m_can_poll() / m_can_handle_state_errors() m_can_handle_state_change() */ +static int virtio_can_handle_busoff (struct net_device *dev) +{
[...]
Quoted 9 lines
drivers/net/can/virtio_can.c new file +9
-0+/* Poll RX used queue for received CAN messages +* See https://wiki.linuxfoundation.org/networking/napi function +* int (*poll)(struct napi_struct *napi, int budget); +* Important: "The networking subsystem promises that poll() will not be +* invoked simultaneously (for the same napi_struct) on multiple processors" +*/ +static int virtio_can_rx_poll (struct napi_struct *napi,int quota) +{ +
[...]
Quoted 5 lines
drivers/net/can/virtio_can.c new file +5
-0+/* Compare with m_can.c/m_can_suspend(), virtio_net.c/virtnet_freeze() and +* virtio_card.c/virtsnd_freeze() +*/ +static int __maybe_unused virtio_can_freeze (struct virtio_device *vdev) +{
[...]
drivers/net/can/virtio_can.c line 894
Quoted 6 lines
drivers/net/can/virtio_can.c new file +6
-0+ +/* Compare with m_can.c/m_can_resume(), virtio_net.c/virtnet_restore() and +* virtio_card.c/virtsnd_restore() +*/ +static int __maybe_unused virtio_can_restore (struct virtio_device *vdev) +{
With this (maybe negligible) note considered:
Thank you!
Regards,
Francesco
Matias Ezequiel Vara Larsen
maintainerQuoted 5 lines · Francesco Valla
Hi Matias,
If an additional version is foreseen, consider dropping some more note-like comments, as in future they might become dangling.
Yes! I am planing to remove some comments and send v9. I was not completely sure which ones. Also, I was thinking to set myself as a maintainer in case Harald is busy.
Quoted 51 lines
E.g.:
On Tue, Jan 20, 2026 at 07:05:38PM +0100, Matias Ezequiel Vara Larsen wrote:
[...]
Quoted 7 lines
drivers/net/can/virtio_can.c new file +7
-0+ +/* Poll TX used queue for sent CAN messages +* See https://wiki.linuxfoundation.org/networking/napi function +* int (*poll)(struct napi_struct *napi, int budget); +*/ +static int virtio_can_tx_poll (struct napi_struct *napi,int quota) +{[...]
Quoted 3 lines
drivers/net/can/virtio_can.c new file +3
-0+/* See m_can_poll() / m_can_handle_state_errors() m_can_handle_state_change() */ +static int virtio_can_handle_busoff (struct net_device *dev) +{[...]
Quoted 9 lines
drivers/net/can/virtio_can.c new file +9
-0+/* Poll RX used queue for received CAN messages +* See https://wiki.linuxfoundation.org/networking/napi function +* int (*poll)(struct napi_struct *napi, int budget); +* Important: "The networking subsystem promises that poll() will not be +* invoked simultaneously (for the same napi_struct) on multiple processors" +*/ +static int virtio_can_rx_poll (struct napi_struct *napi,int quota) +{ +[...]
Quoted 5 lines
drivers/net/can/virtio_can.c new file +5
-0+/* Compare with m_can.c/m_can_suspend(), virtio_net.c/virtnet_freeze() and +* virtio_card.c/virtsnd_freeze() +*/ +static int __maybe_unused virtio_can_freeze (struct virtio_device *vdev) +{[...]
drivers/net/can/virtio_can.c line 894
Quoted 6 lines
drivers/net/can/virtio_can.c new file +6
-0+ +/* Compare with m_can.c/m_can_resume(), virtio_net.c/virtnet_restore() and +* virtio_card.c/virtsnd_restore() +*/ +static int __maybe_unused virtio_can_restore (struct virtio_device *vdev) +{With this (maybe negligible) note considered:
Quoted 3 lines
Reviewed-by Francesco Valla <[email protected]>Tested-by Francesco Valla <[email protected]>
Thanks Francesco!
Matias