From: Wei Hu <weh@xxxxxxxxxxxxx> Sent: Friday, December 6, 2019 3:32 AM > > On Hyper-V, Generation 1 VMs can directly use VM's physical memory for > their framebuffers. This can improve the efficiency of framebuffer and > overall performence for VM. The physical memory assigned to framebuffer > must be contiguous. We use CMA allocator to get contiguouse physicial > memory when the framebuffer size is greater than 4MB. For size under > 4MB, we use alloc_pages to achieve this. > > To enable framebuffer memory allocation from CMA, supply a kernel > parameter to give enough space to CMA allocator at boot time. For > example: > cma=130m > This gives 130MB memory to CAM allocator that can be allocated to > framebuffer. If this fails, we fall back to the old way of using > mmio for framebuffer. > > Reported-by: kbuild test robot <lkp@xxxxxxxxx> > Signed-off-by: Wei Hu <weh@xxxxxxxxxxxxx> > --- [snip] > +/* > + * Allocate enough contiguous physical memory. > + * Return physical address if succeeded or -1 if failed. > + */ > +static phys_addr_t hvfb_get_phymem(struct hv_device *hdev, > + unsigned int request_size) > +{ > + struct page *page = NULL; > + dma_addr_t dma_handle; > + void *vmem; > + unsigned int request_pages; > + phys_addr_t paddr = 0; > + unsigned int order = get_order(request_size); > + > + if (request_size == 0) > + return -1; > + > + if (order < MAX_ORDER) { > + /* Call alloc_pages if the size is less than 2^MAX_ORDER */ > + page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); > + if (!page) > + return -1; > + > + paddr = (page_to_pfn(page) << PAGE_SHIFT); > + request_pages = (1 << order); The above line is no longer needed. request_pages was previously an argument to a pr_info() statement, but that statement has appropriately been removed. > + } else { > + /* Allocate from CMA */ > + hdev->device.coherent_dma_mask = DMA_BIT_MASK(64); > + > + request_pages = (round_up(request_size, PAGE_SIZE) >> > + PAGE_SHIFT); > + > + vmem = dma_alloc_coherent(&hdev->device, > + request_pages * PAGE_SIZE, > + &dma_handle, > + GFP_KERNEL | __GFP_NOWARN); With the request_pages value no longer being needed, there's wasted motion in doing a PAGE_SHIFT shift to calculate request_pages, and then multiplying by PAGE_SIZE. The second argument above could just be round_up(request_size, PAGE_SIZE). Then it would be exactly parallel to the second argument to dma_free_coherent() below in hvfb_release_phymem(). The request_pages variable can be eliminated entirely. > + > + if (!vmem) > + return -1; > + > + paddr = virt_to_phys(vmem); > + } > + > + return paddr; > +} > + > +/* Release contiguous physical memory */ > +static void hvfb_release_phymem(struct hv_device *hdev, > + phys_addr_t paddr, unsigned int size) > +{ > + unsigned int order = get_order(size); > + > + if (order < MAX_ORDER) > + __free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order); > + else > + dma_free_coherent(&hdev->device, > + round_up(size, PAGE_SIZE), > + phys_to_virt(paddr), > + paddr); > +} > + > Everything else looks good. The most recent changes to hvfb_getmem() worked out very nicely. Michael