brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 54b1fd1 Raw
149 lines · c
1#include <linux/device.h>2#include <linux/dma-map-ops.h>3#include <linux/dma-mapping.h>4#include <linux/dmapool.h>5#include <linux/kernel.h>6#include <linux/ktime.h>7#include <linux/module.h>8 9#define NR_TESTS (100)10 11struct dma_pool_pair {12	dma_addr_t dma;13	void *v;14};15 16struct dmapool_parms {17	size_t size;18	size_t align;19	size_t boundary;20};21 22static const struct dmapool_parms pool_parms[] = {23	{ .size = 16, .align = 16, .boundary = 0 },24	{ .size = 64, .align = 64, .boundary = 0 },25	{ .size = 256, .align = 256, .boundary = 0 },26	{ .size = 1024, .align = 1024, .boundary = 0 },27	{ .size = 4096, .align = 4096, .boundary = 0 },28	{ .size = 68, .align = 32, .boundary = 4096 },29};30 31static struct dma_pool *pool;32static struct device test_dev;33static u64 dma_mask;34 35static inline int nr_blocks(int size)36{37	return clamp_t(int, (PAGE_SIZE / size) * 512, 1024, 8192);38}39 40static int dmapool_test_alloc(struct dma_pool_pair *p, int blocks)41{42	int i;43 44	for (i = 0; i < blocks; i++) {45		p[i].v = dma_pool_alloc(pool, GFP_KERNEL,46					&p[i].dma);47		if (!p[i].v)48			goto pool_fail;49	}50 51	for (i = 0; i < blocks; i++)52		dma_pool_free(pool, p[i].v, p[i].dma);53 54	return 0;55 56pool_fail:57	for (--i; i >= 0; i--)58		dma_pool_free(pool, p[i].v, p[i].dma);59	return -ENOMEM;60}61 62static int dmapool_test_block(const struct dmapool_parms *parms)63{64	int blocks = nr_blocks(parms->size);65	ktime_t start_time, end_time;66	struct dma_pool_pair *p;67	int i, ret;68 69	p = kcalloc(blocks, sizeof(*p), GFP_KERNEL);70	if (!p)71		return -ENOMEM;72 73	pool = dma_pool_create("test pool", &test_dev, parms->size,74			       parms->align, parms->boundary);75	if (!pool) {76		ret = -ENOMEM;77		goto free_pairs;78	}79 80	start_time = ktime_get();81	for (i = 0; i < NR_TESTS; i++) {82		ret = dmapool_test_alloc(p, blocks);83		if (ret)84			goto free_pool;85		if (need_resched())86			cond_resched();87	}88	end_time = ktime_get();89 90	printk("dmapool test: size:%-4zu align:%-4zu blocks:%-4d time:%llu\n",91		parms->size, parms->align, blocks,92		ktime_us_delta(end_time, start_time));93 94free_pool:95	dma_pool_destroy(pool);96free_pairs:97	kfree(p);98	return ret;99}100 101static void dmapool_test_release(struct device *dev)102{103}104 105static int dmapool_checks(void)106{107	int i, ret;108 109	ret = dev_set_name(&test_dev, "dmapool-test");110	if (ret)111		return ret;112 113	ret = device_register(&test_dev);114	if (ret) {115		printk("%s: register failed:%d\n", __func__, ret);116		goto put_device;117	}118 119	test_dev.release = dmapool_test_release;120	set_dma_ops(&test_dev, NULL);121	test_dev.dma_mask = &dma_mask;122	ret = dma_set_mask_and_coherent(&test_dev, DMA_BIT_MASK(64));123	if (ret) {124		printk("%s: mask failed:%d\n", __func__, ret);125		goto del_device;126	}127 128	for (i = 0; i < ARRAY_SIZE(pool_parms); i++) {129		ret = dmapool_test_block(&pool_parms[i]);130		if (ret)131			break;132	}133 134del_device:135	device_del(&test_dev);136put_device:137	put_device(&test_dev);138	return ret;139}140 141static void dmapool_exit(void)142{143}144 145module_init(dmapool_checks);146module_exit(dmapool_exit);147MODULE_DESCRIPTION("dma_pool timing test");148MODULE_LICENSE("GPL");149