/** * dma_contiguous_isolate() - isolate contiguous memory from the page allocator * @dev: Pointer to device which owns the contiguous memory * * This function isolates contiguous memory from the page allocator. If some of * the contiguous memory is allocated, it is reclaimed. */ int dma_contiguous_isolate(struct device *dev) { struct cma *cma = dev_get_cma_area(dev); int ret; int idx; if (!cma) return -ENODEV; if (cma->count == 0) return 0; mutex_lock(&cma_mutex); if (cma->isolated) { mutex_unlock(&cma_mutex); dev_err(dev, "Alread isolated!\n"); return 0; } idx = find_first_zero_bit(cma->bitmap, cma->count); while (idx < cma->count) { int idx_set; idx_set = find_next_bit(cma->bitmap, cma->count, idx); do { ret = alloc_contig_range(cma->base_pfn + idx, cma->base_pfn + idx_set, MIGRATE_CMA); } while (ret == -EBUSY); if (ret < 0) { mutex_unlock(&cma_mutex); dma_contiguous_deisolate_until(dev, idx_set); dev_err(dev, "Failed to isolate %#lx@%#010llx (%d).\n", (idx_set - idx) * PAGE_SIZE, PFN_PHYS(cma->base_pfn + idx), ret); return ret; } idx = find_next_zero_bit(cma->bitmap, cma->count, idx_set); } cma->isolated = true; mutex_unlock(&cma_mutex); return 0; }
/** * dma_contiguous_deisolate() - return contiguous memory to the page allocator * @dev: Pointer to device which owns the contiguous memory * * This function return the contiguous memory that is not allocated by CMA to * the page allocator so that the kernel can allocate the contiguous memory. */ void dma_contiguous_deisolate(struct device *dev) { struct cma *cma = dev_get_cma_area(dev); dma_contiguous_deisolate_until(dev, cma->count); }