drivers/virt/acrn/ioreq.c
Source file repositories/reference/linux-study-clean/drivers/virt/acrn/ioreq.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/virt/acrn/ioreq.c- Extension
.c- Size
- 17435 bytes
- Lines
- 653
- Domain
- Driver Families
- Bucket
- drivers/virt
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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/interrupt.hlinux/io.hlinux/kthread.hlinux/mm.hlinux/slab.hasm/acrn.hacrn_drv.h
Detected Declarations
function has_pending_requestfunction is_destroyingfunction ioreq_complete_requestfunction acrn_ioreq_complete_requestfunction acrn_ioreq_request_default_completefunction acrn_ioreq_range_addfunction acrn_ioreq_range_delfunction ioreq_taskfunction acrn_ioreq_request_clearfunction list_for_each_entryfunction acrn_ioreq_client_waitfunction is_cfg_addrfunction is_cfg_datafunction handle_cf8cfcfunction acrn_in_rangefunction list_for_each_entryfunction list_for_each_entryfunction acrn_ioreq_client_createfunction acrn_ioreq_client_destroyfunction acrn_ioreq_dispatchfunction ioreq_dispatcherfunction ioreq_intr_handlerfunction ioreq_pausefunction ioreq_resumefunction acrn_ioreq_intr_setupfunction acrn_ioreq_intr_removefunction acrn_ioreq_initfunction acrn_ioreq_deinit
Annotated Snippet
while (has_pending_request(client)) {
vcpu = find_first_bit(ioreqs_map, client->vm->vcpu_num);
req = client->vm->ioreq_buf->req_slot + vcpu;
ret = client->handler(client, req);
if (ret < 0) {
dev_err(acrn_dev.this_device,
"IO handle failure: %d\n", ret);
break;
}
acrn_ioreq_complete_request(client, vcpu, req);
}
}
return 0;
}
/*
* For the non-default I/O clients, give them chance to complete the current
* I/O requests if there are any. For the default I/O client, it is safe to
* clear all pending I/O requests because the clearing request is from ACRN
* userspace.
*/
void acrn_ioreq_request_clear(struct acrn_vm *vm)
{
struct acrn_ioreq_client *client;
bool has_pending = false;
unsigned long vcpu;
int retry = 10;
/*
* IO requests of this VM will be completed directly in
* acrn_ioreq_dispatch if ACRN_VM_FLAG_CLEARING_IOREQ flag is set.
*/
set_bit(ACRN_VM_FLAG_CLEARING_IOREQ, &vm->flags);
/*
* acrn_ioreq_request_clear is only called in VM reset case. Simply
* wait 100ms in total for the IO requests' completion.
*/
do {
spin_lock_bh(&vm->ioreq_clients_lock);
list_for_each_entry(client, &vm->ioreq_clients, list) {
has_pending = has_pending_request(client);
if (has_pending)
break;
}
spin_unlock_bh(&vm->ioreq_clients_lock);
if (has_pending)
schedule_timeout_interruptible(HZ / 100);
} while (has_pending && --retry > 0);
if (retry == 0)
dev_warn(acrn_dev.this_device,
"%s cannot flush pending request!\n", client->name);
/* Clear all ioreqs belonging to the default client */
spin_lock_bh(&vm->ioreq_clients_lock);
client = vm->default_client;
if (client) {
for_each_set_bit(vcpu, client->ioreqs_map, ACRN_IO_REQUEST_MAX)
acrn_ioreq_complete_request(client, vcpu, NULL);
}
spin_unlock_bh(&vm->ioreq_clients_lock);
/* Clear ACRN_VM_FLAG_CLEARING_IOREQ flag after the clearing */
clear_bit(ACRN_VM_FLAG_CLEARING_IOREQ, &vm->flags);
}
int acrn_ioreq_client_wait(struct acrn_ioreq_client *client)
{
if (client->is_default) {
/*
* In the default client, a user space thread waits on the
* waitqueue. The is_destroying() check is used to notify user
* space the client is going to be destroyed.
*/
wait_event_interruptible(client->wq,
has_pending_request(client) ||
is_destroying(client));
if (is_destroying(client))
return -ENODEV;
} else {
wait_event_interruptible(client->wq,
has_pending_request(client) ||
kthread_should_stop());
}
return 0;
}
Annotation
- Immediate include surface: `linux/interrupt.h`, `linux/io.h`, `linux/kthread.h`, `linux/mm.h`, `linux/slab.h`, `asm/acrn.h`, `acrn_drv.h`.
- Detected declarations: `function has_pending_request`, `function is_destroying`, `function ioreq_complete_request`, `function acrn_ioreq_complete_request`, `function acrn_ioreq_request_default_complete`, `function acrn_ioreq_range_add`, `function acrn_ioreq_range_del`, `function ioreq_task`, `function acrn_ioreq_request_clear`, `function list_for_each_entry`.
- Atlas domain: Driver Families / drivers/virt.
- Implementation status: source 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.