zoukankan      html  css  js  c++  java
  • Ambarella 平台KSZ9031网卡直连不识别问题

    问题描述:

      两个ambarella peanut板子的网口之间用网线直连,会发现不能自动协商成功(网口灯不亮),但是ambarella peanut板子的网口和其他X86 Linux机器网口直连可以协商成功(网口灯亮)。

      对于想使用peanut板子网口作LAN口,给其他peanut 板子DHCP分配IP地址会失败。

    问题分析

      1. 查看ambarella peanut平台驱动 kernel/linux-4.4/drivers/net/ethernet/ambarella/ambarella_eth.c  对网卡芯片 KSZ9031 做了哪些 MDIO 读写,关于MDIO定义看此篇博客:MDC/MDIO接口定义

    static int ambhw_mdio_write(struct mii_bus *bus,
            int mii_id, int regnum, u16 value)
    {
            int ret_val = 0;
            struct ambeth_info *lp;
            int val;
            int cnt = 0;
    
            lp = (struct ambeth_info *)bus->priv;
    
            printk("MII Write: reg[0x%.2x], val[0x%.4x].
    ",
                            regnum, value); //添加的打印MDIO写了哪些寄存器,写了哪些值
            if (netif_msg_hw(lp))
                    dev_info(&lp->ndev->dev,
                            "MII Write: id[0x%02x], add[0x%02x], val[0x%04x].
    ",
                            mii_id, regnum, value);
    
            for (cnt = AMBETH_MII_RETRY_CNT; cnt > 0; cnt--) {
                    val = readl_relaxed(lp->regbase + ETH_MAC_GMII_ADDR_OFFSET);
                    if (!(val & ETH_MAC_GMII_ADDR_GB))
                            break;
                    udelay(10);
            }
            if ((cnt <= 0) && netif_msg_hw(lp)) {
                    dev_err(&lp->ndev->dev, "MII Error: Prewrite tmo!
    ");
                    ret_val = -EIO;
                    goto ambhw_mdio_write_exit;
            }
    
            val = value;
            writel_relaxed(val, lp->regbase + ETH_MAC_GMII_DATA_OFFSET); //把要写到网卡芯片寄存器的值写到ambarella SoC芯片的 lp->regbase+ETH_MAC_GMII_DATA_OFFSET 寄存器里
            val = ETH_MAC_GMII_ADDR_PA(mii_id) | ETH_MAC_GMII_ADDR_GR(regnum);
            val |= ETH_MAC_GMII_ADDR_CR_250_300MHZ | ETH_MAC_GMII_ADDR_GW |
                    ETH_MAC_GMII_ADDR_GB;
            writel_relaxed(val, lp->regbase + ETH_MAC_GMII_ADDR_OFFSET); //给lp->regbase+ETH_MAC_GMII_ADDR_OFFSET写入一些flag(包括要写入的网卡芯片寄存器的地址)触发 lp->regbase+ETH_MAC_GMII_DATA_OFFSET 里的值写入到网卡芯片相关寄存器里
    
            for (cnt = AMBETH_MII_RETRY_CNT; cnt > 0; cnt--) {
                    val = readl_relaxed(lp->regbase + ETH_MAC_GMII_ADDR_OFFSET);
                    if (!(val & ETH_MAC_GMII_ADDR_GB))
                            break;
                    udelay(10);
            }
            if ((cnt <= 0) && netif_msg_hw(lp)) {
                    dev_err(&lp->ndev->dev, "MII Error: Postwrite tmo!
    ");
                    ret_val = -EIO;
                    goto ambhw_mdio_write_exit;
            }
    
    ambhw_mdio_write_exit:
            return ret_val;
    }

    修改后发现打印信息如下:

    MII Write: reg[0x00], val[0x8000].
    MII Write: reg[0x0d], val[0x0002].
    MII Write: reg[0x0e], val[0x0008].
    MII Write: reg[0x0d], val[0x4002].
    MII Write: reg[0x0d], val[0x0002].
    MII Write: reg[0x0e], val[0x0008].
    MII Write: reg[0x0d], val[0x4002].
    MII Write: reg[0x0e], val[0x3df6].
    MII Write: reg[0x0d], val[0x0002].
    MII Write: reg[0x0e], val[0x0004].
    MII Write: reg[0x0d], val[0x4002].
    MII Write: reg[0x0d], val[0x0002].
    MII Write: reg[0x0e], val[0x0004].
    MII Write: reg[0x0d], val[0x4002].
    MII Write: reg[0x0e], val[0x0027].
    MII Write: reg[0x0d], val[0x0002].
    MII Write: reg[0x0e], val[0x0005].
    MII Write: reg[0x0d], val[0x4002].
    MII Write: reg[0x0e], val[0x2222].
    MII Write: reg[0x0d], val[0x0000].
    MII Write: reg[0x0e], val[0x0004].
    MII Write: reg[0x0d], val[0x4000].
    MII Write: reg[0x0e], val[0x0006].
    MII Write: reg[0x0d], val[0x0000].
    MII Write: reg[0x0e], val[0x0003].
    MII Write: reg[0x0d], val[0x4000].
    MII Write: reg[0x0e], val[0x1a80].
    MII Write: reg[0x00], val[0x1340].
    MII Write: reg[0x00], val[0x1140].
    MII Write: reg[0x09], val[0x0300].
    MII Write: reg[0x09], val[0x1300].

      对照KSZ9031 datasheet比较下来,导致问题的可疑之处定位在 MII Write: reg[0x09], val[0x1300] 上面。

       本来09H的第12位网卡默认值为0的,但被设置为1了,从哪个位置设置的呢?

      2. 为了找到在哪个地方把09H的第12位设置为1的,我找到了kernel source code里的 kernel/linux-4.4/drivers/net/phy/micrel.c ,这个驱动是microchip系列网卡芯片相关寄存器配置的地方,找到如下函数:

    static int ksz9031_config_aneg(struct phy_device *phydev)
    {
            u32 val;
    
            genphy_config_aneg(phydev);
    
            /* Set auto Master/Slave resolution process */
            val = phy_read(phydev, MII_CTRL1000);
            val |= 0x1000; // MII_CTRL1000宏的值就是0x9,需要把此行注释掉
            val &= ~(0x0800);
            phy_write(phydev, MII_CTRL1000, val);
    
            return 0;
    }

    原来是在这里设置的 Enable master-slave manual configuration ,Microchip提供到kernel里的网卡驱动让ambarella修改了,注释掉  val |= 0x1000; 这一行,重新编译进内核或者编译成模块,问题解决。

    拓展

      这个问题的根本原因就是两个peanut板子都设置成了 使能手动主从控制,导致用网线直连两个网卡不能自动协商,其中有一个peanut板子 Disable master-slave manual configuration 都不会有这个问题, peanut板子与其他X86主板的连接也没有这个问题;

      在问题发生后,给其中一个peanut板子的网口接到交换机上,正常识别后再拔掉网线会导致网卡 MDIO 配置的复位(9H寄存器的第12位恢复默认值0),这时候再用网线直连两个peanut板子,是可以正常协商成功的。

      虽然这个问题解决了,但还是不知道ambarella原厂为啥做这样的修改,在其他ambarella SoC平台里用的Realtek网卡芯片ambarella没有做类似的修改,是为了修复什么bug? 在咨询过microchip FAE后,得到的回复是千兆自动协商有时会遇到兼容性问题,例如某些千兆设备的连接,发现要在slave模式,或者必须工作在master模式,不然工作不稳定。

  • 相关阅读:
    [macOS] git忽略所有的.DS_Store文件
    [macOS] finder变慢提速
    [React Native] change port when running react native
    转载: 我如何使用 Django + Vue.js 快速构建项目
    MySQL Connector/NET 使用小结(踩坑之路)
    C# 控制台程序(Console Application )启动后隐藏
    解决 pycharm can not save setting
    ubuntu 16.04 LTS 安装 teamviewer 13

    Python 编程规范梳理
  • 原文地址:https://www.cnblogs.com/wanglouxiaozi/p/13903840.html
Copyright © 2011-2022 走看看