使用的是linux3.2.0的内核,这是内核中网卡状态机的工作状态
- enum phy_state {
- PHY_DOWN = 0, // PHY芯片和驱动没准备好,一般情况下少发生
- PHY_STARTING, // PHY芯片OK了,但驱动还没有准备好
- PHY_READY, // 准备好了,在probe中赋值,接下来会切到PHY_UP
- PHY_PENDING,
- PHY_UP, // phy启动了,可以工作了,接下来会到PHY_AN
- PHY_AN, // 自动协商
- PHY_RUNNING, // 正在运行中,在网络连接(插上网线)时会到这个状态
- PHY_NOLINK, // 断网了
- PHY_FORCING, // 强制,当自动协商不使能时,就会进行此状态(实际上会读PHY寄存器进行设置速率、双工,等)
- PHY_CHANGELINK, // 变化,这个状态很重要,当连接时,会换到PHY_RUNNING,当断网时,会切到PHY_NOLINK
- PHY_HALTED,
- PHY_RESUMING
- };
使用过程中发现,当网线从网口中拔出来后,状态机会进入PHY_NOLINK状态,但是再将网线插入,会检测不到网线的插入,状态机依然是PHY_NOLINK状态,
多插拔几次,有时候会进入PHY_RUNNING的正常状态,
跟踪函数发现:void phy_state_machine(struct work_struct *work)
- case PHY_NOLINK:
- err = phy_read_status(phydev); // 读phy状态,包括link,速率、双工,等等
- if (err)
- break;
- if (phydev->link) { // 在断开网络再连接(即拨掉再插上网线),就进入此语句
- if (AUTONEG_ENABLE == phydev->autoneg) {
- err = phy_aneg_done(phydev); // 如果是自动协商使能,就进行自动协商
- if (err < 0)
- break;
- if (!err) {
- phydev->state = PHY_AN;
- phydev->link_timeout = PHY_AN_TIMEOUT;
- break;
- }
- }
- phydev->state = PHY_RUNNING; // 运行时。。。。。
- netif_carrier_on(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
- }
- break;
phy_read_status(phydev)此函数读取到的phydev->link状态,插着网线也读取不到插入状态,是不是我哪个寄存器设置的有问题?还是硬件电路有问题?
Jian Zhou:
MDIO读取PHY芯片寄存器正常么?
如果正常,可能需要检查PHY这部分的硬件设计。