I'm trying to add deferred io support to
drivers/gpu/drm/drm_gem_cma_helper.c.
This is a fbdev helper for DRM.
The first problem is that fb_deferred_io_page() requires either a vmalloc
address or a physical address:
if (is_vmalloc_addr(screen_base + offs))
page = vmalloc_to_page(screen_base + offs);
else
page = pfn_to_page((info->fix.smem_start + offs) >>
PAGE_SHIFT);
However drm_fb_cma_helper allocates memory this way:
cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
&cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN);
The name paddr is somewhat misleading here since this is the device address
which isn't always the same as the physical address (Raspberry Pi). Is
there a way to turn the virtual address into a physical one which will work
on all architectures?
I use __va() now, but that is marked as not for use by drivers in
arch/arm/include/asm/memory.h (the same goes for virt_to_phys).
Maybe this is valid for all? page_to_phys(virt_to_page(x))
I have looked at all the users of fb_deferred_io_init() and found only
3 drivers that doesn't use a vmalloc screen buffer:
drivers/gpu/drm/udl/udl_fb.c:
obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL);
info->screen_base = ufbdev->ufb.obj->vmapping;
info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping;
Since it uses vmap() I guess it is_vmalloc_addr().
drivers/video/fbdev/sh_mobile_lcdcfb.c:
ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
GFP_KERNEL);
info->screen_base = ch->fb_mem;
info->fix.smem_start = ch->dma_handle;
It uses dma_mmap_coherent() in it's fb_mmap function, but nothing special
with it's deferred_io use.
drivers/video/fbdev/ssd1307fb.c:
vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(vmem_size));
info->screen_base = (u8 __force __iomem *)vmem;
info->fix.smem_start = __pa(vmem);
So maybe this could be possible:
static struct page *fb_deferred_io_page(struct fb_info *info, unsigned
long offs)
{
void *screen_base = (void __force *) info->screen_base;
struct page *page;
if (is_vmalloc_addr(screen_base + offs))
page = vmalloc_to_page(screen_base + offs);
else
- page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT);
+ page = virt_to_page(screen_base + offs);
return page;
}
The second problem I'm facing is that I get short horizontal lines that have
old pixels. My problem goes away if I add this to fb_deferred_io_mmap():
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
Is there a way to add this to fb_deferred_io_mmap() with some kind of if
statement, or perhaps export the function so I can use it like this:
static int drm_fbdev_cma_defio_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
fb_deferred_io_mmap(info, vma);
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
return 0;
}
Thanks,
Noralf Trønnes
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html