issue ありがとうございます。 私も当初、pgprot_noncached(vm_page_prot) にしていたのですが、ARM64 の場合、pgprot_noncached(vm_page_prot) だと memset() で Bus error が起きました。 当時の状況を再現すると次のようになります。 root@debian-fpga:~/work/u-dma-buf# insmod u-dma-buf.ko udmabuf0=0x100000[ 1503.464874] u-dma-buf u-dma-buf.0: DMA mask not set[ 1503.472404] u-dma-buf udmabuf0: driver version = 2.1.0-rc2[ 1503.477913] u-dma-buf udmabuf0: major number = 239[ 1503.482876] u-dma-buf udmabuf0: minor number = 0[ 1503.487662] u-dma-buf udmabuf0: phys address = 0x0000000070100000[ 1503.493931] u-dma-buf udmabuf0: buffer size = 1048576[ 1503.499240] u-dma-buf udmabuf0: dma device = u-dma-buf.0[ 1503.504893] u-dma-buf udmabuf0: dma coherent = 0[ 1503.509682] u-dma-buf u-dma-buf.0: driver installed.root@debian-fpga:~/work/u-dma-buf# ./u-dma-buf_testphys_addr=0x70100000size=1048576check_buf()sync_mode=0, O_SYNC=0, time = 0.340671 secsync_mode=0, O_SYNC=1, time = 0.340689 secsync_mode=1, O_SYNC=0, time = 0.340718 secsync_mode=1, O_SYNC=1, time = 2.287233 secsync_mode=2, O_SYNC=0, time = 0.340636 secsync_mode=2, O_SYNC=1, time = 2.284903 secsync_mode=3, O_SYNC=0, time = 0.340641 secsync_mode=3, O_SYNC=1, time = 2.285236 secsync_mode=4, O_SYNC=0, time = 0.340651 secsync_mode=4, O_SYNC=1, time = 0.340708 secsync_mode=5, O_SYNC=0, time = 2.286918 secsync_mode=5, O_SYNC=1, time = 2.286774 secsync_mode=6, O_SYNC=0, time = 2.284642 secsync_mode=6, O_SYNC=1, time = 2.285348 secsync_mode=7, O_SYNC=0, time = 2.285135 secsync_mode=7, O_SYNC=1, time = 2.288342 secclear_buf()sync_mode=0, O_SYNC=0, time = 0.026720 secsync_mode=0, O_SYNC=1, time = 0.026641 secsync_mode=1, O_SYNC=0, time = 0.026642 secBus errorroot@debian-fpga:~/work/u-dma-buf#
ここでの u-dma-buf_test は、https://github.com/ikwzm/udmabuf の含まれている u-dma-buf_test.c をコンパイルしたものです。 この問題は pgprot_noncached(vm_page_prot) を pgprot_writecombine(vm_page_prot) に変更することで治りました。変更後の u-dma-buf_test 実行結果は次の通りです。 root@debian-fpga:~/work/u-dma-buf# insmod u-dma-buf.ko udmabuf0=0x100000[ 1871.450164] u-dma-buf u-dma-buf.0: DMA mask not set[ 1871.458503] u-dma-buf udmabuf0: driver version = 2.1.0-rc2[ 1871.463998] u-dma-buf udmabuf0: major number = 238[ 1871.468970] u-dma-buf udmabuf0: minor number = 0[ 1871.473763] u-dma-buf udmabuf0: phys address = 0x0000000070100000[ 1871.480032] u-dma-buf udmabuf0: buffer size = 1048576[ 1871.485341] u-dma-buf udmabuf0: dma device = u-dma-buf.0[ 1871.490993] u-dma-buf udmabuf0: dma coherent = 0[ 1871.495782] u-dma-buf u-dma-buf.0: driver installed.root@debian-fpga:~/work/u-dma-buf# ./u-dma-buf_testphys_addr=0x70100000size=1048576check_buf()sync_mode=0, O_SYNC=0, time = 0.340644 secsync_mode=0, O_SYNC=1, time = 0.340684 secsync_mode=1, O_SYNC=0, time = 0.340817 secsync_mode=1, O_SYNC=1, time = 2.284729 secsync_mode=2, O_SYNC=0, time = 0.340670 secsync_mode=2, O_SYNC=1, time = 2.284785 secsync_mode=3, O_SYNC=0, time = 0.340598 secsync_mode=3, O_SYNC=1, time = 2.284776 secsync_mode=4, O_SYNC=0, time = 0.340752 secsync_mode=4, O_SYNC=1, time = 0.340691 secsync_mode=5, O_SYNC=0, time = 2.284722 secsync_mode=5, O_SYNC=1, time = 2.284562 secsync_mode=6, O_SYNC=0, time = 2.284552 secsync_mode=6, O_SYNC=1, time = 2.284584 secsync_mode=7, O_SYNC=0, time = 2.284632 secsync_mode=7, O_SYNC=1, time = 2.284620 secclear_buf()sync_mode=0, O_SYNC=0, time = 0.019320 secsync_mode=0, O_SYNC=1, time = 0.019328 secsync_mode=1, O_SYNC=0, time = 0.019312 secsync_mode=1, O_SYNC=1, time = 0.026633 secsync_mode=2, O_SYNC=0, time = 0.019315 secsync_mode=2, O_SYNC=1, time = 0.026621 secsync_mode=3, O_SYNC=0, time = 0.019306 secsync_mode=3, O_SYNC=1, time = 0.026632 secsync_mode=4, O_SYNC=0, time = 0.019307 secsync_mode=4, O_SYNC=1, time = 0.019317 secsync_mode=5, O_SYNC=0, time = 0.026609 secsync_mode=5, O_SYNC=1, time = 0.026621 secsync_mode=6, O_SYNC=0, time = 0.026615 secsync_mode=6, O_SYNC=1, time = 0.026624 secsync_mode=7, O_SYNC=0, time = 0.026605 secsync_mode=7, O_SYNC=1, time = 0.026623 sec
ですので、pgprot_noncached に変更するのは見送らせてください。 しかし、ご指摘の通り、問題があるのはわかりました。 write_combine は CPUからの書き込み要求をキャッシュラインサイズ(ARM64 では 64Byte)単位でをマージしてからメモリに書き込む方法なので、ご指摘のプログラムのようにキャッシュライン単位じゃない書き込み(72Byte書き込み)の後、すぐに読み出すとおかしくなるのかもしれません。 ですが、これって、デバイスドライバレベルで修正できるものなのかわかりません。。。 |
はじめまして、お世話になっております。
Ultra96 上で udmabuf を用いて 72 byte のデータを udmabuf に配置しその後 AXI DMA を用いて PL に送信してみたのですが、最初の 64 byte のみ送信され、残りの値が 0 になってしまいました。
以下のコードで再現します。
以下のようにして実行できます。
1で埋められた配列 arr を udmabuf で確保したメモリに memcpy した後、
/dev/mem
を通じて phys_addr+64 にアクセスしているのですが、0が返ってきてしまいます。(0~63 にアクセスしたときは正しく1が返ってきます。)この PR の変更を適用することで解決したのですが、もし正しい修正ならマージしていただけますでしょうか。
よろしくお願いいたします。