コード例 #1
0
ファイル: videobuf-dma-sg.c プロジェクト: lumag/linux
static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
			int direction, unsigned long data, unsigned long size)
{
	unsigned long first, last;
	int err, rw = 0;
	unsigned int flags = FOLL_FORCE;

	dma->direction = direction;
	switch (dma->direction) {
	case DMA_FROM_DEVICE:
		rw = READ;
		break;
	case DMA_TO_DEVICE:
		rw = WRITE;
		break;
	default:
		BUG();
	}

	first = (data          & PAGE_MASK) >> PAGE_SHIFT;
	last  = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
	dma->offset = data & ~PAGE_MASK;
	dma->size = size;
	dma->nr_pages = last-first+1;
	dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL);
	if (NULL == dma->pages)
		return -ENOMEM;

	if (rw == READ)
		flags |= FOLL_WRITE;

	dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
		data, size, dma->nr_pages);

	err = get_user_pages_longterm(data & PAGE_MASK, dma->nr_pages,
			     flags, dma->pages, NULL);

	if (err != dma->nr_pages) {
		dma->nr_pages = (err >= 0) ? err : 0;
		dprintk(1, "get_user_pages_longterm: err=%d [%d]\n", err,
			dma->nr_pages);
		return err < 0 ? err : -EINVAL;
	}
	return 0;
}
コード例 #2
0
ファイル: gup_benchmark.c プロジェクト: Anjali05/linux
static int __gup_benchmark_ioctl(unsigned int cmd,
		struct gup_benchmark *gup)
{
	ktime_t start_time, end_time;
	unsigned long i, nr_pages, addr, next;
	int nr;
	struct page **pages;

	if (gup->size > ULONG_MAX)
		return -EINVAL;

	nr_pages = gup->size / PAGE_SIZE;
	pages = kvcalloc(nr_pages, sizeof(void *), GFP_KERNEL);
	if (!pages)
		return -ENOMEM;

	i = 0;
	nr = gup->nr_pages_per_call;
	start_time = ktime_get();
	for (addr = gup->addr; addr < gup->addr + gup->size; addr = next) {
		if (nr != gup->nr_pages_per_call)
			break;

		next = addr + nr * PAGE_SIZE;
		if (next > gup->addr + gup->size) {
			next = gup->addr + gup->size;
			nr = (next - addr) / PAGE_SIZE;
		}

		switch (cmd) {
		case GUP_FAST_BENCHMARK:
			nr = get_user_pages_fast(addr, nr, gup->flags & 1,
						 pages + i);
			break;
		case GUP_LONGTERM_BENCHMARK:
			nr = get_user_pages_longterm(addr, nr, gup->flags & 1,
						     pages + i, NULL);
			break;
		case GUP_BENCHMARK:
			nr = get_user_pages(addr, nr, gup->flags & 1, pages + i,
					    NULL);
			break;
		default:
			return -1;
		}

		if (nr <= 0)
			break;
		i += nr;
	}
	end_time = ktime_get();

	gup->get_delta_usec = ktime_us_delta(end_time, start_time);
	gup->size = addr - gup->addr;

	start_time = ktime_get();
	for (i = 0; i < nr_pages; i++) {
		if (!pages[i])
			break;
		put_page(pages[i]);
	}
	end_time = ktime_get();
	gup->put_delta_usec = ktime_us_delta(end_time, start_time);

	kvfree(pages);
	return 0;
}