drivers/net/can/virtio_can.c
Source file repositories/reference/linux-study-clean/drivers/net/can/virtio_can.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/can/virtio_can.c- Extension
.c- Size
- 25867 bytes
- Lines
- 1023
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/atomic.hlinux/idr.hlinux/interrupt.hlinux/io.hlinux/kernel.hlinux/module.hlinux/mutex.hlinux/netdevice.hlinux/stddef.hlinux/can/dev.hlinux/virtio.hlinux/virtio_ring.hlinux/virtio_can.h
Detected Declarations
struct virtio_can_txstruct virtio_can_controlstruct virtio_can_privfunction virtqueue_napi_schedulefunction virtqueue_napi_completefunction virtio_can_free_candevfunction virtio_can_napi_enablefunction virtio_can_napi_disablefunction virtio_can_alloc_tx_idxfunction virtio_can_free_tx_idxfunction virtio_can_add_inbuffunction virtio_can_send_ctrl_msgfunction virtio_can_startfunction virtio_can_set_modefunction virtio_can_openfunction virtio_can_stopfunction virtio_can_closefunction virtio_can_start_xmitfunction scoped_guardfunction register_virtio_can_devfunction virtio_can_read_tx_queuefunction virtio_can_tx_pollfunction virtio_can_tx_intrfunction virtio_can_read_rx_queuefunction virtio_can_handle_busofffunction virtio_can_rx_pollfunction virtio_can_rx_intrfunction virtio_can_control_intrfunction virtio_can_config_changedfunction virtio_can_populate_rx_vqfunction virtio_can_find_vqsfunction virtio_can_del_vqfunction virtio_can_removefunction virtio_can_validatefunction virtio_can_probefunction virtio_can_freezefunction virtio_can_restore
Annotated Snippet
static const struct net_device_ops virtio_can_netdev_ops = {
.ndo_open = virtio_can_open,
.ndo_stop = virtio_can_close,
.ndo_start_xmit = virtio_can_start_xmit,
};
static int register_virtio_can_dev(struct net_device *dev)
{
dev->flags |= IFF_ECHO; /* we support local echo */
dev->netdev_ops = &virtio_can_netdev_ops;
return register_candev(dev);
}
static int virtio_can_read_tx_queue(struct virtqueue *vq)
{
struct virtio_can_priv *can_priv = vq->vdev->priv;
struct net_device *dev = can_priv->dev;
struct virtio_can_tx *can_tx_msg;
struct net_device_stats *stats;
unsigned int len;
u8 result;
stats = &dev->stats;
scoped_guard(spinlock_irqsave, &can_priv->tx_lock)
can_tx_msg = virtqueue_get_buf(vq, &len);
if (!can_tx_msg)
return 0;
if (unlikely(len < sizeof(struct virtio_can_tx_in))) {
netdev_err(dev, "TX ACK: Device sent no result code\n");
result = VIRTIO_CAN_RESULT_NOT_OK; /* Keep things going */
} else {
result = can_tx_msg->tx_in.result;
}
if (can_priv->can.state < CAN_STATE_BUS_OFF) {
if (result != VIRTIO_CAN_RESULT_OK) {
struct can_frame *skb_cf;
struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf);
if (skb) {
skb_cf->can_id |= CAN_ERR_CRTL;
skb_cf->data[1] |= CAN_ERR_CRTL_UNSPEC;
netif_rx(skb);
}
netdev_warn(dev, "TX ACK: Result = %u\n", result);
can_free_echo_skb(dev, can_tx_msg->putidx, NULL);
stats->tx_dropped++;
} else {
stats->tx_bytes += can_get_echo_skb(dev, can_tx_msg->putidx,
NULL);
stats->tx_packets++;
}
} else {
netdev_dbg(dev, "TX ACK: Controller inactive, drop echo\n");
can_free_echo_skb(dev, can_tx_msg->putidx, NULL);
stats->tx_dropped++;
}
virtio_can_free_tx_idx(can_priv, can_tx_msg->putidx);
/* Flow control */
if (netif_queue_stopped(dev)) {
netdev_dbg(dev, "TX ACK: Wake up stopped queue\n");
netif_wake_queue(dev);
}
kfree(can_tx_msg);
return 1; /* Queue was not empty so there may be more data */
}
static int virtio_can_tx_poll(struct napi_struct *napi, int quota)
{
struct net_device *dev = napi->dev;
struct virtio_can_priv *priv = netdev_priv(dev);
struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_TX];
int work_done = 0;
while (work_done < quota && virtio_can_read_tx_queue(vq) != 0)
work_done++;
if (work_done < quota)
virtqueue_napi_complete(napi, vq, work_done);
return work_done;
}
Annotation
- Immediate include surface: `linux/atomic.h`, `linux/idr.h`, `linux/interrupt.h`, `linux/io.h`, `linux/kernel.h`, `linux/module.h`, `linux/mutex.h`, `linux/netdevice.h`.
- Detected declarations: `struct virtio_can_tx`, `struct virtio_can_control`, `struct virtio_can_priv`, `function virtqueue_napi_schedule`, `function virtqueue_napi_complete`, `function virtio_can_free_candev`, `function virtio_can_napi_enable`, `function virtio_can_napi_disable`, `function virtio_can_alloc_tx_idx`, `function virtio_can_free_tx_idx`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.