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; } } }
/* 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; }