drivers/vfio/pci/pds/lm.c

Source file repositories/reference/linux-study-clean/drivers/vfio/pci/pds/lm.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/pci/pds/lm.c
Extension
.c
Size
10174 bytes
Lines
445
Domain
Driver Families
Bucket
drivers/vfio
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.

Dependency Surface

Detected Declarations

Annotated Snippet

pds_vfio_get_lm_file(const struct file_operations *fops, int flags, u64 size)
{
	struct pds_vfio_lm_file *lm_file = NULL;
	unsigned long long npages;
	struct page **pages;
	void *page_mem;
	const void *p;

	if (!size)
		return NULL;

	/* Alloc file structure */
	lm_file = kzalloc_obj(*lm_file);
	if (!lm_file)
		return NULL;

	/* Create file */
	lm_file->filep =
		anon_inode_getfile("pds_vfio_lm", fops, lm_file, flags);
	if (IS_ERR(lm_file->filep))
		goto out_free_file;

	stream_open(lm_file->filep->f_inode, lm_file->filep);
	mutex_init(&lm_file->lock);

	/* prevent file from being released before we are done with it */
	get_file(lm_file->filep);

	/* Allocate memory for file pages */
	npages = DIV_ROUND_UP_ULL(size, PAGE_SIZE);
	pages = kmalloc_objs(*pages, npages);
	if (!pages)
		goto out_put_file;

	page_mem = kvzalloc(ALIGN(size, PAGE_SIZE), GFP_KERNEL);
	if (!page_mem)
		goto out_free_pages_array;

	p = page_mem - offset_in_page(page_mem);
	for (unsigned long long i = 0; i < npages; i++) {
		if (is_vmalloc_addr(p))
			pages[i] = vmalloc_to_page(p);
		else
			pages[i] = kmap_to_page((void *)p);
		if (!pages[i])
			goto out_free_page_mem;

		p += PAGE_SIZE;
	}

	/* Create scatterlist of file pages to use for DMA mapping later */
	if (sg_alloc_table_from_pages(&lm_file->sg_table, pages, npages, 0,
				      size, GFP_KERNEL))
		goto out_free_page_mem;

	lm_file->size = size;
	lm_file->pages = pages;
	lm_file->npages = npages;
	lm_file->page_mem = page_mem;
	lm_file->alloc_size = npages * PAGE_SIZE;

	return lm_file;

out_free_page_mem:
	kvfree(page_mem);
out_free_pages_array:
	kfree(pages);
out_put_file:
	fput(lm_file->filep);
	mutex_destroy(&lm_file->lock);
out_free_file:
	kfree(lm_file);

	return NULL;
}

static void pds_vfio_put_lm_file(struct pds_vfio_lm_file *lm_file)
{
	mutex_lock(&lm_file->lock);

	lm_file->disabled = true;
	lm_file->size = 0;
	lm_file->alloc_size = 0;
	lm_file->filep->f_pos = 0;

	/* Free scatter list of file pages */
	sg_free_table(&lm_file->sg_table);

	kvfree(lm_file->page_mem);
	lm_file->page_mem = NULL;

Annotation

Implementation Notes