2009/06/05(Fri)Realtek RTL8111がLinuxでうまく動かない件

2009/06/05 23:40 Software::Linux
MicroPC HTC-780という小型PCにCentOS5.3を導入しようとしたとき、どーもLANケーブルをつないだ瞬間にOSごと固まる(インストール中でも)ので、どうしたものか、といろいろ調べたときのメモ。
結論から言えば、ドライバに不具合があるようである。

準備

ここからはCentOS 5.3をオフラインインストールし、LANケーブルを抜いた状態でローカルログインしていることを前提にします。
該当のNICに関する情報は以下の通り。
$ lspci -v
(省略)
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 01)
        Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller
        Flags: bus master, fast devsel, latency 0, IRQ 16
        I/O ports at de00 [size=256]
        Memory at dfeff000 (64-bit, non-prefetchable) [size=4K]
        [virtual] Expansion ROM at dfc00000 [disabled] [size=128K]
        Capabilities: <access denied>
まず、ここでRTL8111/8168Bというモデルとして認識されていることを確認。
次に、ethtoolを使って該当ドライバとバージョンを確認。
$ ethtool -i eth0
driver: r8169
version: 2.3LK-NAPI
firmware-version:
bus-info: 0000:03:00.0
問題が起こるのはdriverがr8169かつ、versionが2.3LK-NAPIであることです。
前バージョンの2.2では問題は発生していません。
ちなみにr8169というドライバはRTL8111以外にも、RTL8169,RTL8110,RTL8102,RTL8168,RTL8101あたりもサポートしているようです。

パッチとカーネル再構築

まずはkernel.orgからフルソースをダウンロード。
The latest stable version of the Linux kernelってとこからFとかかれたリンクをダウンロードします。
たとえば、http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.4.tar.bz2
$ tar jxvf linux-2.6.29.4.tar.gz
$ cd linux-2.6.29.4/drivers/net/
で、問題を起こしているのはr8169.cの900行目のif文です。
((BEFORE))
 900     if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
 901         (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
 902         (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
この900行目のif文の第1要素を削除すれば解決。
((AFTER))
 900     if ((tp->mac_version == RTL_GIGA_MAC_VER_12) ||
 901         (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
というわけで、r8169.patchを使ってパッチを当てます。
$ patch < r8169.patch
patching file r8169.c

次に、カーネルの再構築。
現在のカーネルのconfigを引き継ぐため、コピーしてきます。
$ ls /boot/config*
config-2.6.18-128.el5    config-2.6.18-92.el5

$ cp /boot/config-2.6.18-92.el5 .config

$ make oldconfig

(いろいろずらずら出るので、必要に応じて組み込むものを選んだり…。)
(特にこだわらない人はEnter連打でOK)

#
# configuration written to .config
#

$ make bzImage
(コア数に応じて2コアなら-j2、4コアなら-j4とかすると良いらしい)

$ make modules
(これも同様に-jをつけられる)

$ sudo su -

# make modules_install

# make install

$ make clean
こんな感じで。
/bootに独自ビルドした、System.map-2.6.~、config-2.6.~、initrd-2.6.~、vmlinuz-2.6.~ができていればOK。
/boot/grub/menu.lstにもブートレコードの先頭に先ほどビルドしたものが追加されているはず。