All of lore.kernel.org
 help / color / mirror / Atom feed
From: zourongrong@huawei.com (Rongrong Zou)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 2/9] drm/hisilicon/hibmc: Add video memory management
Date: Fri, 11 Nov 2016 21:57:56 +0800	[thread overview]
Message-ID: <5825CE64.5080708@huawei.com> (raw)
In-Reply-To: <CAOw6vbJFitYby+cNezQvdtwJqNkSjhX2=S0QwUrL40gmv-Kozg@mail.gmail.com>

? 2016/11/11 21:25, Sean Paul ??:
> On Fri, Nov 11, 2016 at 6:16 AM, Rongrong Zou <zourongrong@huawei.com> wrote:
>> ? 2016/11/11 1:35, Sean Paul ??:
>>>
>>> On Fri, Oct 28, 2016 at 3:27 AM, Rongrong Zou <zourongrong@gmail.com>
>>> wrote:
>>>>
>>>> Hibmc have 32m video memory which can be accessed through PCIe by host,
>>>> we use ttm to manage these memory.
>>>>
>>>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>>>> ---
>>>>    drivers/gpu/drm/hisilicon/hibmc/Kconfig         |   1 +
>>>>    drivers/gpu/drm/hisilicon/hibmc/Makefile        |   2 +-
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |  12 +
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |  46 +++
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c     | 490
>>>> ++++++++++++++++++++++++
>>>>    5 files changed, 550 insertions(+), 1 deletion(-)
>>>>    create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>>
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> index a9af90d..bcb8c18 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> @@ -1,6 +1,7 @@
>>>>    config DRM_HISI_HIBMC
>>>>           tristate "DRM Support for Hisilicon Hibmc"
>>>>           depends on DRM && PCI
>>>> +       select DRM_TTM
>>>>
>>>>           help
>>>>             Choose this option if you have a Hisilicon Hibmc soc chipset.
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> index 97cf4a0..d5c40b8 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> @@ -1,5 +1,5 @@
>>>>    ccflags-y := -Iinclude/drm
>>>> -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>>>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o hibmc_ttm.o
>>>>
>>>>    obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
>>>>    #obj-y += hibmc-drm.o
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> index 4669d42..81f4301 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> @@ -31,6 +31,7 @@
>>>>    #ifdef CONFIG_COMPAT
>>>>           .compat_ioctl   = drm_compat_ioctl,
>>>>    #endif
>>>> +       .mmap           = hibmc_mmap,
>>>>           .poll           = drm_poll,
>>>>           .read           = drm_read,
>>>>           .llseek         = no_llseek,
>>>> @@ -46,6 +47,8 @@ static void hibmc_disable_vblank(struct drm_device
>>>> *dev, unsigned int pipe)
>>>>    }
>>>>
>>>>    static struct drm_driver hibmc_driver = {
>>>> +       .driver_features        = DRIVER_GEM,
>>>> +
>>>
>>>
>>> nit: extra space
>>>
>>>>           .fops                   = &hibmc_fops,
>>>>           .name                   = "hibmc",
>>>>           .date                   = "20160828",
>>>> @@ -55,6 +58,10 @@ static void hibmc_disable_vblank(struct drm_device
>>>> *dev, unsigned int pipe)
>>>>           .get_vblank_counter     = drm_vblank_no_hw_counter,
>>>>           .enable_vblank          = hibmc_enable_vblank,
>>>>           .disable_vblank         = hibmc_disable_vblank,
>>>> +       .gem_free_object_unlocked = hibmc_gem_free_object,
>>>> +       .dumb_create            = hibmc_dumb_create,
>>>> +       .dumb_map_offset        = hibmc_dumb_mmap_offset,
>>>> +       .dumb_destroy           = drm_gem_dumb_destroy,
>>>>    };
>>>>
>>>>    static int hibmc_pm_suspend(struct device *dev)
>>>> @@ -163,6 +170,7 @@ static int hibmc_unload(struct drm_device *dev)
>>>>    {
>>>>           struct hibmc_drm_device *hidev = dev->dev_private;
>>>>
>>>> +       hibmc_mm_fini(hidev);
>>>>           hibmc_hw_fini(hidev);
>>>>           dev->dev_private = NULL;
>>>>           return 0;
>>>> @@ -183,6 +191,10 @@ static int hibmc_load(struct drm_device *dev,
>>>> unsigned long flags)
>>>>           if (ret)
>>>>                   goto err;
>>>>
>>>> +       ret = hibmc_mm_init(hidev);
>>>> +       if (ret)
>>>> +               goto err;
>>>> +
>>>>           return 0;
>>>>
>>>>    err:
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> index 0037341..db8d80e 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> @@ -20,6 +20,8 @@
>>>>    #define HIBMC_DRM_DRV_H
>>>>
>>>>    #include <drm/drmP.h>
>>>> +#include <drm/ttm/ttm_bo_driver.h>
>>>> +#include <drm/drm_gem.h>
>>>
>>>
>>> nit: alphabetize
>>
>>
>> will fix it, thanks.
>>
>>>
>>>>
>>>>    struct hibmc_drm_device {
>>>>           /* hw */
>>>> @@ -30,6 +32,50 @@ struct hibmc_drm_device {
>>>>
>>>>           /* drm */
>>>>           struct drm_device  *dev;
>>>> +
>>>> +       /* ttm */
>>>> +       struct {
>>>> +               struct drm_global_reference mem_global_ref;
>>>> +               struct ttm_bo_global_ref bo_global_ref;
>>>> +               struct ttm_bo_device bdev;
>>>> +               bool initialized;
>>>> +       } ttm;
>>>
>>>
>>> I don't think you gain anything other than keystrokes from the substruct
>>
>>
>> I'm sorry i didn't catch you, i looked at the all drivers used ttm such
>> as ast/bochs/cirrus/mgag200/qxl/virtio_gpu, they all embedded the ttm
>> substruct
>> into the driver-private struct.
>>
>> so do you mean
>> struct hibmc_drm_device {
>>          /* hw */
>>          void __iomem   *mmio;
>>          void __iomem   *fb_map;
>>          unsigned long  fb_base;
>>          unsigned long  fb_size;
>>
>>          /* drm */
>>          struct drm_device  *dev;
>>          struct drm_plane plane;
>>          struct drm_crtc crtc;
>>          struct drm_encoder encoder;
>>          struct drm_connector connector;
>>          bool mode_config_initialized;
>>
>>          /* ttm */
>>          struct drm_global_reference mem_global_ref;
>>          struct ttm_bo_global_ref bo_global_ref;
>>          struct ttm_bo_device bdev;
>>          bool initialized;
>>          ...
>>          };
>> ?
>
> Yeah, that's what I was thinking
>
>>
>>>
>>>> +
>>>> +       bool mm_inited;
>>>>    };
>>>>
>>>> +struct hibmc_bo {
>>>> +       struct ttm_buffer_object bo;
>>>> +       struct ttm_placement placement;
>>>> +       struct ttm_bo_kmap_obj kmap;
>>>> +       struct drm_gem_object gem;
>>>> +       struct ttm_place placements[3];
>>>> +       int pin_count;
>>>> +};
>>>> +
>>>> +static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
>>>> +{
>>>> +       return container_of(bo, struct hibmc_bo, bo);
>>>> +}
>>>> +
>>>> +static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object
>>>> *gem)
>>>> +{
>>>> +       return container_of(gem, struct hibmc_bo, gem);
>>>> +}
>>>> +
>>>> +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
>>>
>>>
>>> Hide this in ttm.c
>>
>>
>> ok, will do that.
>> thanks for pointing it out.
>>
>>
>>>
>>>> +
>>>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>>>> +                    struct drm_gem_object **obj);
>>>> +
>>>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc);
>>>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc);
>>>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
>>>> +void hibmc_gem_free_object(struct drm_gem_object *obj);
>>>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>>>> +                     struct drm_mode_create_dumb *args);
>>>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device
>>>> *dev,
>>>> +                          u32 handle, u64 *offset);
>>>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
>>>> +
>>>>    #endif
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> new file mode 100644
>>>> index 0000000..0802ebd
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> @@ -0,0 +1,490 @@
>>>> +/* Hisilicon Hibmc SoC drm driver
>>>> + *
>>>> + * Based on the bochs drm driver.
>>>> + *
>>>> + * Copyright (c) 2016 Huawei Limited.
>>>> + *
>>>> + * Author:
>>>> + *     Rongrong Zou <zourongrong@huawei.com>
>>>> + *     Rongrong Zou <zourongrong@gmail.com>
>>>> + *     Jianhua Li <lijianhua@huawei.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License as published by
>>>> + * the Free Software Foundation; either version 2 of the License, or
>>>> + * (at your option) any later version.
>>>> + *
>>>> + */
>>>> +
>>>> +#include "hibmc_drm_drv.h"
>>>> +#include <ttm/ttm_page_alloc.h>
>>>> +#include <drm/drm_crtc_helper.h>
>>>> +#include <drm/drm_atomic_helper.h>
>>>> +
>>>> +static inline struct hibmc_drm_device *
>>>> +hibmc_bdev(struct ttm_bo_device *bd)
>>>> +{
>>>> +       return container_of(bd, struct hibmc_drm_device, ttm.bdev);
>>>> +}
>>>> +
>>>> +static int
>>>> +hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
>>>> +{
>>>> +       return ttm_mem_global_init(ref->object);
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
>>>> +{
>>>> +       ttm_mem_global_release(ref->object);
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_global_init(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       struct drm_global_reference *global_ref;
>>>> +       int r;
>>>
>>>
>>> nit: try not to use one character variable names unless it's for the
>>> purpose of a loop (ie: i,j). You also use ret elsewhere in the driver,
>>> so it'd be nice to remain consistent
>>
>>
>> the whole file is delivered from bochs ttm, i didn't modify anything except
>> some checkpatch warnings and the 'hibmc_' prefix. Unfortunately, some
>> problems were delivered too.
>
> Yeah, seems like it. Perhaps you can post patches to fix these issues
> in the other drivers too :)

i will do after the this one get merged :)

>
>>
>>>
>>>> +
>>>> +       global_ref = &hibmc->ttm.mem_global_ref;
>>>
>>>
>>> I think using the global_ref local obfuscates what you're doing here.
>>> It saves you 6 characters while typing, but adds a layer of
>>> indirection for all future readers.
>>>
>>>> +       global_ref->global_type = DRM_GLOBAL_TTM_MEM;
>>>> +       global_ref->size = sizeof(struct ttm_mem_global);
>>>> +       global_ref->init = &hibmc_ttm_mem_global_init;
>>>> +       global_ref->release = &hibmc_ttm_mem_global_release;
>>>> +       r = drm_global_item_ref(global_ref);
>>>> +       if (r != 0) {
>>>
>>>
>>> nit: if (r)
>>
>>
>> will fix it,
>> thanks.
>> BTW, i wonder why checkpatch.pl didn't report it.
>>
>>
>>>
>>>> +               DRM_ERROR("Failed setting up TTM memory accounting
>>>> subsystem.\n"
>>>> +                        );
>>>
>>>
>>> Breaking up the line for one character is probably not worthwhile, and
>>> you should really print the error. How about:
>>>
>>> DRM_ERROR("Could not get ref on ttm global ret=%d.\n", ret);
>>
>>
>> i like your solution, thanks.
>>
>>
>>>
>>>
>>>> +               return r;
>>>> +       }
>>>> +
>>>> +       hibmc->ttm.bo_global_ref.mem_glob =
>>>> +               hibmc->ttm.mem_global_ref.object;
>>>> +       global_ref = &hibmc->ttm.bo_global_ref.ref;
>>>> +       global_ref->global_type = DRM_GLOBAL_TTM_BO;
>>>> +       global_ref->size = sizeof(struct ttm_bo_global);
>>>> +       global_ref->init = &ttm_bo_global_init;
>>>> +       global_ref->release = &ttm_bo_global_release;
>>>> +       r = drm_global_item_ref(global_ref);
>>>> +       if (r != 0) {
>>>> +               DRM_ERROR("Failed setting up TTM BO subsystem.\n");
>>>> +               drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>>>> +               return r;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_ttm_global_release(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       if (!hibmc->ttm.mem_global_ref.release)
>>>
>>>
>>> Are you actually hitting this condition? This seems like it's papering
>>> over something else.
>>
>>
>> it was also delivered from others, i looked at the xxx_ttm_global_init
>> function, 'mem_global_ref.release' is assigned unconditionally, so i
>> think this condition never be hit, it may be hit when release twice,
>> but this won't take place in my driver.
>>
>
> Yeah, that's what I was hoping for. So perhaps we can remove this?

yes, we can.

Regards,
Rongrong.

>
>>>
>>>> +               return;
>>>> +
>>>> +       drm_global_item_unref(&hibmc->ttm.bo_global_ref.ref);
>>>> +       drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>>>> +       hibmc->ttm.mem_global_ref.release = NULL;
>>>> +}
>>>> +
>>>> +static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
>>>> +{
>>>> +       struct hibmc_bo *bo;
>>>> +
>>>> +       bo = container_of(tbo, struct hibmc_bo, bo);
>>>
>>>
>>> nit: No need to split this into a separate line.
>>
>>
>> agreed, thanks.
>>
>>>
>>>> +
>>>> +       drm_gem_object_release(&bo->gem);
>>>> +       kfree(bo);
>>>> +}
>>>> +
>>>> +static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
>>>> +{
>>>> +       if (bo->destroy == &hibmc_bo_ttm_destroy)
>>>> +               return true;
>>>> +       return false;
>>>
>>>
>>> return bo->destroy == &hibmc_bo_ttm_destroy;
>>
>>
>> looks better to me.
>>
>>
>>>
>>>> +}
>>>> +
>>>> +static int
>>>> +hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
>>>> +                      struct ttm_mem_type_manager *man)
>>>> +{
>>>> +       switch (type) {
>>>> +       case TTM_PL_SYSTEM:
>>>> +               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
>>>> +               man->available_caching = TTM_PL_MASK_CACHING;
>>>> +               man->default_caching = TTM_PL_FLAG_CACHED;
>>>> +               break;
>>>> +       case TTM_PL_VRAM:
>>>> +               man->func = &ttm_bo_manager_func;
>>>> +               man->flags = TTM_MEMTYPE_FLAG_FIXED |
>>>> +                       TTM_MEMTYPE_FLAG_MAPPABLE;
>>>> +               man->available_caching = TTM_PL_FLAG_UNCACHED |
>>>> +                       TTM_PL_FLAG_WC;
>>>> +               man->default_caching = TTM_PL_FLAG_WC;
>>>> +               break;
>>>> +       default:
>>>> +               DRM_ERROR("Unsupported memory type %u\n", type);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
>>>> +{
>>>> +       u32 c = 0;
>>>
>>>
>>> Can you please use a more descriptive name than 'c'?
>>
>>
>> ok, will do that.
>>
>>>
>>>> +       u32 i;
>>>> +
>>>> +       bo->placement.placement = bo->placements;
>>>> +       bo->placement.busy_placement = bo->placements;
>>>> +       if (domain & TTM_PL_FLAG_VRAM)
>>>> +               bo->placements[c++].flags = TTM_PL_FLAG_WC |
>>>> +               TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
>>>
>>>
>>> nit: you're alignment is off here and below
>>
>>
>> is it correct?
>>
>>          if (domain & TTM_PL_FLAG_VRAM)
>>                  bo->placements[c++].flags = TTM_PL_FLAG_WC |
>>                          TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
>>          if (domain & TTM_PL_FLAG_SYSTEM)
>>                  bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>                          TTM_PL_FLAG_SYSTEM;
>>          if (!c)
>>                  bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>                          TTM_PL_FLAG_SYSTEM;
>>
>
> Pretty much anything other than lining them up one under the other is better
>
>>>
>>>> +       if (domain & TTM_PL_FLAG_SYSTEM)
>>>> +               bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>>> +               TTM_PL_FLAG_SYSTEM;
>>>> +       if (!c)
>>>> +               bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>>> +               TTM_PL_FLAG_SYSTEM;
>>>> +
>>>> +       bo->placement.num_placement = c;
>>>> +       bo->placement.num_busy_placement = c;
>>>> +       for (i = 0; i < c; ++i) {
>>>
>>>
>>> nit: we tend towards post-increment in kernel
>>
>>
>> agreed, thanks.
>>
>>
>>>
>>>> +               bo->placements[i].fpfn = 0;
>>>> +               bo->placements[i].lpfn = 0;
>>>> +       }
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement
>>>> *pl)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>>>> +
>>>> +       if (!hibmc_ttm_bo_is_hibmc_bo(bo))
>>>> +               return;
>>>> +
>>>> +       hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
>>>> +       *pl = hibmcbo->placement;
>>>> +}
>>>> +
>>>> +static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
>>>> +                                 struct file *filp)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>>>> +
>>>> +       return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
>>>> +                                         filp->private_data);
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
>>>> +                                   struct ttm_mem_reg *mem)
>>>> +{
>>>> +       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
>>>> +       struct hibmc_drm_device *hibmc = hibmc_bdev(bdev);
>>>> +
>>>> +       mem->bus.addr = NULL;
>>>> +       mem->bus.offset = 0;
>>>> +       mem->bus.size = mem->num_pages << PAGE_SHIFT;
>>>> +       mem->bus.base = 0;
>>>> +       mem->bus.is_iomem = false;
>>>> +       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
>>>> +               return -EINVAL;
>>>> +       switch (mem->mem_type) {
>>>> +       case TTM_PL_SYSTEM:
>>>> +               /* system memory */
>>>> +               return 0;
>>>> +       case TTM_PL_VRAM:
>>>> +               mem->bus.offset = mem->start << PAGE_SHIFT;
>>>> +               mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
>>>> +               mem->bus.is_iomem = true;
>>>> +               break;
>>>> +       default:
>>>> +               return -EINVAL;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void hibmc_ttm_io_mem_free(struct ttm_bo_device *bdev,
>>>> +                                 struct ttm_mem_reg *mem)
>>>> +{
>>>> +}
>>>
>>>
>>> No need to stub this, the caller does a NULL-check before invoking
>>
>>
>> will delete it, thanks.
>>
>>>
>>>> +
>>>> +static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
>>>> +{
>>>> +       ttm_tt_fini(tt);
>>>> +       kfree(tt);
>>>> +}
>>>> +
>>>> +static struct ttm_backend_func hibmc_tt_backend_func = {
>>>> +       .destroy = &hibmc_ttm_backend_destroy,
>>>> +};
>>>> +
>>>> +static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
>>>> +                                         unsigned long size,
>>>> +                                         u32 page_flags,
>>>> +                                         struct page *dummy_read_page)
>>>> +{
>>>> +       struct ttm_tt *tt;
>>>> +
>>>> +       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
>>>> +       if (!tt)
>>>
>>>
>>> Print error
>>
>>
>> ok, will do that, thanks.
>>
>>>
>>>> +               return NULL;
>>>> +       tt->func = &hibmc_tt_backend_func;
>>>> +       if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
>>>
>>>
>>> Here too?
>>
>>
>> ditto
>>
>>
>>>
>>>> +               kfree(tt);
>>>> +               return NULL;
>>>> +       }
>>>> +       return tt;
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
>>>> +{
>>>> +       return ttm_pool_populate(ttm);
>>>> +}
>>>> +
>>>> +static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
>>>> +{
>>>> +       ttm_pool_unpopulate(ttm);
>>>> +}
>>>> +
>>>> +struct ttm_bo_driver hibmc_bo_driver = {
>>>> +       .ttm_tt_create          = hibmc_ttm_tt_create,
>>>> +       .ttm_tt_populate        = hibmc_ttm_tt_populate,
>>>> +       .ttm_tt_unpopulate      = hibmc_ttm_tt_unpopulate,
>>>> +       .init_mem_type          = hibmc_bo_init_mem_type,
>>>> +       .evict_flags            = hibmc_bo_evict_flags,
>>>> +       .move                   = NULL,
>>>> +       .verify_access          = hibmc_bo_verify_access,
>>>> +       .io_mem_reserve         = &hibmc_ttm_io_mem_reserve,
>>>> +       .io_mem_free            = &hibmc_ttm_io_mem_free,
>>>> +       .lru_tail               = &ttm_bo_default_lru_tail,
>>>> +       .swap_lru_tail          = &ttm_bo_default_swap_lru_tail,
>>>> +};
>>>> +
>>>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       int ret;
>>>> +       struct drm_device *dev = hibmc->dev;
>>>> +       struct ttm_bo_device *bdev = &hibmc->ttm.bdev;
>>>> +
>>>> +       ret = hibmc_ttm_global_init(hibmc);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       ret = ttm_bo_device_init(&hibmc->ttm.bdev,
>>>> +                                hibmc->ttm.bo_global_ref.ref.object,
>>>> +                                &hibmc_bo_driver,
>>>> +                                dev->anon_inode->i_mapping,
>>>> +                                DRM_FILE_PAGE_OFFSET,
>>>> +                                true);
>>>> +       if (ret) {
>>>
>>>
>>> Call hibmc_ttm_global_release here?
>>
>>
>> agreed, thanks for pointing it out.
>>
>>>
>>>> +               DRM_ERROR("Error initialising bo driver; %d\n", ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
>>>> +                            hibmc->fb_size >> PAGE_SHIFT);
>>>> +       if (ret) {
>>>
>>>
>>> Clean up here as well?
>>
>>
>> ditto
>>
>>
>>>
>>>> +               DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       hibmc->mm_inited = true;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       if (!hibmc->mm_inited)
>>>> +               return;
>>>> +
>>>> +       ttm_bo_device_release(&hibmc->ttm.bdev);
>>>> +       hibmc_ttm_global_release(hibmc);
>>>> +       hibmc->mm_inited = false;
>>>> +}
>>>> +
>>>> +int hibmc_bo_create(struct drm_device *dev, int size, int align,
>>>> +                   u32 flags, struct hibmc_bo **phibmcbo)
>>>> +{
>>>> +       struct hibmc_drm_device *hibmc = dev->dev_private;
>>>> +       struct hibmc_bo *hibmcbo;
>>>> +       size_t acc_size;
>>>> +       int ret;
>>>> +
>>>> +       hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
>>>> +       if (!hibmcbo)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
>>>> +       if (ret) {
>>>> +               kfree(hibmcbo);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       hibmcbo->bo.bdev = &hibmc->ttm.bdev;
>>>> +
>>>> +       hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM |
>>>> TTM_PL_FLAG_SYSTEM);
>>>> +
>>>> +       acc_size = ttm_bo_dma_acc_size(&hibmc->ttm.bdev, size,
>>>> +                                      sizeof(struct hibmc_bo));
>>>> +
>>>> +       ret = ttm_bo_init(&hibmc->ttm.bdev, &hibmcbo->bo, size,
>>>> +                         ttm_bo_type_device, &hibmcbo->placement,
>>>> +                         align >> PAGE_SHIFT, false, NULL, acc_size,
>>>> +                         NULL, NULL, hibmc_bo_ttm_destroy);
>>>> +       if (ret)
>>>
>>>
>>> Missing hibmcbo clean up here
>>
>>
>> i looked at all other ttm drivers and all of them return directly when
>> ttm_bo_init
>> failed, however, i think it is better to clean up here, should i call
>> hibmc_bo_unref(&hibmc_bo) here ?
>>
>
> Yeah, that should work (might want to test it, though ;)
>
>
>>>
>>>> +               return ret;
>>>> +
>>>> +       *phibmcbo = hibmcbo;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static inline u64 hibmc_bo_gpu_offset(struct hibmc_bo *bo)
>>>> +{
>>>> +       return bo->bo.offset;
>>>> +}
>>>
>>>
>>> I don't think this function provides any value
>>
>>
>> do you nean i use bo->bo.offset instead of calling hibmc_bo_gpu_offset()?
>>
>
> yes
>
>>>
>>>> +
>>>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
>>>> +{
>>>> +       int i, ret;
>>>> +
>>>> +       if (bo->pin_count) {
>>>> +               bo->pin_count++;
>>>> +               if (gpu_addr)
>>>> +                       *gpu_addr = hibmc_bo_gpu_offset(bo);
>>>
>>>
>>> Are you missing a return here?
>>
>>
>> Thanks for pointing it out!
>>
>>
>>>
>>>> +       }
>>>> +
>>>> +       hibmc_ttm_placement(bo, pl_flag);
>>>> +       for (i = 0; i < bo->placement.num_placement; i++)
>>>> +               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>>>> +       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       bo->pin_count = 1;
>>>> +       if (gpu_addr)
>>>> +               *gpu_addr = hibmc_bo_gpu_offset(bo);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_bo_push_sysram(struct hibmc_bo *bo)
>>>> +{
>>>> +       int i, ret;
>>>> +
>>>> +       if (!bo->pin_count) {
>>>> +               DRM_ERROR("unpin bad %p\n", bo);
>>>> +               return 0;
>>>> +       }
>>>> +       bo->pin_count--;
>>>> +       if (bo->pin_count)
>>>> +               return 0;
>>>> +
>>>> +       if (bo->kmap.virtual)
>>>
>>>
>>> ttm_bo_kunmap already does this check so you don't have to
>>
>>
>> agreed. will remove this condition.
>>
>>>
>>>> +               ttm_bo_kunmap(&bo->kmap);
>>>> +
>>>> +       hibmc_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
>>>> +       for (i = 0; i < bo->placement.num_placement ; i++)
>>>> +               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>>>> +
>>>> +       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>>>> +       if (ret) {
>>>> +               DRM_ERROR("pushing to VRAM failed\n");
>>>
>>>
>>> Print ret
>>
>>
>> ok, thanks.
>>
>>
>>>
>>>> +               return ret;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
>>>> +{
>>>> +       struct drm_file *file_priv;
>>>> +       struct hibmc_drm_device *hibmc;
>>>> +
>>>> +       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
>>>> +               return -EINVAL;
>>>> +
>>>> +       file_priv = filp->private_data;
>>>> +       hibmc = file_priv->minor->dev->dev_private;
>>>> +       return ttm_bo_mmap(filp, vma, &hibmc->ttm.bdev);
>>>> +}
>>>> +
>>>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>>>> +                    struct drm_gem_object **obj)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo;
>>>> +       int ret;
>>>> +
>>>> +       *obj = NULL;
>>>> +
>>>> +       size = PAGE_ALIGN(size);
>>>> +       if (size == 0)
>>>
>>>
>>> Print error
>>
>>
>> ditto
>>
>>>
>>>> +               return -EINVAL;
>>>> +
>>>> +       ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
>>>> +       if (ret) {
>>>> +               if (ret != -ERESTARTSYS)
>>>> +                       DRM_ERROR("failed to allocate GEM object\n");
>>>
>>>
>>> Print ret
>>
>>
>> ditto
>>
>>>
>>>> +               return ret;
>>>> +       }
>>>> +       *obj = &hibmcbo->gem;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>>>> +                     struct drm_mode_create_dumb *args)
>>>> +{
>>>> +       struct drm_gem_object *gobj;
>>>> +       u32 handle;
>>>> +       int ret;
>>>> +
>>>> +       args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 16);
>>>
>>>
>>> What's up with the bpp + 7 here? Perhaps you're looking for DIV_ROUND_UP?
>>
>>
>> Yes, that sounds sane.
>>
>
> sane is what i usually aim for :)
>
> Sean
>
>
>>>
>>>
>>>> +       args->size = args->pitch * args->height;
>>>> +
>>>> +       ret = hibmc_gem_create(dev, args->size, false,
>>>> +                              &gobj);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       ret = drm_gem_handle_create(file, gobj, &handle);
>>>> +       drm_gem_object_unreference_unlocked(gobj);
>>>> +       if (ret)
>>>
>>>
>>> Print error here
>>
>>
>> agreed.
>>
>>
>>>
>>>> +               return ret;
>>>> +
>>>> +       args->handle = handle;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void hibmc_bo_unref(struct hibmc_bo **bo)
>>>> +{
>>>> +       struct ttm_buffer_object *tbo;
>>>> +
>>>> +       if ((*bo) == NULL)
>>>> +               return;
>>>> +
>>>> +       tbo = &((*bo)->bo);
>>>> +       ttm_bo_unref(&tbo);
>>>> +       *bo = NULL;
>>>> +}
>>>> +
>>>> +void hibmc_gem_free_object(struct drm_gem_object *obj)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
>>>> +
>>>> +       hibmc_bo_unref(&hibmcbo);
>>>> +}
>>>> +
>>>> +static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
>>>> +{
>>>> +       return drm_vma_node_offset_addr(&bo->bo.vma_node);
>>>> +}
>>>> +
>>>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device
>>>> *dev,
>>>> +                          u32 handle, u64 *offset)
>>>> +{
>>>> +       struct drm_gem_object *obj;
>>>> +       struct hibmc_bo *bo;
>>>> +
>>>> +       obj = drm_gem_object_lookup(file, handle);
>>>> +       if (!obj)
>>>> +               return -ENOENT;
>>>> +
>>>> +       bo = gem_to_hibmc_bo(obj);
>>>> +       *offset = hibmc_bo_mmap_offset(bo);
>>>> +
>>>> +       drm_gem_object_unreference_unlocked(obj);
>>>> +       return 0;
>>>> +}
>>
>>
>> Regards,
>> Rongrong.
>>
>>>> --
>>>> 1.9.1
>>>>
>>>>
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel at lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>> _______________________________________________
>>> linuxarm mailing list
>>> linuxarm at huawei.com
>>> http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
>>>
>>> .
>>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> .
>


-- 
Regards, Rongrong

WARNING: multiple messages have this Message-ID (diff)
From: Rongrong Zou <zourongrong@huawei.com>
To: Sean Paul <seanpaul@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
	Archit <architt@codeaurora.org>,
	lijianhua@huawei.com, Daniel Vetter <daniel@ffwll.ch>,
	Tomeu Vizoso <tomeu.vizoso@collabora.com>,
	Jonathan Corbet <corbet@lwn.net>, Dave Airlie <airlied@linux.ie>,
	catalin.marinas@arm.com, Emil Velikov <emil.l.velikov@gmail.com>,
	linuxarm@huawei.com, dri-devel <dri-devel@lists.freedesktop.org>,
	Xinliang Liu <xinliang.liu@linaro.org>,
	james.xiong@huawei.com, shenhui@huawei.com,
	Rongrong Zou <zourongrong@gmail.com>,
	Daniel Stone <daniel@fooishbar.org>,
	Will Deacon <will.deacon@arm.com>,
	Linux ARM Kernel <linux-arm-kernel@lists.infradead.org>,
	Benjamin Gaignard <benjamin.gaignard@linaro.org>
Subject: Re: [PATCH v6 2/9] drm/hisilicon/hibmc: Add video memory management
Date: Fri, 11 Nov 2016 21:57:56 +0800	[thread overview]
Message-ID: <5825CE64.5080708@huawei.com> (raw)
In-Reply-To: <CAOw6vbJFitYby+cNezQvdtwJqNkSjhX2=S0QwUrL40gmv-Kozg@mail.gmail.com>

在 2016/11/11 21:25, Sean Paul 写道:
> On Fri, Nov 11, 2016 at 6:16 AM, Rongrong Zou <zourongrong@huawei.com> wrote:
>> 在 2016/11/11 1:35, Sean Paul 写道:
>>>
>>> On Fri, Oct 28, 2016 at 3:27 AM, Rongrong Zou <zourongrong@gmail.com>
>>> wrote:
>>>>
>>>> Hibmc have 32m video memory which can be accessed through PCIe by host,
>>>> we use ttm to manage these memory.
>>>>
>>>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>>>> ---
>>>>    drivers/gpu/drm/hisilicon/hibmc/Kconfig         |   1 +
>>>>    drivers/gpu/drm/hisilicon/hibmc/Makefile        |   2 +-
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |  12 +
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |  46 +++
>>>>    drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c     | 490
>>>> ++++++++++++++++++++++++
>>>>    5 files changed, 550 insertions(+), 1 deletion(-)
>>>>    create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>>
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> index a9af90d..bcb8c18 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>> @@ -1,6 +1,7 @@
>>>>    config DRM_HISI_HIBMC
>>>>           tristate "DRM Support for Hisilicon Hibmc"
>>>>           depends on DRM && PCI
>>>> +       select DRM_TTM
>>>>
>>>>           help
>>>>             Choose this option if you have a Hisilicon Hibmc soc chipset.
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> index 97cf4a0..d5c40b8 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>> @@ -1,5 +1,5 @@
>>>>    ccflags-y := -Iinclude/drm
>>>> -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>>>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o hibmc_ttm.o
>>>>
>>>>    obj-$(CONFIG_DRM_HISI_HIBMC)   +=hibmc-drm.o
>>>>    #obj-y += hibmc-drm.o
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> index 4669d42..81f4301 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>> @@ -31,6 +31,7 @@
>>>>    #ifdef CONFIG_COMPAT
>>>>           .compat_ioctl   = drm_compat_ioctl,
>>>>    #endif
>>>> +       .mmap           = hibmc_mmap,
>>>>           .poll           = drm_poll,
>>>>           .read           = drm_read,
>>>>           .llseek         = no_llseek,
>>>> @@ -46,6 +47,8 @@ static void hibmc_disable_vblank(struct drm_device
>>>> *dev, unsigned int pipe)
>>>>    }
>>>>
>>>>    static struct drm_driver hibmc_driver = {
>>>> +       .driver_features        = DRIVER_GEM,
>>>> +
>>>
>>>
>>> nit: extra space
>>>
>>>>           .fops                   = &hibmc_fops,
>>>>           .name                   = "hibmc",
>>>>           .date                   = "20160828",
>>>> @@ -55,6 +58,10 @@ static void hibmc_disable_vblank(struct drm_device
>>>> *dev, unsigned int pipe)
>>>>           .get_vblank_counter     = drm_vblank_no_hw_counter,
>>>>           .enable_vblank          = hibmc_enable_vblank,
>>>>           .disable_vblank         = hibmc_disable_vblank,
>>>> +       .gem_free_object_unlocked = hibmc_gem_free_object,
>>>> +       .dumb_create            = hibmc_dumb_create,
>>>> +       .dumb_map_offset        = hibmc_dumb_mmap_offset,
>>>> +       .dumb_destroy           = drm_gem_dumb_destroy,
>>>>    };
>>>>
>>>>    static int hibmc_pm_suspend(struct device *dev)
>>>> @@ -163,6 +170,7 @@ static int hibmc_unload(struct drm_device *dev)
>>>>    {
>>>>           struct hibmc_drm_device *hidev = dev->dev_private;
>>>>
>>>> +       hibmc_mm_fini(hidev);
>>>>           hibmc_hw_fini(hidev);
>>>>           dev->dev_private = NULL;
>>>>           return 0;
>>>> @@ -183,6 +191,10 @@ static int hibmc_load(struct drm_device *dev,
>>>> unsigned long flags)
>>>>           if (ret)
>>>>                   goto err;
>>>>
>>>> +       ret = hibmc_mm_init(hidev);
>>>> +       if (ret)
>>>> +               goto err;
>>>> +
>>>>           return 0;
>>>>
>>>>    err:
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> index 0037341..db8d80e 100644
>>>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>> @@ -20,6 +20,8 @@
>>>>    #define HIBMC_DRM_DRV_H
>>>>
>>>>    #include <drm/drmP.h>
>>>> +#include <drm/ttm/ttm_bo_driver.h>
>>>> +#include <drm/drm_gem.h>
>>>
>>>
>>> nit: alphabetize
>>
>>
>> will fix it, thanks.
>>
>>>
>>>>
>>>>    struct hibmc_drm_device {
>>>>           /* hw */
>>>> @@ -30,6 +32,50 @@ struct hibmc_drm_device {
>>>>
>>>>           /* drm */
>>>>           struct drm_device  *dev;
>>>> +
>>>> +       /* ttm */
>>>> +       struct {
>>>> +               struct drm_global_reference mem_global_ref;
>>>> +               struct ttm_bo_global_ref bo_global_ref;
>>>> +               struct ttm_bo_device bdev;
>>>> +               bool initialized;
>>>> +       } ttm;
>>>
>>>
>>> I don't think you gain anything other than keystrokes from the substruct
>>
>>
>> I'm sorry i didn't catch you, i looked at the all drivers used ttm such
>> as ast/bochs/cirrus/mgag200/qxl/virtio_gpu, they all embedded the ttm
>> substruct
>> into the driver-private struct.
>>
>> so do you mean
>> struct hibmc_drm_device {
>>          /* hw */
>>          void __iomem   *mmio;
>>          void __iomem   *fb_map;
>>          unsigned long  fb_base;
>>          unsigned long  fb_size;
>>
>>          /* drm */
>>          struct drm_device  *dev;
>>          struct drm_plane plane;
>>          struct drm_crtc crtc;
>>          struct drm_encoder encoder;
>>          struct drm_connector connector;
>>          bool mode_config_initialized;
>>
>>          /* ttm */
>>          struct drm_global_reference mem_global_ref;
>>          struct ttm_bo_global_ref bo_global_ref;
>>          struct ttm_bo_device bdev;
>>          bool initialized;
>>          ...
>>          };
>> ?
>
> Yeah, that's what I was thinking
>
>>
>>>
>>>> +
>>>> +       bool mm_inited;
>>>>    };
>>>>
>>>> +struct hibmc_bo {
>>>> +       struct ttm_buffer_object bo;
>>>> +       struct ttm_placement placement;
>>>> +       struct ttm_bo_kmap_obj kmap;
>>>> +       struct drm_gem_object gem;
>>>> +       struct ttm_place placements[3];
>>>> +       int pin_count;
>>>> +};
>>>> +
>>>> +static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
>>>> +{
>>>> +       return container_of(bo, struct hibmc_bo, bo);
>>>> +}
>>>> +
>>>> +static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object
>>>> *gem)
>>>> +{
>>>> +       return container_of(gem, struct hibmc_bo, gem);
>>>> +}
>>>> +
>>>> +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
>>>
>>>
>>> Hide this in ttm.c
>>
>>
>> ok, will do that.
>> thanks for pointing it out.
>>
>>
>>>
>>>> +
>>>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>>>> +                    struct drm_gem_object **obj);
>>>> +
>>>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc);
>>>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc);
>>>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
>>>> +void hibmc_gem_free_object(struct drm_gem_object *obj);
>>>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>>>> +                     struct drm_mode_create_dumb *args);
>>>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device
>>>> *dev,
>>>> +                          u32 handle, u64 *offset);
>>>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
>>>> +
>>>>    #endif
>>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> new file mode 100644
>>>> index 0000000..0802ebd
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>>>> @@ -0,0 +1,490 @@
>>>> +/* Hisilicon Hibmc SoC drm driver
>>>> + *
>>>> + * Based on the bochs drm driver.
>>>> + *
>>>> + * Copyright (c) 2016 Huawei Limited.
>>>> + *
>>>> + * Author:
>>>> + *     Rongrong Zou <zourongrong@huawei.com>
>>>> + *     Rongrong Zou <zourongrong@gmail.com>
>>>> + *     Jianhua Li <lijianhua@huawei.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License as published by
>>>> + * the Free Software Foundation; either version 2 of the License, or
>>>> + * (at your option) any later version.
>>>> + *
>>>> + */
>>>> +
>>>> +#include "hibmc_drm_drv.h"
>>>> +#include <ttm/ttm_page_alloc.h>
>>>> +#include <drm/drm_crtc_helper.h>
>>>> +#include <drm/drm_atomic_helper.h>
>>>> +
>>>> +static inline struct hibmc_drm_device *
>>>> +hibmc_bdev(struct ttm_bo_device *bd)
>>>> +{
>>>> +       return container_of(bd, struct hibmc_drm_device, ttm.bdev);
>>>> +}
>>>> +
>>>> +static int
>>>> +hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
>>>> +{
>>>> +       return ttm_mem_global_init(ref->object);
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
>>>> +{
>>>> +       ttm_mem_global_release(ref->object);
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_global_init(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       struct drm_global_reference *global_ref;
>>>> +       int r;
>>>
>>>
>>> nit: try not to use one character variable names unless it's for the
>>> purpose of a loop (ie: i,j). You also use ret elsewhere in the driver,
>>> so it'd be nice to remain consistent
>>
>>
>> the whole file is delivered from bochs ttm, i didn't modify anything except
>> some checkpatch warnings and the 'hibmc_' prefix. Unfortunately, some
>> problems were delivered too.
>
> Yeah, seems like it. Perhaps you can post patches to fix these issues
> in the other drivers too :)

i will do after the this one get merged :)

>
>>
>>>
>>>> +
>>>> +       global_ref = &hibmc->ttm.mem_global_ref;
>>>
>>>
>>> I think using the global_ref local obfuscates what you're doing here.
>>> It saves you 6 characters while typing, but adds a layer of
>>> indirection for all future readers.
>>>
>>>> +       global_ref->global_type = DRM_GLOBAL_TTM_MEM;
>>>> +       global_ref->size = sizeof(struct ttm_mem_global);
>>>> +       global_ref->init = &hibmc_ttm_mem_global_init;
>>>> +       global_ref->release = &hibmc_ttm_mem_global_release;
>>>> +       r = drm_global_item_ref(global_ref);
>>>> +       if (r != 0) {
>>>
>>>
>>> nit: if (r)
>>
>>
>> will fix it,
>> thanks.
>> BTW, i wonder why checkpatch.pl didn't report it.
>>
>>
>>>
>>>> +               DRM_ERROR("Failed setting up TTM memory accounting
>>>> subsystem.\n"
>>>> +                        );
>>>
>>>
>>> Breaking up the line for one character is probably not worthwhile, and
>>> you should really print the error. How about:
>>>
>>> DRM_ERROR("Could not get ref on ttm global ret=%d.\n", ret);
>>
>>
>> i like your solution, thanks.
>>
>>
>>>
>>>
>>>> +               return r;
>>>> +       }
>>>> +
>>>> +       hibmc->ttm.bo_global_ref.mem_glob =
>>>> +               hibmc->ttm.mem_global_ref.object;
>>>> +       global_ref = &hibmc->ttm.bo_global_ref.ref;
>>>> +       global_ref->global_type = DRM_GLOBAL_TTM_BO;
>>>> +       global_ref->size = sizeof(struct ttm_bo_global);
>>>> +       global_ref->init = &ttm_bo_global_init;
>>>> +       global_ref->release = &ttm_bo_global_release;
>>>> +       r = drm_global_item_ref(global_ref);
>>>> +       if (r != 0) {
>>>> +               DRM_ERROR("Failed setting up TTM BO subsystem.\n");
>>>> +               drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>>>> +               return r;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_ttm_global_release(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       if (!hibmc->ttm.mem_global_ref.release)
>>>
>>>
>>> Are you actually hitting this condition? This seems like it's papering
>>> over something else.
>>
>>
>> it was also delivered from others, i looked at the xxx_ttm_global_init
>> function, 'mem_global_ref.release' is assigned unconditionally, so i
>> think this condition never be hit, it may be hit when release twice,
>> but this won't take place in my driver.
>>
>
> Yeah, that's what I was hoping for. So perhaps we can remove this?

yes, we can.

Regards,
Rongrong.

>
>>>
>>>> +               return;
>>>> +
>>>> +       drm_global_item_unref(&hibmc->ttm.bo_global_ref.ref);
>>>> +       drm_global_item_unref(&hibmc->ttm.mem_global_ref);
>>>> +       hibmc->ttm.mem_global_ref.release = NULL;
>>>> +}
>>>> +
>>>> +static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
>>>> +{
>>>> +       struct hibmc_bo *bo;
>>>> +
>>>> +       bo = container_of(tbo, struct hibmc_bo, bo);
>>>
>>>
>>> nit: No need to split this into a separate line.
>>
>>
>> agreed, thanks.
>>
>>>
>>>> +
>>>> +       drm_gem_object_release(&bo->gem);
>>>> +       kfree(bo);
>>>> +}
>>>> +
>>>> +static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
>>>> +{
>>>> +       if (bo->destroy == &hibmc_bo_ttm_destroy)
>>>> +               return true;
>>>> +       return false;
>>>
>>>
>>> return bo->destroy == &hibmc_bo_ttm_destroy;
>>
>>
>> looks better to me.
>>
>>
>>>
>>>> +}
>>>> +
>>>> +static int
>>>> +hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
>>>> +                      struct ttm_mem_type_manager *man)
>>>> +{
>>>> +       switch (type) {
>>>> +       case TTM_PL_SYSTEM:
>>>> +               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
>>>> +               man->available_caching = TTM_PL_MASK_CACHING;
>>>> +               man->default_caching = TTM_PL_FLAG_CACHED;
>>>> +               break;
>>>> +       case TTM_PL_VRAM:
>>>> +               man->func = &ttm_bo_manager_func;
>>>> +               man->flags = TTM_MEMTYPE_FLAG_FIXED |
>>>> +                       TTM_MEMTYPE_FLAG_MAPPABLE;
>>>> +               man->available_caching = TTM_PL_FLAG_UNCACHED |
>>>> +                       TTM_PL_FLAG_WC;
>>>> +               man->default_caching = TTM_PL_FLAG_WC;
>>>> +               break;
>>>> +       default:
>>>> +               DRM_ERROR("Unsupported memory type %u\n", type);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
>>>> +{
>>>> +       u32 c = 0;
>>>
>>>
>>> Can you please use a more descriptive name than 'c'?
>>
>>
>> ok, will do that.
>>
>>>
>>>> +       u32 i;
>>>> +
>>>> +       bo->placement.placement = bo->placements;
>>>> +       bo->placement.busy_placement = bo->placements;
>>>> +       if (domain & TTM_PL_FLAG_VRAM)
>>>> +               bo->placements[c++].flags = TTM_PL_FLAG_WC |
>>>> +               TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
>>>
>>>
>>> nit: you're alignment is off here and below
>>
>>
>> is it correct?
>>
>>          if (domain & TTM_PL_FLAG_VRAM)
>>                  bo->placements[c++].flags = TTM_PL_FLAG_WC |
>>                          TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
>>          if (domain & TTM_PL_FLAG_SYSTEM)
>>                  bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>                          TTM_PL_FLAG_SYSTEM;
>>          if (!c)
>>                  bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>                          TTM_PL_FLAG_SYSTEM;
>>
>
> Pretty much anything other than lining them up one under the other is better
>
>>>
>>>> +       if (domain & TTM_PL_FLAG_SYSTEM)
>>>> +               bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>>> +               TTM_PL_FLAG_SYSTEM;
>>>> +       if (!c)
>>>> +               bo->placements[c++].flags = TTM_PL_MASK_CACHING |
>>>> +               TTM_PL_FLAG_SYSTEM;
>>>> +
>>>> +       bo->placement.num_placement = c;
>>>> +       bo->placement.num_busy_placement = c;
>>>> +       for (i = 0; i < c; ++i) {
>>>
>>>
>>> nit: we tend towards post-increment in kernel
>>
>>
>> agreed, thanks.
>>
>>
>>>
>>>> +               bo->placements[i].fpfn = 0;
>>>> +               bo->placements[i].lpfn = 0;
>>>> +       }
>>>> +}
>>>> +
>>>> +static void
>>>> +hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement
>>>> *pl)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>>>> +
>>>> +       if (!hibmc_ttm_bo_is_hibmc_bo(bo))
>>>> +               return;
>>>> +
>>>> +       hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
>>>> +       *pl = hibmcbo->placement;
>>>> +}
>>>> +
>>>> +static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
>>>> +                                 struct file *filp)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = hibmc_bo(bo);
>>>> +
>>>> +       return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
>>>> +                                         filp->private_data);
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
>>>> +                                   struct ttm_mem_reg *mem)
>>>> +{
>>>> +       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
>>>> +       struct hibmc_drm_device *hibmc = hibmc_bdev(bdev);
>>>> +
>>>> +       mem->bus.addr = NULL;
>>>> +       mem->bus.offset = 0;
>>>> +       mem->bus.size = mem->num_pages << PAGE_SHIFT;
>>>> +       mem->bus.base = 0;
>>>> +       mem->bus.is_iomem = false;
>>>> +       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
>>>> +               return -EINVAL;
>>>> +       switch (mem->mem_type) {
>>>> +       case TTM_PL_SYSTEM:
>>>> +               /* system memory */
>>>> +               return 0;
>>>> +       case TTM_PL_VRAM:
>>>> +               mem->bus.offset = mem->start << PAGE_SHIFT;
>>>> +               mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
>>>> +               mem->bus.is_iomem = true;
>>>> +               break;
>>>> +       default:
>>>> +               return -EINVAL;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void hibmc_ttm_io_mem_free(struct ttm_bo_device *bdev,
>>>> +                                 struct ttm_mem_reg *mem)
>>>> +{
>>>> +}
>>>
>>>
>>> No need to stub this, the caller does a NULL-check before invoking
>>
>>
>> will delete it, thanks.
>>
>>>
>>>> +
>>>> +static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
>>>> +{
>>>> +       ttm_tt_fini(tt);
>>>> +       kfree(tt);
>>>> +}
>>>> +
>>>> +static struct ttm_backend_func hibmc_tt_backend_func = {
>>>> +       .destroy = &hibmc_ttm_backend_destroy,
>>>> +};
>>>> +
>>>> +static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
>>>> +                                         unsigned long size,
>>>> +                                         u32 page_flags,
>>>> +                                         struct page *dummy_read_page)
>>>> +{
>>>> +       struct ttm_tt *tt;
>>>> +
>>>> +       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
>>>> +       if (!tt)
>>>
>>>
>>> Print error
>>
>>
>> ok, will do that, thanks.
>>
>>>
>>>> +               return NULL;
>>>> +       tt->func = &hibmc_tt_backend_func;
>>>> +       if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
>>>
>>>
>>> Here too?
>>
>>
>> ditto
>>
>>
>>>
>>>> +               kfree(tt);
>>>> +               return NULL;
>>>> +       }
>>>> +       return tt;
>>>> +}
>>>> +
>>>> +static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
>>>> +{
>>>> +       return ttm_pool_populate(ttm);
>>>> +}
>>>> +
>>>> +static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
>>>> +{
>>>> +       ttm_pool_unpopulate(ttm);
>>>> +}
>>>> +
>>>> +struct ttm_bo_driver hibmc_bo_driver = {
>>>> +       .ttm_tt_create          = hibmc_ttm_tt_create,
>>>> +       .ttm_tt_populate        = hibmc_ttm_tt_populate,
>>>> +       .ttm_tt_unpopulate      = hibmc_ttm_tt_unpopulate,
>>>> +       .init_mem_type          = hibmc_bo_init_mem_type,
>>>> +       .evict_flags            = hibmc_bo_evict_flags,
>>>> +       .move                   = NULL,
>>>> +       .verify_access          = hibmc_bo_verify_access,
>>>> +       .io_mem_reserve         = &hibmc_ttm_io_mem_reserve,
>>>> +       .io_mem_free            = &hibmc_ttm_io_mem_free,
>>>> +       .lru_tail               = &ttm_bo_default_lru_tail,
>>>> +       .swap_lru_tail          = &ttm_bo_default_swap_lru_tail,
>>>> +};
>>>> +
>>>> +int hibmc_mm_init(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       int ret;
>>>> +       struct drm_device *dev = hibmc->dev;
>>>> +       struct ttm_bo_device *bdev = &hibmc->ttm.bdev;
>>>> +
>>>> +       ret = hibmc_ttm_global_init(hibmc);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       ret = ttm_bo_device_init(&hibmc->ttm.bdev,
>>>> +                                hibmc->ttm.bo_global_ref.ref.object,
>>>> +                                &hibmc_bo_driver,
>>>> +                                dev->anon_inode->i_mapping,
>>>> +                                DRM_FILE_PAGE_OFFSET,
>>>> +                                true);
>>>> +       if (ret) {
>>>
>>>
>>> Call hibmc_ttm_global_release here?
>>
>>
>> agreed, thanks for pointing it out.
>>
>>>
>>>> +               DRM_ERROR("Error initialising bo driver; %d\n", ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
>>>> +                            hibmc->fb_size >> PAGE_SHIFT);
>>>> +       if (ret) {
>>>
>>>
>>> Clean up here as well?
>>
>>
>> ditto
>>
>>
>>>
>>>> +               DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       hibmc->mm_inited = true;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void hibmc_mm_fini(struct hibmc_drm_device *hibmc)
>>>> +{
>>>> +       if (!hibmc->mm_inited)
>>>> +               return;
>>>> +
>>>> +       ttm_bo_device_release(&hibmc->ttm.bdev);
>>>> +       hibmc_ttm_global_release(hibmc);
>>>> +       hibmc->mm_inited = false;
>>>> +}
>>>> +
>>>> +int hibmc_bo_create(struct drm_device *dev, int size, int align,
>>>> +                   u32 flags, struct hibmc_bo **phibmcbo)
>>>> +{
>>>> +       struct hibmc_drm_device *hibmc = dev->dev_private;
>>>> +       struct hibmc_bo *hibmcbo;
>>>> +       size_t acc_size;
>>>> +       int ret;
>>>> +
>>>> +       hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
>>>> +       if (!hibmcbo)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
>>>> +       if (ret) {
>>>> +               kfree(hibmcbo);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       hibmcbo->bo.bdev = &hibmc->ttm.bdev;
>>>> +
>>>> +       hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM |
>>>> TTM_PL_FLAG_SYSTEM);
>>>> +
>>>> +       acc_size = ttm_bo_dma_acc_size(&hibmc->ttm.bdev, size,
>>>> +                                      sizeof(struct hibmc_bo));
>>>> +
>>>> +       ret = ttm_bo_init(&hibmc->ttm.bdev, &hibmcbo->bo, size,
>>>> +                         ttm_bo_type_device, &hibmcbo->placement,
>>>> +                         align >> PAGE_SHIFT, false, NULL, acc_size,
>>>> +                         NULL, NULL, hibmc_bo_ttm_destroy);
>>>> +       if (ret)
>>>
>>>
>>> Missing hibmcbo clean up here
>>
>>
>> i looked at all other ttm drivers and all of them return directly when
>> ttm_bo_init
>> failed, however, i think it is better to clean up here, should i call
>> hibmc_bo_unref(&hibmc_bo) here ?
>>
>
> Yeah, that should work (might want to test it, though ;)
>
>
>>>
>>>> +               return ret;
>>>> +
>>>> +       *phibmcbo = hibmcbo;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static inline u64 hibmc_bo_gpu_offset(struct hibmc_bo *bo)
>>>> +{
>>>> +       return bo->bo.offset;
>>>> +}
>>>
>>>
>>> I don't think this function provides any value
>>
>>
>> do you nean i use bo->bo.offset instead of calling hibmc_bo_gpu_offset()?
>>
>
> yes
>
>>>
>>>> +
>>>> +int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
>>>> +{
>>>> +       int i, ret;
>>>> +
>>>> +       if (bo->pin_count) {
>>>> +               bo->pin_count++;
>>>> +               if (gpu_addr)
>>>> +                       *gpu_addr = hibmc_bo_gpu_offset(bo);
>>>
>>>
>>> Are you missing a return here?
>>
>>
>> Thanks for pointing it out!
>>
>>
>>>
>>>> +       }
>>>> +
>>>> +       hibmc_ttm_placement(bo, pl_flag);
>>>> +       for (i = 0; i < bo->placement.num_placement; i++)
>>>> +               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>>>> +       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       bo->pin_count = 1;
>>>> +       if (gpu_addr)
>>>> +               *gpu_addr = hibmc_bo_gpu_offset(bo);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_bo_push_sysram(struct hibmc_bo *bo)
>>>> +{
>>>> +       int i, ret;
>>>> +
>>>> +       if (!bo->pin_count) {
>>>> +               DRM_ERROR("unpin bad %p\n", bo);
>>>> +               return 0;
>>>> +       }
>>>> +       bo->pin_count--;
>>>> +       if (bo->pin_count)
>>>> +               return 0;
>>>> +
>>>> +       if (bo->kmap.virtual)
>>>
>>>
>>> ttm_bo_kunmap already does this check so you don't have to
>>
>>
>> agreed. will remove this condition.
>>
>>>
>>>> +               ttm_bo_kunmap(&bo->kmap);
>>>> +
>>>> +       hibmc_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
>>>> +       for (i = 0; i < bo->placement.num_placement ; i++)
>>>> +               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
>>>> +
>>>> +       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
>>>> +       if (ret) {
>>>> +               DRM_ERROR("pushing to VRAM failed\n");
>>>
>>>
>>> Print ret
>>
>>
>> ok, thanks.
>>
>>
>>>
>>>> +               return ret;
>>>> +       }
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
>>>> +{
>>>> +       struct drm_file *file_priv;
>>>> +       struct hibmc_drm_device *hibmc;
>>>> +
>>>> +       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
>>>> +               return -EINVAL;
>>>> +
>>>> +       file_priv = filp->private_data;
>>>> +       hibmc = file_priv->minor->dev->dev_private;
>>>> +       return ttm_bo_mmap(filp, vma, &hibmc->ttm.bdev);
>>>> +}
>>>> +
>>>> +int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
>>>> +                    struct drm_gem_object **obj)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo;
>>>> +       int ret;
>>>> +
>>>> +       *obj = NULL;
>>>> +
>>>> +       size = PAGE_ALIGN(size);
>>>> +       if (size == 0)
>>>
>>>
>>> Print error
>>
>>
>> ditto
>>
>>>
>>>> +               return -EINVAL;
>>>> +
>>>> +       ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
>>>> +       if (ret) {
>>>> +               if (ret != -ERESTARTSYS)
>>>> +                       DRM_ERROR("failed to allocate GEM object\n");
>>>
>>>
>>> Print ret
>>
>>
>> ditto
>>
>>>
>>>> +               return ret;
>>>> +       }
>>>> +       *obj = &hibmcbo->gem;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
>>>> +                     struct drm_mode_create_dumb *args)
>>>> +{
>>>> +       struct drm_gem_object *gobj;
>>>> +       u32 handle;
>>>> +       int ret;
>>>> +
>>>> +       args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 16);
>>>
>>>
>>> What's up with the bpp + 7 here? Perhaps you're looking for DIV_ROUND_UP?
>>
>>
>> Yes, that sounds sane.
>>
>
> sane is what i usually aim for :)
>
> Sean
>
>
>>>
>>>
>>>> +       args->size = args->pitch * args->height;
>>>> +
>>>> +       ret = hibmc_gem_create(dev, args->size, false,
>>>> +                              &gobj);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       ret = drm_gem_handle_create(file, gobj, &handle);
>>>> +       drm_gem_object_unreference_unlocked(gobj);
>>>> +       if (ret)
>>>
>>>
>>> Print error here
>>
>>
>> agreed.
>>
>>
>>>
>>>> +               return ret;
>>>> +
>>>> +       args->handle = handle;
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void hibmc_bo_unref(struct hibmc_bo **bo)
>>>> +{
>>>> +       struct ttm_buffer_object *tbo;
>>>> +
>>>> +       if ((*bo) == NULL)
>>>> +               return;
>>>> +
>>>> +       tbo = &((*bo)->bo);
>>>> +       ttm_bo_unref(&tbo);
>>>> +       *bo = NULL;
>>>> +}
>>>> +
>>>> +void hibmc_gem_free_object(struct drm_gem_object *obj)
>>>> +{
>>>> +       struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
>>>> +
>>>> +       hibmc_bo_unref(&hibmcbo);
>>>> +}
>>>> +
>>>> +static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
>>>> +{
>>>> +       return drm_vma_node_offset_addr(&bo->bo.vma_node);
>>>> +}
>>>> +
>>>> +int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device
>>>> *dev,
>>>> +                          u32 handle, u64 *offset)
>>>> +{
>>>> +       struct drm_gem_object *obj;
>>>> +       struct hibmc_bo *bo;
>>>> +
>>>> +       obj = drm_gem_object_lookup(file, handle);
>>>> +       if (!obj)
>>>> +               return -ENOENT;
>>>> +
>>>> +       bo = gem_to_hibmc_bo(obj);
>>>> +       *offset = hibmc_bo_mmap_offset(bo);
>>>> +
>>>> +       drm_gem_object_unreference_unlocked(obj);
>>>> +       return 0;
>>>> +}
>>
>>
>> Regards,
>> Rongrong.
>>
>>>> --
>>>> 1.9.1
>>>>
>>>>
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel@lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>> _______________________________________________
>>> linuxarm mailing list
>>> linuxarm@huawei.com
>>> http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
>>>
>>> .
>>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> .
>


-- 
Regards, Rongrong

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2016-11-11 13:57 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-28  7:27 [PATCH v6 0/9] Add DRM driver for Hisilicon Hibmc Rongrong Zou
2016-10-28  7:27 ` Rongrong Zou
2016-10-28  7:27 ` [PATCH v6 1/9] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 17:35   ` Sean Paul
2016-11-10 17:35     ` Sean Paul
2016-11-11  3:10     ` Rongrong Zou
2016-11-11  3:10       ` Rongrong Zou
2016-10-28  7:27 ` [PATCH v6 2/9] drm/hisilicon/hibmc: Add video memory management Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 17:35   ` Sean Paul
2016-11-10 17:35     ` Sean Paul
2016-11-11 11:16     ` Rongrong Zou
2016-11-11 11:16       ` Rongrong Zou
2016-11-11 13:25       ` Sean Paul
2016-11-11 13:25         ` Sean Paul
2016-11-11 13:57         ` Rongrong Zou [this message]
2016-11-11 13:57           ` Rongrong Zou
2016-10-28  7:27 ` [PATCH v6 3/9] drm/hisilicon/hibmc: Add support for frame buffer Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 18:30   ` Sean Paul
2016-11-10 18:30     ` Sean Paul
2016-11-11 13:16     ` Rongrong Zou
2016-11-11 13:16       ` Rongrong Zou
2016-11-11 13:27       ` Sean Paul
2016-11-11 13:27         ` Sean Paul
2016-10-28  7:27 ` [PATCH v6 4/9] drm/hisilicon/hibmc: Add plane for DE Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 21:53   ` Sean Paul
2016-11-10 21:53     ` Sean Paul
2016-11-12  5:11     ` Rongrong Zou
2016-11-12  5:11       ` Rongrong Zou
2016-11-14 17:08       ` Sean Paul
2016-11-14 17:08         ` Sean Paul
2016-10-28  7:27 ` [PATCH v6 5/9] drm/hisilicon/hibmc: Add crtc " Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 22:14   ` Sean Paul
2016-11-10 22:14     ` Sean Paul
2016-11-12 10:19     ` Rongrong Zou
2016-11-12 10:19       ` Rongrong Zou
2016-11-14 17:10       ` Sean Paul
2016-11-14 17:10         ` Sean Paul
2016-10-28  7:27 ` [PATCH v6 6/9] drm/hisilicon/hibmc: Add encoder for VDAC Rongrong Zou
2016-10-28  7:27   ` Rongrong Zou
2016-11-10 22:20   ` Sean Paul
2016-11-10 22:20     ` Sean Paul
2016-11-12 10:36     ` Rongrong Zou
2016-11-12 10:36       ` Rongrong Zou
2016-10-28  7:28 ` [PATCH v6 7/9] drm/hisilicon/hibmc: Add connector " Rongrong Zou
2016-10-28  7:28   ` Rongrong Zou
2016-11-11  1:45   ` Sean Paul
2016-11-11  1:45     ` Sean Paul
2016-11-14 14:07     ` Rongrong Zou
2016-11-14 14:07       ` Rongrong Zou
2016-10-28  7:28 ` [PATCH v6 8/9] drm/hisilicon/hibmc: Add vblank interruput Rongrong Zou
2016-10-28  7:28   ` Rongrong Zou
2016-11-11  1:49   ` Sean Paul
2016-11-11  1:49     ` Sean Paul
2016-11-14 14:10     ` Rongrong Zou
2016-11-14 14:10       ` Rongrong Zou
2016-10-28  7:28 ` [PATCH v6 9/9] MAINTAINERS: Update HISILICON DRM entries Rongrong Zou
2016-10-28  7:28   ` Rongrong Zou
2016-11-11  1:50   ` Sean Paul
2016-11-11  1:50     ` Sean Paul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5825CE64.5080708@huawei.com \
    --to=zourongrong@huawei.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.