LinuxBSP1.3.0でのLAN通信

おせわになります。もう といいます。

 

今、当社設計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 で受信エラーが出ていることを
    確認してください。

  • お返事ありがとうございます。
    もう です。

    pingコマンドの実行ですが、カスタムボード(シリアルターミナル)上から
    WindowsPCに対しpingをかけています。
    オプションはなしで、IPアドレス指定のみです。
    linux側pingはコントロール+Cをしないと連続してpingする状態になりますので
    適当なタイミング(20秒ぐらい)でコントロール+Cでとめています。
    その結果、たとえば下記①のように「22% packet loss」となってしまいます。
    下記①の結果で、途中途中で出てくる
    Read RD0:610 RD1(Flame):3C RD1(Buffer):610 entry:XX
    は、エラーがあった際、printkで受信ディスクリプタを表示するように改造しています。
    (RD0、RD1のフレームサイズ、バッファサイズ、リングバッファカウンタ番号)
    カスタムボードの相手ですが、違うPCにしたり、カスタムボード同士にしたりしても
    発生状況に顕著な違いはありませんでした。
    Windowsからpingを-tオプションで実行した場合は、たまに
    「要求がタイムアウトしました」
    と出てやはり損失がでます。たとえば「損失2(5%)」とか。
    ただなんとなくですが、Windowsからのpingのほうがlossは小さいような気がします。

    ②はethtool実行した結果です。mii、オートネゴシエーションは設定されていると
    思います。また、PHYのステータスレジスタを直接読んでもみましたが
    特に変な設定になっていることはありませんでした。

    ifconfigを実行した結果では、
    RX packets:76 errors:11 dropped:0 overruns:0 frame:33
    みたいに受信でやはりerrorがカウントされています。
    送信側はerrorは0です。

    netstat実行した結果が③ですが、すいませんどう読んでいいのか不勉強です。
    No such file or directoryとあり、なにかおかしいのでしょうか?

    -結果-----------------------------
    ①カスタムボードからWindowsPCへのping結果
    $ ping 192.168.2.80
    PING 192.168.2.80 (192.168.2.80): 56 data bytes
    Read RD0:610 RD1(Flame):3C RD1(Buffer):610 entry:62
    64 bytes from 192.168.2.80: seq=0 ttl=128 time=1000.000 ms
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:1
    64 bytes from 192.168.2.80: seq=2 ttl=128 time=0.000 ms
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:3
    64 bytes from 192.168.2.80: seq=4 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=5 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=6 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=7 ttl=128 time=0.000 ms
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:12
    64 bytes from 192.168.2.80: seq=9 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=10 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=11 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=12 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=13 ttl=128 time=0.000 ms
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:18
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:19
    64 bytes from 192.168.2.80: seq=16 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=17 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=18 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=19 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=20 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=21 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=22 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=23 ttl=128 time=0.000 ms
    Read RD0:610 RD1(Flame):62 RD1(Buffer):610 entry:28
    64 bytes from 192.168.2.80: seq=25 ttl=128 time=0.000 ms
    64 bytes from 192.168.2.80: seq=26 ttl=128 time=0.000 ms
    ^C
    --- 192.168.2.80 ping statistics ---
    27 packets transmitted, 21 packets received, 22% packet loss
    round-trip min/avg/max = 0.000/47.619/1000.000 ms
    ----------------------------
    ②ethtool実行結果
    $ ethtool eth0
    Settings for eth0:
    Supported ports: [ TP AUI BNC MII FIBRE ]
    Supported link modes: 10baseT/Half 10baseT/Full
    100baseT/Half 100baseT/Full
    Supported pause frame use: No
    Supports auto-negotiation: Yes
    Advertised link modes: 10baseT/Half 10baseT/Full
    100baseT/Half 100baseT/Full
    Advertised pause frame use: No
    Advertised auto-negotiation: Yes
    Link partner advertised link modes: 10baseT/Half 10baseT/Full
    100baseT/Half 100baseT/Full
    Link partner advertised pause frame use: Symmetric
    Link partner advertised auto-negotiation: Yes
    Speed: 100Mb/s
    Duplex: Full
    Port: MII
    PHYAD: 1
    Transceiver: external
    Auto-negotiation: on
    Current message level: 0x000000cc (204)
    link timer rx_err tx_err
    Link detected: yes

    ----------------------------
    ③netstat実行結果
    $ netstat
    Active Internet connections (w/o servers)
    Proto Recv-Q Send-Q Local Address Foreign Address State
    netstat: /proc/net/tcp6: No such file or directory
    netstat: /proc/net/udp6: No such file or directory
    netstat: /proc/net/raw6: No such file or directory
    Active UNIX domain sockets (w/o servers)
    Proto RefCnt Flags Type State I-Node Path
    unix 3 [ ] DGRAM 616 /dev/log
    unix 2 [ ] DGRAM 620
  • もう さん

    御社と同様な 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 などでリンク速度や全二重/半二重などを変えてみる、で状況が変わるか
    確認してみてください。

  • 検討ありがとうございます。

    RD0の表示ですが、sh_eth_rx関数内で、

    if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
    RD_RFS5 | RD_RFS7 | RD_RFS10)) {

    (オリジナルは、
    if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
    RD_RFS5 | RD_RFS6 | RD_RFS10)) {
     となっていますが、RD_RFS6 判定は間違っていると思いますので
     修正しています。)

    が成立したら、

    オリジナルでプログラムされている、desc_status、entry
    と、私が勝手に定義した

    dec_flength = edmac_to_cpu(mdp, rxdesc->frame_length);
    dec_blength = edmac_to_cpu(mdp, rxdesc->buffer_length);

    を使用して

    printk("Read RD0:%X RD1(Flame):%X RD1(Buffer):%X entry:%d\n", desc_status,dec_flength, dec_blength, entry);

    にて表示しています。そちらで表示された状況と同じでしょうか?

    確かにこちらでも正常な場合もRD0を表示すると、RD0 は3000 で、
    たまに頭がBになることはありますが、
    これは、未送信ということで正常なのかなと思っています。

    異常な場合、ほとんどは、RD0表示610となります。
    ご指摘のようにRFEはセットされていないので、実はエラーではなかったりすると
    うれしいのですが、RD0のRACT、RDLE、RFP1、RFP0が全部0となることは
    ありえないのかなと思います。(あってますか?)
    全部0となる状況ってどんな場合なのでしょうか?

    また、ごくごくたまにですが、RFEが立つ場合もあります。
    このときは、RFSのビットはほとんど立った状態となるので、
    やはり異常となることがあるのだと考えています。

    接続機器は、先日ご回答したとおりいろいろ変えてみていますが、
    状況は変わりません。
    また、ハブを使わず直結も試していますが、かわりません。
    半二重設定は試してみます。

    あとPHYの全レジスタを表示したりして設定に間違いがないか
    再度確認してみます。
    PHYはTI社のDP83848Kを使用していますが、ブート時、Generic PHYとして
    認識されています。

    sh-eth r7s72100-ether eth0: attached PHY 1 (IRQ -1) to driver Generic PHY
    libphy: r7s72100-ether-f:01 - Link is Up - 100/Full

    TI社ではlinuxのドライバが提供(下記アドレス)されており、
    内容見たのですが割り込みの設定があるだけで、
    今回使用するDP83848Kでは意味のない
    (DP83848Kには割り込みピンがない)ものなので使用していません。
    GenericPHYを使用する場合、なにか気をつける点とかはないでしょうか?

    git.kernel.org/.../dp83848.c
  • > 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 の拡張レジスタに役立つものがあるかもしれません。

  • 回答ありがとうございます。
    いろいろご面倒おかけしてすいません。

    > このドライバ自体は、GbE のコントローラ"も"サポートしていますから、例えば、ジャンボフレームを
    >受信した場合には、複数のバッファに分割して保存することになり、RFP が 00/01/10 の場合も
    >あるのでしょう。

    今回については、1フレーム(ping実行時はたぶん98バイト)はバッファサイズ(1552バイト)なので
    十分1つに収まるはずなので、やはり、00はありえないですよね。
    (複数のバッファに分割されるはずはない)

    教えていただいたとおり、PHYのレジスタを拡張レジスタも含め確認してみます。
  • もう です。

    いまだLAN通信がうまくいかないのですが、いろいろ調べていて
    受信ディスクリプタRD0がちゃんと受信ができていないことに気がつきました。
    下記のように、pingのサイズを変えると、エラー時のRD0(データの頭が610のとき)の
    下位データがRD1(Flame)と同じ数字にかわります。
    RD0のデータがなぜかRD1のデータで上書きされてしまっているようです。
    ※下記はRD_RFS1~10のフラグが立っていても無視するよう改造しpingを継続実行

    $> ping 192.168.2.80
    PING 192.168.2.80 (192.168.2.80)
    Read RD0:6100062 RD1(Flame):62 RD1(Buffer):610 entry:1   <-------RD0とRD1が同じ
    64 bytes from 192.168.2.80: seq=0 ttl=128 time=15.625 ms
    Read RD0:6100062 RD1(Flame):62 RD1(Buffer):610 entry:2   <-------RD0とRD1が同じ
    64 bytes from 192.168.2.80: seq=1 ttl=128 time=7.813 ms

    $> ping -s 500 192.168.2.80
    PING 192.168.2.80 (192.168.2.80): 500 data bytes
    Read RD0:610021E RD1(Flame):21E RD1(Buffer):610 entry:40  <-------RD0とRD1が同じ
    508 bytes from 192.168.2.80: seq=1 ttl=128 time=7.812 ms
    Read RD0:30000000 RD1(Flame):62 RD1(Buffer):610 entry:3
    64 bytes from 192.168.2.80: seq=2 ttl=128 time=7.812 ms

    $> ping -s 1000 192.168.2.80
    PING 192.168.2.80 (192.168.2.80): 1000 data bytes
    Read RD0:30000000 RD1(Flame):412 RD1(Buffer):610 entry:57
    1008 bytes from 192.168.2.80: seq=0 ttl=128 time=23.438 ms
    Read RD0:6100412 RD1(Flame):412 RD1(Buffer):610 entry:58  <-------RD0とRD1が同じ
    1008 bytes from 192.168.2.80: seq=1 ttl=128 time=7.813 ms

    RD0、RD1などを受信ディスクリプタのコピーはDMAが行っていると思いますが
    なにか設定間違いなどありえますか?(Linuxドライバそのまま使用していますが)

    またイーサネット関連以外のRSK等評価ボードとの違いで、当社ボードは
    SD-RAMのバス幅が32ビットであることもちょっと気になってはいます。
    バスステートコントローラはSD-RAMを32ビットとして設定はしているつもりですが
    本件のような不具合発生が関連する可能性はないでしょうか?

    お手数おかけしてすいません。
    よろしくおねがいします。
  • > 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しました。あってますか?)
    内蔵RAMは、u-bootでしか使っていないため、どこを指定しても問題ないと思いますので
    0x20400000としました。

    結果、全く通信できません。

    sh-eth r7s72100-ether eth0: Receive Descriptor Empty

    のエラーが出てとまってしまうか、pingができても、結果100%lossとでるので
    受信処理がうまくできていなさそうです。

    あと、別件ですが、前の返信を見ていただくとわかりますが、RD1の受信バッファサイズの値が
    0x610で表示されているのですが、RZ/A1Hのハードウェアマニュアルを見ると、
    RBLの値は、32バイト境界で指定とあります。
    0x610だと32で割り切れません。
    正しく設定できているのでしょうか?
  • > 修正して試してみました。(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を超えることは、通常、ありません。

    これで回答になっていますか?