Posted at

Linuxでユーザー空間で動作するプログラムとハードウェアがメモリを共有するためのデバイスドライバ(Device Tree Overlay対応)

More than 3 years have passed since last update.


はじめに

先日投稿した 「Linuxでユーザー空間で動作するプログラムとハードウェアがメモリを共有するためのデバイスドライバ」 で紹介した udmabufは、デバイスドライバのロード時に Device Tree に従って各種デバイスファイルを生成します。

通常、 Device Tree は Linux のブート時に指定されたものから変化することはありませんでした。

しかし、「FPGA+SoC+LinuxでDevice Tree Overlayを試してみた」で紹介したように、最近の Linux では Device Tree が動的に変化することがあります。

その際、問題になるのが udmabuf のデバイス名とデバイスドライバのマイナー番号でした。Device Tree が常に一定ならば、udmabuf のロード時にデバイス名とデバイスドライバのマイナー番号を決め打ちしても問題ありませんでしたが、動的に Device Tree が変化する場合、デバイス名やデバイスドライバのマイナー番号を決め打ちするのは不便です。

そこで、デバイスドライバをこれらの問題に対応すべく、Device Tree でデバイス名をで指定できるようにしたり、デバイスドライバのマイナー番号を省略した場合は自動的に空いている番号を割り当てるようにしました。

http://github.com/ikwzm/udmabuf


デバイスツリーによる設定


devicetree.dts

        udmabuf@0x00 {

compatible = "ikwzm,udmabuf-0.10.a";
device-name = "udmabuf0";
minor-number = <0>;
size = <0x00100000>;
};


sizeでDMAバッファの容量をバイト数で指定します。

device-nameでデバイス名を指定します。

minor-number でudmabufのマイナー番号を指定します。マイナー番号は0から255までつけることができます。ただし、insmodの引数の方が優先され、マイナー番号がかち合うとdevicetreeで指定した方が失敗します。minor-numberが省略された場合、空いているマイナー番号が割り当てられます。

デバイス名は次のように決まります。


  1. device-nameが指定されていた場合は、 device-name。

  2. device-nameが省略されていて、かつminor-numberが指定されていた場合は、sprintf("udmabuf%d", minor-number)。

  3. device-nameが省略されていて、かつminor-numberも省略されていた場合は、devicetree のエントリー名(例ではudmabuf@0x00)。

zynq$ insmod udmabuf.ko

udmabuf udmabuf0: driver installed
udmabuf udmabuf0: major number = 248
udmabuf udmabuf0: minor number = 0
udmabuf udmabuf0: phys address = 0x1e900000
udmabuf udmabuf0: buffer size = 1048576
zynq$ ls -la /dev/udmabuf0
crw------- 1 root root 248, 0 Dec 1 09:34 /dev/udmabuf0


デバイスファイル

udmabufをinsmodでカーネルにロードすると、次のようなデバイスファイルが作成されます。<device-name>には、前節で説明したデバイス名が入ります。


  • /dev/<device-name>

  • /sys/class/udmabuf/<device-name>/phys_addr

  • /sys/class/udmabuf/<device-name>/size

  • /sys/class/udmabuf/<device-name>/sync_mode

  • /sys/class/udmabuf/<device-name>/sync_offset

  • /sys/class/udmabuf/<device-name>/sync_size

  • /sys/class/udmabuf/<device-name>/sync_direction

  • /sys/class/udmabuf/<device-name>/sync_owner

  • /sys/class/udmabuf/<device-name>/sync_for_cpu

  • /sys/class/udmabuf/<device-name>/sync_for_device