Problems using fb_deferred_io with drm_fb_cma_helper

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Tourism]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux