mm/dmapool.c

Source file repositories/reference/linux-study-clean/mm/dmapool.c

File Facts

System
Linux kernel
Corpus path
mm/dmapool.c
Extension
.c
Size
13512 bytes
Lines
528
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dma_block {
	struct dma_block *next_block;
	dma_addr_t dma;
};

struct dma_pool {		/* the pool */
	struct list_head page_list;
	spinlock_t lock;
	struct dma_block *next_block;
	size_t nr_blocks;
	size_t nr_active;
	size_t nr_pages;
	struct device *dev;
	unsigned int size;
	unsigned int allocation;
	unsigned int boundary;
	int node;
	char name[32];
	struct list_head pools;
};

struct dma_page {		/* cacheable header for 'allocation' bytes */
	struct list_head page_list;
	void *vaddr;
	dma_addr_t dma;
};

static DEFINE_MUTEX(pools_lock);
static DEFINE_MUTEX(pools_reg_lock);

static ssize_t pools_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct dma_pool *pool;
	unsigned size;

	size = sysfs_emit(buf, "poolinfo - 0.1\n");

	mutex_lock(&pools_lock);
	list_for_each_entry(pool, &dev->dma_pools, pools) {
		/* per-pool info, no real statistics yet */
		size += sysfs_emit_at(buf, size, "%-16s %4zu %4zu %4u %2zu\n",
				      pool->name, pool->nr_active,
				      pool->nr_blocks, pool->size,
				      pool->nr_pages);
	}
	mutex_unlock(&pools_lock);

	return size;
}

static DEVICE_ATTR_RO(pools);

#ifdef DMAPOOL_DEBUG
static void pool_check_block(struct dma_pool *pool, struct dma_block *block,
			     gfp_t mem_flags)
{
	u8 *data = (void *)block;
	int i;

	for (i = sizeof(struct dma_block); i < pool->size; i++) {
		if (data[i] == POOL_POISON_FREED)
			continue;
		dev_err(pool->dev, "%s %s, %p (corrupted)\n", __func__,
			pool->name, block);

		/*
		 * Dump the first 4 bytes even if they are not
		 * POOL_POISON_FREED
		 */
		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1,
				data, pool->size, 1);
		break;
	}

	if (!want_init_on_alloc(mem_flags))
		memset(block, POOL_POISON_ALLOCATED, pool->size);
}

static struct dma_page *pool_find_page(struct dma_pool *pool, dma_addr_t dma)
{
	struct dma_page *page;

	list_for_each_entry(page, &pool->page_list, page_list) {
		if (dma < page->dma)
			continue;
		if ((dma - page->dma) < pool->allocation)
			return page;
	}
	return NULL;
}

Annotation

Implementation Notes