Re: [Linaro-mm-sig] [PATCH] dma-buf: add meta data attachment

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

 



Hi all,

On 2014년 03월 24일 16:35, Daniel Vetter wrote:
> Hi all,
> 
> Adding piles more people.
> 
> For the first case of caching the iommu mapping there's different
> answers, depening upon the exact case:
> 
> 1) You need to fix your userspace to not constantly re-establish the sharing.
> 
> 2) We need to add streaming dma support for real to dma-bufs so that
> the mapping can be kept while we transfer ownership around. Thus far
> no one really needed this though since usually you don't actually do
> cpu access.
> 
> 3) You need opportunistic caching of imported/exported buffer objects
> and their mappings. For this you need a) subsystem import/export
> support which guarantees you to hand out the same dma-buf/native
> object again upon re-export or re-import (drm has it) b) some
> opportunistic caching of buffer objects (pretty much are real gpu drm
> drivers have it). No need of any metadata scheme, and given how much
> fun I've had implemented this for drm I don't you can make your
> metadata scheme work in a sane or correct way wrt lifetimes.
> 
> For caching the iommu mapping if the iommu is the same for multiple devices:
> 
> 1) We need some way to figure out which iommu serves which devices.
> 
> 2) The exporter needs to consult this and might just hand out the same
> sg mapping out again if it wants to.
> 
> No need for importers to do fancy stuff, or attach any
> importer-visible metadata to dma-bufs. Of course duplicating this code
> all over the place is a but uncool, so I expect that eventually we'll
> have a generic exporter implementation, at least for non-swappable
> buffers. drm/gem is a bit special here ...
> 
> In general I don't like the idea of arbitrary metadata at all, sounds
> prone to abuse with crazy lifetime/refcounting rules for the objects
> involved. Also I think for a lot of your examples (like debugging) it
> would be much better if we have a standardized piece of metadata so
> that all drivers/platforms can use the same tooling.
> 
> And it feels like I'm writing such a mail every few months ...

I posted concept about importer priv of dma-buf, and it seems that this
patch is partly from similar requirement - iommu map/unmap.

And at that time, Daniel agreed at least the issue, that unnecessary
map/unmap can repeatedly called, is also in the drm gem.
http://lists.freedesktop.org/archives/dri-devel/2013-June/039469.html

So I agree about the necessary of some data of dma-buf for general
importer even though the data can be shared between different subsystems.

> 
> Cheers, Daniel
> 
> On Mon, Mar 24, 2014 at 7:20 AM, Bin Wang <binw@xxxxxxxxxxx> wrote:
>> Hi Sumit,
>>
>> On 03/21/2014 07:26 PM, Sumit Semwal wrote:
>>> Hi Bin Wang,
>>>
>>> On 21 March 2014 10:34, Bin Wang <binw@xxxxxxxxxxx> wrote:
>>>> we found there'd be varied specific data connected to a dmabuf, like
>>>> the iommu mapping of buffer, the dma descriptors (that can be shared
>>>> between several components). Though these info might be able to be
>>>> generated every time before dma operations, for performance sake,
>>>> it's better to be kept before really invalid.
>>> Thanks for your patch!
>>> I think we'd need to have more specific details on what does 'meta
>>> data' mean here; more specific comments inline.
>>>> Change-Id: I89d43dc3fe1ee3da91c42074da5df71b968e6d3c
>>>> Signed-off-by: Bin Wang <binw@xxxxxxxxxxx>
>>>> ---
>>>>   drivers/base/dma-buf.c  |  100 +++++++++++++++++++++++++++++++++++++++++++++++
>>>>   include/linux/dma-buf.h |   22 ++++++++++
>>>>   2 files changed, 122 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
>>>> index 08fe897..5c82e60 100644
>>>> --- a/drivers/base/dma-buf.c
>>>> +++ b/drivers/base/dma-buf.c
>>>> @@ -50,6 +50,7 @@ static int dma_buf_release(struct inode *inode, struct file *file)
>>>>
>>>>          BUG_ON(dmabuf->vmapping_counter);
>>>>
>>>> +       dma_buf_meta_release(dmabuf);
>>>>          dmabuf->ops->release(dmabuf);
>>>>
>>>>          mutex_lock(&db_list.lock);
>>>> @@ -138,6 +139,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
>>>>
>>>>          mutex_init(&dmabuf->lock);
>>>>          INIT_LIST_HEAD(&dmabuf->attachments);
>>>> +       INIT_LIST_HEAD(&dmabuf->metas);
>>>>
>>> I am not sure I understand the relationship of 'meta data' with
>>> 'dma-buf', or 'attachments' - do you mean to have a list of some
>>> meta-data that is unrelated to the attachments to the dma-buf? I think
>>> it'd help to explain whether meta-data is specific to each dma-buf,
>>> and there's a list of them, or this meta-data is related to each
>>> importer device attachment?
>>> If it's related to each importer, it should really be added as part of
>>> the dma_buf_attachment, and not separately.

This is basic concept of my RFC patch.
http://www.kernelhub.org/?p=2&msg=268056

Best Regards,
- Seung-Woo Kim

>> The "meta-data" here can be any kind of data related to the dmabuf, , it's specific
>> for each dmabuf.
>>
>> For example, we have iommu for a VPU device, VPU driver has
>> to map the dmabuf to get an IOVA address before it can access the buffer. This
>> dmabuf would be reused many times during the video playback, for performance
>> concern we don't want this dmabuf be map/unmaped by iommu driver every time
>> of VPU HW data transfer, since the physical pages not changed and iommu IOVA
>> plenty.
>>
>> Another example, in our SoC, device A and device B use the same dma chain format,
>> and these drivers share dmabuf between each other, thus the "dma chain"
>> array doesn't need to be generated every timer for each device.
>>
>> So here, with the help from the "meta-data", only the "first time" we need to generate
>> the "meta-data" from scratch, and later we can just reuse it until the buffer freed.
>>
>> The "meta-data" is related to the importer, or importers. However, the "dma_buf_attachment"
>> is per "devices", holding device specific attributes, while "meta-data" is per "dmabuf',
>> holding buffer specific attributes, like the example above.
>>>>          mutex_lock(&db_list.lock);
>>>>          list_add(&dmabuf->list_node, &db_list.head);
>>>> @@ -570,6 +572,104 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
>>>>   }
>>>>   EXPORT_SYMBOL_GPL(dma_buf_vunmap);
>>>>
>>>> +/**
>>>> + * dma_buf_meta_attach - Attach additional meta data to the dmabuf
>>>> + * @dmabuf:    [in]    the dmabuf to attach to
>>>> + * @id:                [in]    the id of the meta data
>>>> + * @pdata:     [in]    the raw data to be attached
>>>> + * @release:   [in]    the callback to release the meta data
>>>> + */
>>>> +int dma_buf_meta_attach(struct dma_buf *dmabuf, int id, void *pdata,
>>>> +       int (*release)(void *))
>>>> +{
>>>> +       struct dma_buf_meta *pmeta;
>>>> +
>>>> +       pmeta = kmalloc(sizeof(struct dma_buf_meta), GFP_KERNEL);
>>>> +       if (pmeta == NULL)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       pmeta->id = id;
>>> What does 'id' mean here? Also there is no check on any duplicity on
>>> the 'id', so if any device adds more meta data with the same ID, you
>>> would always work only on the first one? It would also help if you
>>> could explain the relevance of id.
>> The "id" here means a kind of specific "meta-data", for example we use
>> "#define VPU_DMABUF_META_ID    0x10000" for the VPU iommu related
>> data.
>>
>> Each importer would try to "dma_buf_meta_fetch()" the "meta-data" first, if
>> not found, it would generate and attach it. If found, it would just reuse it.
>>
>> I agree with you that it's better to add the check of id in this function as well.
>>>> +       pmeta->pdata = pdata;
>>>> +       pmeta->release = release;
>>>> +
>>>> +       mutex_lock(&dmabuf->lock);
>>>> +       list_add(&pmeta->node, &dmabuf->metas);
>>>> +       mutex_unlock(&dmabuf->lock);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(dma_buf_meta_attach);
>>>> +
>>>> +/**
>>>> + * dma_buf_meta_dettach - Dettach the meta data from dmabuf by id
>>>> + * @dmabuf:    [in]    the dmabuf including the meta data
>>>> + * @id:                [in]    the id of the meta data
>>>> + */
>>>> +int dma_buf_meta_dettach(struct dma_buf *dmabuf, int id)
>>>> +{
>>>> +       struct dma_buf_meta *pmeta, *tmp;
>>>> +       int ret = -ENOENT;
>>>> +
>>>> +       mutex_lock(&dmabuf->lock);
>>>> +       list_for_each_entry_safe(pmeta, tmp, &dmabuf->metas, node) {
>>>> +               if (pmeta->id == id) {
>>>> +                       if (pmeta->release)
>>>> +                               pmeta->release(pmeta->pdata);
>>>> +                       list_del(&pmeta->node);
>>>> +                       kfree(pmeta);
>>>> +                       ret = 0;
>>>> +                       break;
>>>> +               }
>>>> +       }
>>>> +       mutex_unlock(&dmabuf->lock);
>>>> +
>>>> +       return ret;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(dma_buf_meta_dettach);
>>>> +
>>>> +/**
>>>> + * dma_buf_meta_fetch - Get the meta data from dmabuf by id
>>>> + * @dmabuf:    [in]    the dmabuf including the meta data
>>>> + * @id:                [in]    the id of the meta data
>>>> + */
>>>> +void *dma_buf_meta_fetch(struct dma_buf *dmabuf, int id)
>>>> +{
>>>> +       struct dma_buf_meta *pmeta;
>>>> +       void *pdata = NULL;
>>>> +
>>>> +       mutex_lock(&dmabuf->lock);
>>>> +       list_for_each_entry(pmeta, &dmabuf->metas, node) {
>>>> +               if (pmeta->id == id) {
>>>> +                       pdata = pmeta->pdata;
>>>> +                       break;
>>>> +               }
>>>> +       }
>>>> +       mutex_unlock(&dmabuf->lock);
>>>> +
>>>> +       return pdata;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(dma_buf_meta_fetch);
>>>> +
>>>> +/**
>>>> + * dma_buf_meta_release - Release all the meta data attached to the dmabuf
>>>> + * @dmabuf:    [in]    the dmabuf including the meta data
>>>> + */
>>>> +void dma_buf_meta_release(struct dma_buf *dmabuf)
>>>> +{
>>>> +       struct dma_buf_meta *pmeta, *tmp;
>>>> +
>>>> +       mutex_lock(&dmabuf->lock);
>>>> +       list_for_each_entry_safe(pmeta, tmp, &dmabuf->metas, node) {
>>>> +               if (pmeta->release)
>>>> +                       pmeta->release(pmeta->pdata);
>>>> +               list_del(&pmeta->node);
>>>> +               kfree(pmeta);
>>>> +       }
>>>> +       mutex_unlock(&dmabuf->lock);
>>>> +
>>>> +       return;
>>>> +}
>>>> +
>>>>   #ifdef CONFIG_DEBUG_FS
>>>>   static int dma_buf_describe(struct seq_file *s)
>>>>   {
>>>> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
>>>> index dfac5ed..369d032 100644
>>>> --- a/include/linux/dma-buf.h
>>>> +++ b/include/linux/dma-buf.h
>>>> @@ -120,6 +120,7 @@ struct dma_buf {
>>>>          size_t size;
>>>>          struct file *file;
>>>>          struct list_head attachments;
>>>> +       struct list_head metas;
>>>>          const struct dma_buf_ops *ops;
>>>>          /* mutex to serialize list manipulation, attach/detach and vmap/unmap */
>>>>          struct mutex lock;
>>>> @@ -149,6 +150,20 @@ struct dma_buf_attachment {
>>>>   };
>>>>
>>> Like I said above, I don't think I completely understand the need of
>>> 'a list of metas' - a sample usage would be most helpful to realise
>>> the relevance here.
>> As the examples above, in the list of "metas", there can be, VPU iommu mapping info,
>> camera/display dma chain info, or other debugging/tracking info etc.
>>>>   /**
>>>> + * struct dma_buf_meta - holds varied meta data attached to the buffer
>>>> + * @id: the identification of the meta data
>>>> + * @dmabuf: buffer for this attachment.
>>>> + * @node: list of dma_buf_meta.
>>>> + * @pdata: specific meta data.
>>>> + */
>>>> +struct dma_buf_meta {
>>>> +       int id;
>>>> +       struct list_head node;
>>>> +       int (*release)(void *pdata);
>>>> +       void *pdata;
>>>> +};
>>>> +
>>>> +/**
>>>>    * get_dma_buf - convenience wrapper for get_file.
>>>>    * @dmabuf:    [in]    pointer to dma_buf
>>>>    *
>>>> @@ -194,6 +209,13 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
>>>>                   unsigned long);
>>>>   void *dma_buf_vmap(struct dma_buf *);
>>>>   void dma_buf_vunmap(struct dma_buf *, void *vaddr);
>>>> +
>>>> +int dma_buf_meta_attach(struct dma_buf *dmabuf, int id, void *pdata,
>>>> +       int (*release)(void *));
>>>> +int dma_buf_meta_dettach(struct dma_buf *dmabuf, int id);
>>>> +void *dma_buf_meta_fetch(struct dma_buf *dmabuf, int id);
>>>> +void dma_buf_meta_release(struct dma_buf *dmabuf);
>>>> +
>>>>   int dma_buf_debugfs_create_file(const char *name,
>>>>                                  int (*write)(struct seq_file *));
>>>>   #endif /* __DMA_BUF_H__ */
>>>> --
>>>> 1.7.0.4
>>>>
>>>>
>>>> _______________________________________________
>>>> Linaro-mm-sig mailing list
>>>> Linaro-mm-sig@xxxxxxxxxxxxxxxx
>>>> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig
>>>
>>>
>> The purpose of this extension mainly is:
>> 1. Try to reuse the first generated specific data in the buffer's life time, to avoid redundant map/unmap, or generate/free.
>> 2. Try to share the "reusable" data between devices, if the devices support compatible formats.
>>
>> Regards,
>> Bin Wang
>> _______________________________________________
>> Linaro-mm-sig mailing list
>> Linaro-mm-sig@xxxxxxxxxxxxxxxx
>> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig
> 
> 
> 

-- 
Seung-Woo Kim
Samsung Software R&D Center
--

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux