Esempio n. 1
0
static int hmm_reserved_pool_init(void **pool, unsigned int pool_size)
{
	int ret;
	unsigned int blk_pgnr;
	unsigned int pgnr = pool_size;
	unsigned int order = 0;
	unsigned int i = 0;
	int fail_number = 0;
	struct page *pages;
	int j;
	struct hmm_reserved_pool_info *repool_info;
	if (pool_size == 0)
		return 0;

	ret = hmm_reserved_pool_setup(&repool_info, pool_size);
	if (ret) {
		dev_err(atomisp_dev, "hmm_reserved_pool_setup failed.\n");
		return ret;
	}

	pgnr = pool_size;

	i = 0;
	order = MAX_ORDER;

	while (pgnr) {
		blk_pgnr = 1U << order;
		while (blk_pgnr > pgnr) {
			order--;
			blk_pgnr >>= 1U;
		}
		BUG_ON(order > MAX_ORDER);

		pages = alloc_pages(GFP_KERNEL | __GFP_NOWARN, order);
		if (unlikely(!pages)) {
			if (order == 0) {
				fail_number++;
				dev_err(atomisp_dev, "%s: alloc_pages failed: %d\n",
						__func__, fail_number);
				/* if fail five times, will goto end */

				/* FIXME: whether is the mechanism is ok? */
				if (fail_number == ALLOC_PAGE_FAIL_NUM)
					goto end;
			} else {
				order--;
			}
		} else {
			blk_pgnr = 1U << order;

			ret = set_pages_uc(pages, blk_pgnr);
			if (ret) {
				dev_err(atomisp_dev,
						"set pages uncached failed\n");
				__free_pages(pages, order);
				goto end;
			}

			for (j = 0; j < blk_pgnr; j++)
				repool_info->pages[i++] = pages + j;

			repool_info->index += blk_pgnr;
			repool_info->pgnr += blk_pgnr;

			pgnr -= blk_pgnr;

			fail_number = 0;
		}
	}

end:
	repool_info->initialized = true;

	*pool = repool_info;

	dev_info(atomisp_dev,
			"hmm_reserved_pool init successfully,"
			"hmm_reserved_pool is with %d pages.\n",
			repool_info->pgnr);
	return 0;
}
static int hmm_reserved_pool_init(void **priv_data, unsigned int pool_size)
{
	int ret;
	unsigned int pgnr, order, blk_pgnr, i;
	int fail_number = 0;
	struct page *pages;
	int j;
	struct hmm_reserved_pool_info *repool_info;
	gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;

	if (pool_size == 0)
		return -EINVAL;

	ret = hmm_reserved_pool_setup(&repool_info, pool_size);
	if (ret) {
		v4l2_err(&atomisp_dev,
			    "hmm_reserved_pool_setup failed.\n");
		return ret;
	}

	pgnr = pool_size;

	i = 0;
	order = 0;

	while (pgnr) {
		pages = alloc_pages(gfp, order);
		if (unlikely(!pages)) {
			fail_number++;
			v4l2_err(&atomisp_dev,
				 "%s: cannot allocate pages, fail number is %d times.\n",
				 __func__, fail_number);
			/* if fail five times, will goto end */

			/* FIXME: whether is the mechanism is ok? */
			if (fail_number == ALLOC_PAGE_FAIL_NUM)
				goto end;
		} else {
			blk_pgnr = 1U << order;

			/*
			 * set memory to uncacheable -- UC_MINUS
			 */
			ret = set_pages_uc(pages, blk_pgnr);
			if (ret) {
				v4l2_err(&atomisp_dev,
					     "set page uncacheable"
						"failed.\n");
				__free_pages(pages, order);
				goto end;
			}

			for (j = 0; j < blk_pgnr; j++)
				repool_info->pages[i++] = pages + j;

			repool_info->index += blk_pgnr;
			repool_info->pgnr += blk_pgnr;

			pgnr -= blk_pgnr;

			fail_number = 0;
		}
	}

end:
	repool_info->flag = HMM_RESERVED_POOL_INITED;

	*priv_data = repool_info;

	v4l2_info(&atomisp_dev,
			"hmm_reserved_pool init successfully,"
			"hmm_reserved_pool is with %d pages.\n",
			repool_info->pgnr);
	return 0;
}