おせわになります。もう といいます。
今、当社設計RZカスタムボードにてLinuxを組み込もうとしています。
ポーティングマニュアルに従い、BSP1.3.0をポーティングし、Linuxはブートできているのですが、
pingコマンドにてWindowsPC-カスタムボード間LAN通信でパケットロスが10~20%ぐらい発生してしまいます。
RSKボードなど評価ボードと比較してLAN関連で異なる部品といえば、
・PHYがTI社のDP83848Kであること。
・PHYのアドレスが1番であること
ぐらいです。
パケットロスの原因を調査するため、Linuxイーサネットドライバのsh_eth.c(関数sh_eth_rx)を調べると
受信ディスクリプタRD0のRACT、RDLEが0のとき、
受信フレーム位置(RFP1、RFP2)が00となっており、
また、そのときRFEビットは0なのに、RFS9、RFS4のビットが1となっています。
(受信FIFOオーバフロー、端数ビットフレーム受信エラー)
RFS9、RFS4のビットが立っているため、フレーム異常として破棄されて
パケットロスとなっているみたいです。
ハード要因も疑いましたが、PHY-CPU間の通信波形には異常が見られずお手上げ状態です。
なにか調査すべき点、考えられる原因ありませんでしょうか?
もう さん
> pingコマンドにてWindowsPC-カスタムボード間LAN通信でパケットロスが10~20%ぐらい発生してしまいます。
もう少し詳しく、機器構成や実験方法を教えていただけますか?上の文を素直に読むと「Windows から Windows の ping コマンドでカスタムボードの RZ/A1 Linux にping すると...」となるのですが、1秒に1回程度の ping で 10~20%のパケットロス?ですか?また、Windows PC のイーサネットカード/コントローラ、ping コマンドに指定したオプション、等々もお願いします。
> パケットロスの原因を調査するため、Linuxイーサネットドライバのsh_eth.c(関数sh_eth_rx)を調べると ~中略~> パケットロスとなっているみたいです。
RZ/A1 と PHY 間は、RMII ではなく MII で接続されていますね?RZ/A1 Linux 上で ethtool や miitool を使って、オートネゴシエーションを再実行し、インタフェースの状態を表示してみてください。同じく ping の実験後、netstat や ifconfig で受信エラーが出ていることを確認してください。
御社と同様な printk を加えたドライバを使い、flood ping でネットワークに負荷をかけたり、意図的にCPUやバスに負荷をかけたり、ケーブルを抜き差ししたり、意図的に CRCエラーのパケットを送ってみたりと、色々と試してみて、(ifconfig で表示できる) 一通りの受信エラーを起こしてみましたが、
RX packets:55780 errors:408 dropped:32 overruns:408 frame:912
当方の環境では、ご提示のようなエラー
Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:28
が出ることは、ありませんでした(当方では、RD0 は、3000 か 7000)。
また、御社と類似した事例があるか確認してみましたが、ありませんでした。
ですので、現時点では、御社のボード(ハードウェア要因)に問題があるのでは?と考えています。
念のため、上のエラー表示、特に RD0 の値が正しく表示出来ているか、今一度、ソースをご確認ください(RFE がセットされないのが不思議です)。
また、可能でしたら、接続機器を変える(ケーブル/ハブ/スイッチを交換してみる、ケーブルで直結する、ダムハブ/スイッチで中継する、など)、あるいは、ethtool などでリンク速度や全二重/半二重などを変えてみる、で状況が変わるか確認してみてください。
> printk("Read RD0:%X RD1(Flame):%X RD1(Buffer):%X entry:%d\n", desc_status,dec_flength, dec_blength, entry);> にて表示しています。そちらで表示された状況と同じでしょうか?
最初は、御社同様、if の then 節に置いたのですが、何も出ないので、最終的に if の前に置いた以外は、ほぼ同じです。
printk("Read RD0:%04x, RD1(Flame):%04x RD1(Buffer):%04x entry:%d\n", desc_status, rxdesc->frame_length, rxdesc->buffer_length, mdp->cur_rx);
> ご指摘のようにRFEはセットされていないので、実はエラーではなかったりすると> うれしいのですが、RD0のRACT、RDLE、RFP1、RFP0が全部0となることは> ありえないのかなと思います。(あってますか?)> 全部0となる状況ってどんな場合なのでしょうか?
このドライバ自体は、GbE のコントローラ"も"サポートしていますから、例えば、ジャンボフレームを受信した場合には、複数のバッファに分割して保存することになり、RFP が 00/01/10 の場合もあるのでしょう。
> GenericPHYを使用する場合、なにか気をつける点とかはないでしょうか?
基本、標準(共通)のレジスタ/ビットを操作するだけですから、PHY が特殊な機能をデフォルトにしていない限り、問題はないはずです。
もし、MAC-PHY 間は大丈夫そうとの感触をお持ちならば、RJ45-PHY 間を疑うのも1つかもしれません。その場合、PHY の拡張レジスタに役立つものがあるかもしれません。
> RD0、RD1などを受信ディスクリプタのコピーはDMAが行っていると思いますが> なにか設定間違いなどありえますか?(Linuxドライバそのまま使用していますが) (中略)> バスステートコントローラはSD-RAMを32ビットとして設定はしているつもりですが> 本件のような不具合発生が関連する可能性はないでしょうか?
RZ/A1 の内部バスの構成を考え合わせると、設定間違いや不具合があるとしたらイーサネットコントローラではなくバスステートコントローラの方でしょう。
タグに RZ/A1H とありますが、現状、内蔵 RAM に 1KB の空きがありますか?受信ディスクリプタを外部 SDRAM から内蔵 RAM に移動して、不具合が修正されるか試してみてください。
内蔵 RAM に確保した 1 KB の領域の先頭物理アドレスを 0x20XXXXXX とすると、Github の最新ソースの drivers/net/ethernet/renesas/sh_eth.c で
1190 static int sh_eth_ring_init(struct net_device *ndev) 1191 { 1192 struct sh_eth_private *mdp = netdev_priv(ndev); 1193 int rx_ringsize, tx_ringsize, ret = 0; (中略) 1220 /* Allocate all Rx descriptors. */ 1221 rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; - 1222 mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, - 1223 GFP_KERNEL); + BUG_ON(rx_ringsize > (16 * 64)); + mdp->rx_ring = ioremap_uncache(0x20XXXXXX, rx_ringsize); 1224 if (!mdp->rx_ring) { 1225 ret = -ENOMEM; 1226 goto desc_ring_free; 1227 } (中略) 1241 desc_ring_free: 1242 /* free DMA buffer */ - 1243 dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma); + iounmap(mdp->rx_ring); 1244 (中略) 1254 static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp) 1255 { 1256 int ringsize; 1257 1258 if (mdp->rx_ring) { 1259 ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; - 1260 dma_free_coherent(NULL, ringsize, mdp->rx_ring, - 1261 mdp->rx_desc_dma); + iounmap(mdp->rx_ring); 1262 mdp->rx_ring = NULL;
のように修正してください。# 試していませんが。
なお、確保する領域は、1 KB だったと思いますが、もし足りなければ、BUG_ON() が呼ばれますから、増やしてください。
> 修正して試してみました。(ioremap_uncacheだとエラーになるので、ioremap_nocacheにしてmakeしました。あってますか?)
私の勘違いです。ioremap_nocacheで正しいです。
前半は、確認してから回答するとして、とりあえず、後半だけ回答します。
> あと、別件ですが、前の返信を見ていただくとわかりますが、RD1の受信バッファサイズの値が> 0x610で表示されているのですが、RZ/A1Hのハードウェアマニュアルを見ると、> RBLの値は、32バイト境界で指定とあります。> 0x610だと32で割り切れません。
最初、受信バッファサイズに32バイト境界?と思ったのですが、確認してみると、確かにハードウェアマニュアルにそのように記載されていますね。推測ですが、E-DMACが受信フレームを32バイト単位で転送するため、最後にゴミが付く場合があり、それを心配して、こうした記述になったのでしょう。RBLは、0x610 で正しい(ドライバの記述通り)です。また、イーサネットの最大フレーム長は、1518バイトで、VLANタグを含めても、1522バイト(=0x5F2)ですから、転送サイズが 0x600を超えることは、通常、ありません。
これで回答になっていますか?
まだ、未確認ですが、私の投稿したソースを見る限り、mdp->rx_desc_dma への代入を忘れていました。
- 1222 mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, - 1223 GFP_KERNEL); + BUG_ON(rx_ringsize > (16 * 64)); + mdp->rx_desc_dma = 0x20XXXXXX; + mdp->rx_ring = ioremap_nocache(mdp->rx_desc_dma, rx_ringsize);
これでは、全然、動かないです。申し訳ありません。
上の修正したコードで、RSK ボードでの動作を確認しました。受信ディスクリプタは、0x209ff000 以降に割り当てています。
Welcome to Buildrootbuildroot login: root # cat /proc/iomem00000000-03ffffff : physmap-flash.1 00000000-03ffffff : physmap-flash.108000000-09ffffff : System RAM 08008000-0805ff5f : Kernel data18000000-1bffffff : physmap-flash.0 18000000-1bffffff : physmap-flash.0 ... (snip) # ping 192.168.0.253PING 192.168.0.253 (192.168.0.253): 56 data bytes64 bytes from 192.168.0.253: seq=0 ttl=128 time=0.000 ms64 bytes from 192.168.0.253: seq=1 ttl=128 time=0.000 ms ... (snip)64 bytes from 192.168.0.253: seq=25 ttl=128 time=0.000 ms64 bytes from 192.168.0.253: seq=26 ttl=128 time=0.000 ms --- 192.168.0.253 ping statistics ---27 packets transmitted, 27 packets received, 0% packet lossround-trip min/avg/max = 0.000/0.000/0.000 ms # ./mem r l 0x209ff000 0x410209ff000: b0000000 06100156 0927dea0 00000000209ff010: b0000000 0610003c 0927e5e0 00000000 ... (snip)209ff3e0: b0000000 06100000 0927d020 00000000209ff3f0: f0000000 06100000 0927d760 00000000209ff400: 63922f63 418775e1 24bca11e b1998f06#
大丈夫だと思いますので、これで試してみてください。
もう です。 RD1の32ビット境界の件、回答ありがとうございました。また、 わかりやすく説明いただきありがとうございました。 実用上は問題ないこと、了解いたしました。 でも、ハードウェアマニュアルに、「32ビット境界で指定」と書いてあるからには、 0x600(余裕を見るなら0x620)にすべきとは思うですが・・・・。 でも今回のエラーと関係なさそうですし深堀やめときます。