Example #1
0
File: fastdiv.c Project: alnsn/rgph
void
rgph_fastdiv_prepare(uint32_t div, uint32_t *m,
    uint8_t *s1, uint8_t *s2, int branchless)
{
	/* fast_divide32(3) from NetBSD. */
	const int l = fls32(div - 1);
	const uint64_t nextpow2 = UINT64_C(1) << l;
	uint32_t rem, magic = ((nextpow2 - div) << 32) / div;

	*m = magic + 1;
	*s1 = (l > 1) ? 1 : l;
	*s2 = (l == 0) ? 0 : l - 1;

	if (branchless || div == 1)
		return;

	if (magic == 0) { /* div == nextpow2 */
		*s1 -= 1;
		*s2 += 1;
	} else {
		/*
		 * See libdivide_internal_u32_gen()
		 * by ridiculous_fish for clues.
		 */
		magic = (magic + UINT64_C(0x100000000)) / 2;
		rem = (nextpow2 << 31) - magic * div;
		assert(rem > 0 && rem < div);
		if (rem > div - (nextpow2 / 2)) {
			*m = magic + 1;
			*s1 -= 1;
		}
	}
}
Example #2
0
/* Round the specified buffer size up to the next valid LZX window size, and
 * return its order (log2).  Or, if the buffer size is 0 or greater than the
 * largest valid LZX window size, return 0.  */
unsigned
lzx_get_window_order(size_t max_bufsize)
{
	unsigned order;

	if (max_bufsize == 0 || max_bufsize > LZX_MAX_WINDOW_SIZE)
		return 0;

	order = fls32(max_bufsize);

	if (((u32)1 << order) != max_bufsize)
		order++;

	return max(order, LZX_MIN_WINDOW_ORDER);
}
static int
gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
	     u32 memtype, struct nouveau_mem **pmem)
{
#if !defined(__NetBSD__)
	struct device *dev = nv_device_base(nv_device(pfb));
	int i;
#endif
	struct gk20a_mem *mem;
	u32 type = memtype & 0xff;
	u32 npages, order;

	nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__,
		 (unsigned long long)size, align, ncmin);

	npages = size >> PAGE_SHIFT;
	if (npages == 0)
		npages = 1;

	if (align == 0)
		align = PAGE_SIZE;
	align >>= PAGE_SHIFT;

	/* round alignment to the next power of 2, if needed */
#if defined(__NetBSD__)
	order = fls32(align);
#else
	order = fls(align);
#endif
	if ((align & (align - 1)) == 0)
		order--;
	align = BIT(order);

	/* ensure returned address is correctly aligned */
	npages = max(align, npages);

	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
	if (!mem)
		return -ENOMEM;

	mem->base.size = npages;
	mem->base.memtype = type;

#if defined(__NetBSD__)
	int ret, nsegs;

	if (align == 0)
		align = PAGE_SIZE;

	const bus_dma_tag_t dmat = nv_device(pfb)->platformdev->dmat;
	const bus_size_t dmasize = npages << PAGE_SHIFT;

	ret = -bus_dmamem_alloc(dmat, dmasize, align, 0,
	    &mem->dmaseg, 1, &nsegs, BUS_DMA_WAITOK);
	if (ret) {
fail0:		kfree(mem);
		return ret;
	}
	KASSERT(nsegs == 1);

	ret = -bus_dmamap_create(dmat, dmasize, nsegs, dmasize, 0,
	    BUS_DMA_WAITOK, &mem->base.pages);
	if (ret) {
fail1:		bus_dmamem_free(dmat, &mem->dmaseg, nsegs);
		goto fail0;
	}

	ret = -bus_dmamem_map(dmat, &mem->dmaseg, nsegs, dmasize,
	    &mem->cpuaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
	if (ret) {
fail2:		bus_dmamap_destroy(dmat, mem->base.pages);
		goto fail1;
	}
	memset(mem->cpuaddr, 0, dmasize);

	ret = -bus_dmamap_load(dmat, mem->base.pages, mem->cpuaddr,
	    dmasize, NULL, BUS_DMA_WAITOK);
	if (ret) {
fail3: __unused	bus_dmamem_unmap(dmat, mem->cpuaddr, dmasize);
		goto fail2;
	}

	nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %"PRIxPADDR
	   ", vaddr: %p\n", npages << PAGE_SHIFT, align,
	   mem->base.pages->dm_segs[0].ds_addr, mem->cpuaddr);

	mem->dmasize = dmasize;
	mem->base.offset = (u64)mem->base.pages->dm_segs[0].ds_addr;
	*pmem = &mem->base;
#else
	mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL);
	if (!mem->base.pages) {
		kfree(mem);
		return -ENOMEM;
	}

	*pmem = &mem->base;

	mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT,
					  &mem->handle, GFP_KERNEL);
	if (!mem->cpuaddr) {
		nv_error(pfb, "%s: cannot allocate memory!\n", __func__);
		gk20a_ram_put(pfb, pmem);
		return -ENOMEM;
	}

	align <<= PAGE_SHIFT;

	/* alignment check */
	if (unlikely(mem->handle & (align - 1)))
		nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n",
			&mem->handle, align);

	nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n",
		 npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr);

	for (i = 0; i < npages; i++)
		mem->base.pages[i] = mem->handle + (PAGE_SIZE * i);

	mem->base.offset = (u64)mem->base.pages[0];
#endif

	return 0;
}