drivers/hv/ring_buffer.c
Source file repositories/reference/linux-study-clean/drivers/hv/ring_buffer.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/hv/ring_buffer.c- Extension
.c- Size
- 19562 bytes
- Lines
- 655
- Domain
- Driver Families
- Bucket
- drivers/hv
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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/kernel.hlinux/mm.hlinux/hyperv.hlinux/uio.hlinux/vmalloc.hlinux/slab.hlinux/prefetch.hlinux/io.hlinux/export.hasm/mshyperv.hhyperv_vmbus.h
Detected Declarations
function Copyrightfunction hv_get_next_write_locationfunction hv_set_next_write_locationfunction hv_get_ring_buffersizefunction hv_get_ring_bufferindicesfunction hv_copyto_ringbufferfunction hv_get_ringbuffer_availbytesfunction hv_ringbuffer_get_debuginfofunction hv_ringbuffer_pre_initfunction hv_ringbuffer_initfunction hv_ringbuffer_cleanupfunction hv_ringbuffer_spinlock_busyfunction hv_ringbuffer_writefunction hv_ringbuffer_readfunction iteratorfunction locationfunction hv_pkt_iter_bytes_readfunction hv_pkt_iter_closeexport hv_ringbuffer_get_debuginfoexport hv_ringbuffer_spinlock_busyexport hv_pkt_iter_firstexport __hv_pkt_iter_nextexport hv_pkt_iter_close
Annotated Snippet
if (!channel->out_full_flag) {
++channel->out_full_first;
channel->out_full_flag = true;
}
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
return -EAGAIN;
}
channel->out_full_flag = false;
/* Write to the ring buffer */
next_write_location = hv_get_next_write_location(outring_info);
old_write = next_write_location;
for (i = 0; i < kv_count; i++) {
next_write_location = hv_copyto_ringbuffer(outring_info,
next_write_location,
kv_list[i].iov_base,
kv_list[i].iov_len);
}
/*
* Allocate the request ID after the data has been copied into the
* ring buffer. Once this request ID is allocated, the completion
* path could find the data and free it.
*/
if (desc->flags == VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED) {
if (channel->next_request_id_callback != NULL) {
rqst_id = channel->next_request_id_callback(channel, requestid);
if (rqst_id == VMBUS_RQST_ERROR) {
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
return -EAGAIN;
}
}
}
desc = hv_get_ring_buffer(outring_info) + old_write;
__trans_id = (rqst_id == VMBUS_NO_RQSTOR) ? requestid : rqst_id;
/*
* Ensure the compiler doesn't generate code that reads the value of
* the transaction ID from the ring buffer, which is shared with the
* Hyper-V host and subject to being changed at any time.
*/
WRITE_ONCE(desc->trans_id, __trans_id);
if (trans_id)
*trans_id = __trans_id;
/* Set previous packet start */
prev_indices = hv_get_ring_bufferindices(outring_info);
next_write_location = hv_copyto_ringbuffer(outring_info,
next_write_location,
&prev_indices,
sizeof(u64));
/* Issue a full memory barrier before updating the write index */
virt_mb();
/* Now, update the write location */
hv_set_next_write_location(outring_info, next_write_location);
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
hv_signal_on_write(old_write, channel);
if (channel->rescind) {
if (rqst_id != VMBUS_NO_RQSTOR) {
/* Reclaim request ID to avoid leak of IDs */
if (channel->request_addr_callback != NULL)
channel->request_addr_callback(channel, rqst_id);
}
return -ENODEV;
}
return 0;
}
int hv_ringbuffer_read(struct vmbus_channel *channel,
void *buffer, u32 buflen, u32 *buffer_actual_len,
u64 *requestid, bool raw)
{
struct vmpacket_descriptor *desc;
u32 packetlen, offset;
if (unlikely(buflen == 0))
return -EINVAL;
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/mm.h`, `linux/hyperv.h`, `linux/uio.h`, `linux/vmalloc.h`, `linux/slab.h`, `linux/prefetch.h`, `linux/io.h`.
- Detected declarations: `function Copyright`, `function hv_get_next_write_location`, `function hv_set_next_write_location`, `function hv_get_ring_buffersize`, `function hv_get_ring_bufferindices`, `function hv_copyto_ringbuffer`, `function hv_get_ringbuffer_availbytes`, `function hv_ringbuffer_get_debuginfo`, `function hv_ringbuffer_pre_init`, `function hv_ringbuffer_init`.
- Atlas domain: Driver Families / drivers/hv.
- Implementation status: integration 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.