Raspberry Pi Advent Calendar 2020の11日目です。
10日目に書いたRaspberry Pi Compute Module 4でPCI Expressデバイスを動かすまでの話です。以下は前回のやつ。
さして起動してもサクッとは認識しないPCIeデバイス
前回の記事の最後にちらっと書きましたが、Raspberry PiにPCI Expressが出てきたのはPi 4のUSB3.0ポート用チップ搭載からなので、そのへんの最適化しか考慮されていなければ、もちろん他のPCIeデバイス用のドライバーも標準では用意されていないので、基本的には自分でコンパイルする必要があります。また、ARM環境で使えるデバイスばかりとは行かない点にも要注意です。
なので、今回手元にあったGbE NIC、10GBe NIC、GPUのうち、いまのところ動作させられたのはGbE NICだけという点は先に書いておきます。惜しい!
先人の資料とBARアドレス空間について
海外では、すでにCM4をゲットした人達によって動作させるための情報がまとめられ始めています。多分一番まとまっているのではないかと思うのが、Jeff Geerling氏によるページです。
Jeff氏のまとめ曰く、ソースコード云々やARMでコンパイルが通るかとは別に、PCIeデバイスを初期化するときに使うBARアドレス空間というものを広げるための作業が必要なケースが多いとのこと。BARアドレス空間を広げるための手順は以下に公開されています。
Increase the BAR memory address space for PCIe devices on the Raspberry Pi Compute Module 4 · GitHub
また、rpi-updateコマンドでnextブランチのファームウェアを持ってくると、最初からBARアドレス空間が拡張された状態になるとのことなので、PCIeデバイスでほげほげして遊ぶならnextブランチの最新ファームにしてしまったほうが良いかもしれません。私もdtbを書き換えたりしてみましたが、ソースコードのコンパイルの方でうまく行かなかったので、最新ファームコースでやっていくことにしました。
nextブランチの最新ファームにして、カーネルソースを拾う
以下のrpi-updateコマンドで最新ファームを拾います。これをやるとファームウェア周りがdebパッケージ管理の道から逸れていくため、これ用にOSを用意したほうが良いです。
pi@raspberrypi:~ $ sudo BRANCH=next rpi-update
適用したらOSを再起動して、rpi-updateで適用されたLinuxカーネルのリビジョンと同じカーネルソースをダウンロードします。rpi-sourceというツールがあるのでこれを使ってダウンロードします。ダウンロード後は/home/pi/linuxでソースコードにアクセスできます。
pi@raspberrypi:~ $ sudo apt install -y rpi-source pi@raspberrypi:~ $ rpi-source
ドライバーをコンパイルしよう
わたしはLinuxカーネルコンパイル周りに明るくないので、menuconfigでちくちくと項目を見ていくことにします。
pi@raspberrypi:~/linux $ sudo apt install -y libncurses-dev pi@raspberrypi:~/linux $ make menuconfig
ネットワークドライバー周りは「Device Drivers」→「Network device support」→「Ethernet driver support」にありました。手元にはHP NC320TというBroadcomチップ採用のGbE NIC(tg3が必要)と、先日会社に行った時に廃品コーナーから持ってきたIntel PRO/1000 PT Desktopアダプター(e1000eが必要)があったので、それぞれ有効にします。Intelのは3つほどあってよくわからんかったのでとりあえず全部有効化して
- Intel(R) PRO/1000 Gigabit Ethernet support
- Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support
- Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support
Broadcomのドライバーは「Broadcom Tigon3 support」とわかりやすく1つだったのでこれを
コンパイルは全部やってると日が暮れる(と思いきやそうでもなさそうっぽいですが)ので、今有効にしたやつだけコンパイルしたいです。ぐぐったらどうもできそうだったので、以下の記事を参考にコンパイルしました。
ドライバーをコンパイルする前にmake modules_prepareを実行します。
pi@raspberrypi:~/linux $ make modules_prepare
まずはIntel。depmodに失敗してそうですが、なんか大丈夫そうです。depmodは手でやってみます。
pi@raspberrypi:~/linux $ cd drivers/net/ethernet/intel/e1000e pi@raspberrypi:~/linux/drivers/net/ethernet/intel/e1000e $ make -C /home/pi/linux M=`pwd` -j 4 (略) pi@raspberrypi:~/linux/drivers/net/ethernet/intel/e1000e $ sudo make -C /home/pi/linux M=`pwd` -j 4 modules_install make: Entering directory '/home/pi/linux-f77383ec0ed313e8ab19067065b423fb3e17ab82' INSTALL /home/pi/linux/drivers/net/ethernet/intel/e1000e/e1000e.ko DEPMOD 5.10.0-rc7-v7l+ Warning: modules_install: missing 'System.map' file. Skipping depmod. make: Leaving directory '/home/pi/linux-f77383ec0ed313e8ab19067065b423fb3e17ab82' pi@raspberrypi:~/linux/drivers/net/ethernet/intel/e1000e $ sudo depmod -a
同様にtg3もコンパイルします。
pi@raspberrypi:~/linux $ cd drivers/net/ethernet/broadcom pi@raspberrypi:~/linux/drivers/net/ethernet/intel/broadcom $ make -C /home/pi/linux M=`pwd` -j 4 (略) pi@raspberrypi:~/linux/drivers/net/ethernet/intel/broadcom $ sudo make -C /home/pi/linux M=`pwd` -j 4 modules_install make: Entering directory '/home/pi/linux-f77383ec0ed313e8ab19067065b423fb3e17ab82' INSTALL /home/pi/linux/drivers/net/ethernet/broadcom/tg3.ko DEPMOD 5.10.0-rc7-v7l+ Warning: modules_install: missing 'System.map' file. Skipping depmod. make: Leaving directory '/home/pi/linux-f77383ec0ed313e8ab19067065b423fb3e17ab82' pi@raspberrypi:~/linux/drivers/net/ethernet/intel/broadcom $ sudo depmod -a
コンパイルできたら、一旦電源を落として、まずはIntel PRO/1000 PT Desktopをスロットに差し込んで起動してみます。
Intel PRO/1000 PT Desktop
起動すると、オンボードNICのeth0と別に、eth1が生えて、IPアドレスが取得できていました。
pi@raspberrypi:~ $ ip a (略) 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:1b:21:**:**:** brd ff:ff:ff:ff:ff:ff inet 192.168.29.124/24 brd 192.168.29.255 scope global dynamic noprefixroute eth1 valid_lft 14261sec preferred_lft 12461sec
ethtoolコマンドで、eth1がIntelのNICが確認します。e1000eドライバーが読み込まれているのでIntelのNICですね。
pi@raspberrypi:~ $ ethtool -i eth1 driver: e1000e version: 5.10.0-rc7-v7l+ firmware-version: 5.11-10 expansion-rom-version: bus-info: 0000:01:00.0 supports-statistics: yes supports-test: yes supports-eeprom-access: yes supports-register-dump: yes supports-priv-flags: no
LANケーブルをIntelのNICだけにした状態で再起動してみても、IntelのNICを使ってSSH接続ができました。
iperf3を動かした結果はこのとおり。概ねギガビットの性能ですね。
[ ID] Interval Transfer Bitrate [ 5] 0.00-10.00 sec 1.02 GBytes 879 Mbits/sec receiver
HP NC320T
こちらはいきなりオンボードNICの接続無しでチャレンジ。再試しながらやっていたのでtg3ドライバーのコンパイルを忘れていてアクセスできないと焦りましたが、コンパイルして再起動したら無事に接続できました。
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:19:bb:**:**:** brd ff:ff:ff:ff:ff:ff inet 192.168.29.125/24 brd 192.168.29.255 scope global dynamic noprefixroute eth1
ドライバー情報。ちゃんとtg3ドライバーで動いていますね。
pi@raspberrypi:~ $ ethtool -i eth1 driver: tg3 version: 5.10.0-rc7-v7l+ firmware-version: 5721-v3.55a expansion-rom-version: bus-info: 0000:01:00.0 supports-statistics: yes supports-test: yes supports-eeprom-access: yes supports-register-dump: yes supports-priv-flags: no
こちらも一応iperf3で計測しました。こちらもちゃんとギガビット性能でした。
[ ID] Interval Transfer Bitrate [ 5] 0.00-10.00 sec 1.03 GBytes 881 Mbits/sec receiver
まとめ
Raspberry Pi Compute Module 4で、まずはGbE NIC2種類を動作させてみました。GbE NICはCM4本体に載っているので、わざわざPCIeデバイスで生やす必要がなく、動いても有りがたみは薄いのですが、普段PCやらサーバーに挿せば何も考えなくてもサクッと認識するメジャーすぎるデバイスをドライバーのコンパイルからやっていくというのは、なんというか大事なことだなあと思うなどしました。
さて、次は10GbE NIC、次はGPU、とポンポンいきたいところですが、どちらもいまのところうまくいっていないので、このへんが明日の記事になることはありません。残念。
他に手持ちのPCIeカードがそんなにないのであれですが、NVMe SSD変換あたりはちょっと用意できる状況になったので、明日はそのへんのチャレンジと記事化……までできるといいなと思っています。