drivers/infiniband/core/umem_odp.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/core/umem_odp.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/core/umem_odp.c
Extension
.c
Size
13922 bytes
Lines
470
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (hmm_order + PAGE_SHIFT < page_shift) {
			ret = -EINVAL;
			ibdev_dbg(umem_odp->umem.ibdev,
				  "%s: un-expected hmm_order %u, page_shift %u\n",
				  __func__, hmm_order, page_shift);
			break;
		}
	}
	/* upon success lock should stay on hold for the callee */
	if (!ret)
		ret = dma_index - start_idx;
	else
		mutex_unlock(&umem_odp->umem_mutex);

out_put_mm:
	mmput_async(owning_mm);
out_put_task:
	if (owning_process)
		put_task_struct(owning_process);
	return ret;
}
EXPORT_SYMBOL(ib_umem_odp_map_dma_and_lock);

void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt,
				 u64 bound)
{
	struct ib_device *dev = umem_odp->umem.ibdev;
	u64 addr;

	lockdep_assert_held(&umem_odp->umem_mutex);

	virt = max_t(u64, virt, ib_umem_start(umem_odp));
	bound = min_t(u64, bound, ib_umem_end(umem_odp));
	for (addr = virt; addr < bound; addr += BIT(umem_odp->page_shift)) {
		u64 offset = addr - ib_umem_start(umem_odp);
		size_t idx = offset >> umem_odp->page_shift;
		unsigned long pfn = umem_odp->map.pfn_list[idx];

		if (!hmm_dma_unmap_pfn(dev->dma_device, &umem_odp->map, idx))
			goto clear;

		if (pfn & HMM_PFN_WRITE) {
			struct page *page = hmm_pfn_to_page(pfn);
			struct page *head_page = compound_head(page);
			/*
			 * set_page_dirty prefers being called with
			 * the page lock. However, MMU notifiers are
			 * called sometimes with and sometimes without
			 * the lock. We rely on the umem_mutex instead
			 * to prevent other mmu notifiers from
			 * continuing and allowing the page mapping to
			 * be removed.
			 */
			set_page_dirty(head_page);
		}
		umem_odp->npages--;
clear:
		umem_odp->map.pfn_list[idx] &= ~HMM_PFN_FLAGS;
	}
}
EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);

Annotation

Implementation Notes