*参照元 [#l9ed6214]
#backlinks

*説明 [#j29aa4c1]
FIXME: なにをするもの?

-とぴっく
--共有に特化、バッファを確保する機能は提供しない。
--CMA など、別の手段を用いてドライバ(DMA buffer sharing の利用者側)が確保しなければならない。


**主要ユーザ API [#v97154ee]

-[[linux-4.4.1/dma_buf_fops(global)]] より、下記に対応していると思われる。
--close()
--mmap()
---ユーザプロセスからバッファを読み書きしたいときに使う。offset はバッファの先頭からの距離を表す。キャッシュの有効、無効はバックエンドのシステムによるので、一概に言えない。
--seek()
---バッファのサイズを知るために使う。SEEK_END を指定すればサイズがわかる。
--poll()
---同時に DMA を実行して、バッファの内容を破壊しないように、fence という仕組みで排他していて、fence からのシグナルを待つために poll を使うようだ。

-mmap() の動き
 mmap()
   - dma_buf_mmap_internal()
     - dmabuf->ops->mmap()
       ION の場合 mmap = ion_mmap, なので、
       - ion_mmap()
         - buffer->heap->ops->map_user()
           Carveout Heap の場合 map_user = ion_heap_map_user, なので、
           - ion_heap_map_user()
             - remap_pfn_range()
 
 もう一例。
 mmap()
   - dma_buf_mmap_internal()
     - dmabuf->ops->mmap()
       V4L2, 物理連続メモリを要求するデバイスの場合 mmap = vb2_dc_mmap, なので、
       - vb2_dc_mmap()
         - dma_mmap_coherent()
           - dma_mmap_attrs()
             - ops->mmap()
               ARM の場合、通常は mmap = arm_dma_mmap, なので、
               - arm_dma_mmap()
                 - __arm_dma_mmap()
                   - remap_pfn_range()


**主要カーネル API [#v9878462]

-dma_buf_ops を使って、DMA バッファの扱い方(特にどうやって仮想空間にマップするかは必須)を定義する。
--[[linux-4.4.1/dma_buf_ops]]
--なぜかというと、DMA バッファの確保の仕方によってバッファのマップの仕方は違うので、マップの仕方を dma_buf ライブラリに渡す必要があるから。最低限、実装が必要なメンバは下記の通り。
---map_dma_buf
---unmap_dma_buf
---release
---kmap_atomic
---kmap
---mmap
-バッファを共有するための準備をする、dma_buf ライブラリにバッファを伝える。上記の dma_buf_ops も渡す。
--[[linux-4.4.1/dma_buf_export()]]
--[[linux-4.4.1/dma_buf_export_info]]
-DMA Buffer を fd を得る。
-DMA Buffer から fd を得る。
--[[linux-4.4.1/dma_buf_fd()]]
-fd から DMA Buffer を得る。
--[[linux-4.4.1/dma_buf_get()]]
-DMA Buffer の共有を開始する
--[[linux-4.4.1/dma_buf_attach()]]
--[[linux-4.4.1/dma_buf_attachment]]
-DMA Buffer をカーネルのリニアアドレス空間にマッピングする。
--ドライバからバッファにアクセスするときは必須。
--[[linux-4.4.1/dma_buf_map_attachment()]]
--[[linux-4.4.1/dma_buf_unmap_attachment()]]
-DMA Buffer をユーザの仮想空間にマッピングする。
--[[linux-4.4.1/dma_buf_mmap()]]
-DMA Buffer の共有を終了する
--[[linux-4.4.1/dma_buf_detach()]]


**シーケンス [#n3abc860]

-バッファのオーナーとなるドライバ
--バッファ確保
---方法は何でも良い、例えば [[linux-4.4.1/dma_alloc_coherent()]] などを使う
--[[linux-4.4.1/dma_buf_export()]]
---バッファの共有の準備をする。
---dma_buf カーネルライブラリにバッファの存在を教える。
---[[linux-4.4.1/dma_buf]] が得られる。
--[[linux-4.4.1/dma_buf_fd()]]
---バッファを共有するためのファイルディスクリプタが得られる。

-バッファのオーナーとなるプロセス
--ファイルディスクリプタを受け取る。
---ドライバからファイルディスクリプタを受け取る方法は任意。
---[[linux-4.4.1/ioctl()]] を使うことになる?

-バッファのユーザとなるプロセス
--ファイルディスクリプタを受け取る。
---バッファのオーナープロセスから受け取る方法は任意。
---UNIX socket の sendmsg() の cmsg で複製できる?

-バッファのユーザとなるドライバ
--ファイルディスクリプタを受け取る
---ユーザプロセスから fd を受け取る方法は任意。
---[[linux-4.4.1/ioctl()]] を使うことになる?
--[[linux-4.4.1/dma_buf_get()]]
---dma_buf カーネルライブラリから共有したいバッファを得る。
---[[linux-4.4.1/dma_buf]] が得られる。
--[[linux-4.4.1/dma_buf_attach()]]
---dma_buf カーネルライブラリにバッファを使用し始めることを教える。
---[[linux-4.4.1/dma_buf_attachment]] が得られる。
---attach() コールバックが呼ばれる。
--[[linux-4.4.1/dma_buf_map_attachment()]]
---バッファにアクセスできるようにマップする。
---[[linux-4.4.1/sg_table]] が得られる。
---map_dma_buf() コールバックが呼ばれる。
--バッファに対して、データの読み書きなどを行う。
--[[linux-4.4.1/dma_buf_unmap_attachment()]]
---バッファのマップを解放して、アクセスできないようにする。
---unmap_dma_buf() コールバックが呼ばれる。
--[[linux-4.4.1/dma_buf_detach()]]
---dma_buf カーネルライブラリにバッファを使用し終わったことを教える。
---detach() コールバックが呼ばれる。

-予想
--バッファのオーナーとユーザーがファイルディスクリプタを閉じると、
release() コールバックが呼ばれると思われる。


**使い方の例 [#ab4da934]

 (調査中)


**カーネル API 一覧[#v9878462]

-linux/Documentation/DocBook/device-drivers/ より
--[[linux-4.4.1/dma_buf_export()]]: Creates a new dma_buf, and associates an anon file with this buffer, so it can be exported. Also connect the allocator specific data and ops to the buffer. Additionally, provide a name string for exporter; useful in debugging.
--[[linux-4.4.1/dma_buf_fd()]]: returns a file descriptor for the given dma_buf
--[[linux-4.4.1/dma_buf_get()]]: returns the dma_buf structure related to an fd
--[[linux-4.4.1/dma_buf_put()]]: decreases refcount of the buffer
--[[linux-4.4.1/dma_buf_attach()]]: Add the device to dma_buf's attachments list; optionally, calls attach of dma_buf_ops to allow device-specific attach functionality
--[[linux-4.4.1/dma_buf_detach()]]: Remove the given attachment from dmabuf's attachments list; optionally calls detach of dma_buf_ops for device-specific detach
--[[linux-4.4.1/dma_buf_map_attachment()]]: Returns the scatterlist table of the attachment; mapped into _device_ address space. Is a wrapper for map_dma_buf of the dma_buf_ops.
--[[linux-4.4.1/dma_buf_unmap_attachment()]]: unmaps and decreases usecount of the buffer;might deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf of dma_buf_ops.
--[[linux-4.4.1/dma_buf_begin_cpu_access()]]: Must be called before accessing a dma_buf from the cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific preparations. Coherency is only guaranteed in the specified range for the specified access direction.
--[[linux-4.4.1/dma_buf_end_cpu_access()]]: Must be called after accessing a dma_buf from the cpu in the kernel context. Calls end_cpu_access to allow exporter-specific actions. Coherency is only guaranteed in the specified range for the specified access direction.
--[[linux-4.4.1/dma_buf_kmap_atomic()]]: Map a page of the buffer object into kernel address space. The same restrictions as for kmap_atomic and friends apply.
--[[linux-4.4.1/dma_buf_kunmap_atomic()]]: Unmap a page obtained by dma_buf_kmap_atomic.
--[[linux-4.4.1/dma_buf_kmap()]]: Map a page of the buffer object into kernel address space. The same restrictions as for kmap and friends apply.
--[[linux-4.4.1/dma_buf_kunmap()]]: Unmap a page obtained by dma_buf_kmap.
--[[linux-4.4.1/dma_buf_mmap()]]: Setup up a userspace mmap with the given vma
--[[linux-4.4.1/dma_buf_vmap()]]: Create virtual mapping for the buffer object into kernel address space. Same restrictions as for vmap and friends apply.
--[[linux-4.4.1/dma_buf_vunmap()]]: Unmap a vmap obtained by dma_buf_vmap.


**参考 [#oea5d6fe]

 $ egrep -r '^EXPORT_SYMBOL' drivers/dma-buf/
 drivers/dma-buf/seqno-fence.c:EXPORT_SYMBOL(seqno_fence_ops);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_context_alloc);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_signal_locked);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_signal);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_wait_timeout);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_release);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_free);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_enable_sw_signaling);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_add_callback);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_remove_callback);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_default_wait);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_wait_any_timeout);
 drivers/dma-buf/fence.c:EXPORT_SYMBOL(fence_init);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_ww_class);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_seqcount_class);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_seqcount_string);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_object_reserve_shared);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_object_add_shared_fence);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL(reservation_object_add_excl_fence);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu);
 drivers/dma-buf/reservation.c:EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_export);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_fd);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_get);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_put);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_attach);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_detach);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_kmap);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_kunmap);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_mmap);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_vmap);
 drivers/dma-buf/dma-buf.c:EXPORT_SYMBOL_GPL(dma_buf_vunmap);


**関連モジュール [#q31b30fc]


*コメント [#n7c0ba9b]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS