drivers/infiniband/core/frmr_pools.c
Source file repositories/reference/linux-study-clean/drivers/infiniband/core/frmr_pools.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/infiniband/core/frmr_pools.c- Extension
.c- Size
- 14802 bytes
- Lines
- 596
- Domain
- Driver Families
- Bucket
- drivers/infiniband
- 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/slab.hlinux/rbtree.hlinux/sort.hlinux/spinlock.hrdma/ib_verbs.hlinux/timer.hfrmr_pools.h
Detected Declarations
function Copyrightfunction pop_handle_from_queue_lockedfunction pop_frmr_handles_pagefunction destroy_all_handles_in_queuefunction splice_frmr_queue_lockedfunction age_pinned_poolfunction pool_aging_workfunction destroy_frmr_poolfunction ib_frmr_pools_initfunction ib_frmr_pools_cleanupfunction ib_frmr_pools_set_aging_periodfunction compare_keysfunction frmr_pool_cmp_findfunction frmr_pool_cmp_addfunction ib_frmr_pools_set_pinnedfunction get_frmr_from_poolfunction ib_frmr_pool_popfunction ib_frmr_pool_pushfunction ib_frmr_pool_dropexport ib_frmr_pools_initexport ib_frmr_pools_cleanupexport ib_frmr_pool_popexport ib_frmr_pool_pushexport ib_frmr_pool_drop
Annotated Snippet
while (free_in_tail && src->ci) {
handle = pop_handle_from_queue_locked(src);
push_handle_to_queue_locked(dst, handle);
free_in_tail--;
}
}
if (src->ci > 0) {
list_splice_tail_init(&src->pages_list, &dst->pages_list);
dst->num_pages += src->num_pages;
dst->ci += src->ci;
src->num_pages = 0;
src->ci = 0;
}
}
static bool age_pinned_pool(struct ib_device *device, struct ib_frmr_pool *pool)
{
struct ib_frmr_pools *pools = device->frmr_pools;
u32 total, to_destroy, destroyed = 0;
bool has_work = false;
u32 *handles;
spin_lock(&pool->lock);
total = pool->queue.ci + pool->inactive_queue.ci + pool->in_use;
if (total <= pool->pinned_handles) {
spin_unlock(&pool->lock);
return false;
}
to_destroy = min(total - pool->pinned_handles, pool->inactive_queue.ci);
handles = kcalloc(to_destroy, sizeof(*handles), GFP_ATOMIC);
if (!handles) {
spin_unlock(&pool->lock);
return true;
}
/* Destroy all excess handles in the inactive queue */
for (; destroyed < to_destroy; destroyed++)
handles[destroyed] = pop_handle_from_queue_locked(
&pool->inactive_queue);
/* Move all handles from regular queue to inactive queue */
if (pool->queue.ci > 0) {
splice_frmr_queue_locked(&pool->inactive_queue, &pool->queue);
has_work = true;
}
spin_unlock(&pool->lock);
if (destroyed)
pools->pool_ops->destroy_frmrs(device, handles, destroyed);
kfree(handles);
return has_work;
}
static void pool_aging_work(struct work_struct *work)
{
struct ib_frmr_pool *pool = container_of(
to_delayed_work(work), struct ib_frmr_pool, aging_work);
struct ib_frmr_pools *pools = pool->device->frmr_pools;
bool has_work = false;
if (pool->pinned_handles) {
has_work = age_pinned_pool(pool->device, pool);
goto out;
}
destroy_all_handles_in_queue(pool->device, pool, &pool->inactive_queue);
/* Move all pages from regular queue to inactive queue */
spin_lock(&pool->lock);
if (pool->queue.ci > 0) {
splice_frmr_queue_locked(&pool->inactive_queue, &pool->queue);
has_work = true;
}
spin_unlock(&pool->lock);
out:
/* Reschedule if there are handles to age in next aging period */
if (has_work)
queue_delayed_work(
pools->aging_wq, &pool->aging_work,
secs_to_jiffies(READ_ONCE(pools->aging_period_sec)));
}
static void destroy_frmr_pool(struct ib_device *device,
struct ib_frmr_pool *pool)
{
Annotation
- Immediate include surface: `linux/slab.h`, `linux/rbtree.h`, `linux/sort.h`, `linux/spinlock.h`, `rdma/ib_verbs.h`, `linux/timer.h`, `frmr_pools.h`.
- Detected declarations: `function Copyright`, `function pop_handle_from_queue_locked`, `function pop_frmr_handles_page`, `function destroy_all_handles_in_queue`, `function splice_frmr_queue_locked`, `function age_pinned_pool`, `function pool_aging_work`, `function destroy_frmr_pool`, `function ib_frmr_pools_init`, `function ib_frmr_pools_cleanup`.
- Atlas domain: Driver Families / drivers/infiniband.
- 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.