PHY的12种状态

  1. enum phy_state {
  2. PHY_DOWN = 0, //关闭网卡
  3. PHY_STARTING, //PHY设备准备好了,PHY driver尚为准备好
  4. PHY_READY, //PHY设备注册成功
  5. PHY_PENDING, //PHY芯片挂起
  6. PHY_UP, //开启网卡
  7. PHY_AN, //网卡自协商
  8. PHY_RUNNING, //网卡已经插入网线并建立物理连接,该状态可切换到PHY_CHANGELINK
  9. PHY_NOLINK, //断网,拔掉网线
  10. PHY_FORCING,//自动协商失败,强制处理(读phy状态寄存器,设置速率,设置工作模式)
  11. PHY_CHANGELINK, //LINK检查,当物理连接存在时切换到PHY_RUNING,物理连接不存在时切换到PHY_NOLINK
  12. PHY_HALTED, //网卡关闭时,PHY挂起
  13. PHY_RESUMING //网卡开启时,PHY恢复
  14. };

PHY状态机



PHY指PHY芯片,负责数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口。

MAC指MAC芯片,属于数据链路层,提供寻址机构、数据帧的构建、数据差错检查、传送控制、向网络层提供标准的数据接口等功能。

PHY_DOWN: phy、phy driver、mac都没准备好

  1. 如果phy driver被集成在内核中,PHY.probe后,phydev状态为PHY_READY。
  2. 如果phy driver被未集成在内核中,PHY.probe后,phydev状态为PHY_STARTING。

PHY_READY:phy、phy driver已经就绪,mac未准备好

当MAC层加载时,在PHY.start后,phydev状态切换为PHY_UP。

PHY_STARTING:phy准备就绪,phy driver、mac未准备好

  1. 当MAC加载时,PHY.start后,phydev状态为PHY_PENDING。
  2. 当phy driver加载时,phydev状态为PHY_READY。

PHY_PENDING:phy、mac准备就绪,phy driver未准备好

当phy dirver加载后,phdev状态为PHY_UP

上图中0-->1-->2-->4、0-->2-->4代表phy、phy dirver、mac顺序加载。

0-->1-->3-->4代表phy、mac、phy driver顺序加载。

PHY_UP:phy、phy driver、mac准备就绪

当前状态将启动自动协商,若启动成功则进入PHY_AN,若启动失败则进入PHY_FORCING。

PHY_AN:网卡自协商模式,检测自协商是否完成。

先判断物理链路的状态,如果未LINK则进入PHY_NOLINK,如果LINK则判断自协商是否完成,

自协商完成进入PHY_RUNNING,若自协商超时则重新开启自协商。

PHY_FORCING:强制协商

读link和自协商状态寄存器,如果状态正常则进入PHY_RUNNING模式。

PHY_NOLINK:物理链路未连接

判断物理链路状态,如果LINK,再判断是否支持自协商,若支持待自协商完成后进入PHY_RUNNING模式,

若不支持,直接进入PHY_RUNNING模式。若自协商处于挂起状态,则进入PHY_AN模式。

PHY_RUNNING:正常运行中

获取当前link状态,当link状态发生改变时,进入PHY_CHANGELINK模式。

PHY_CHANGELINK:检查物理链路

物理链路link时,切换到PHY_RUNNING,非LINK时切换到PHY_NOLINK。

PHY_HALTED:网卡关闭phy_stop

挂起phy

PHY_RESUMING: 网卡启用phy_start

恢复phy

phy_state_machine是PHY的状态机函数

  1. /**
  2. * phy_state_machine - Handle the state machine
  3. * @work: work_struct that describes the work to be done
  4. */
  5. void phy_state_machine(struct work_struct *work)
  6. {
  7. struct delayed_work *dwork = to_delayed_work(work);
  8. struct phy_device *phydev =
  9. container_of(dwork, struct phy_device, state_queue);
  10. bool needs_aneg = false, do_suspend = false;
  11. enum phy_state old_state;
  12. int err = 0;
  13. int old_link;
  14. mutex_lock(&phydev->lock);
  15. old_state = phydev->state;
  16. if (phydev->drv->link_change_notify)
  17. phydev->drv->link_change_notify(phydev);
  18. switch (phydev->state) {
  19. case PHY_DOWN:
  20. case PHY_STARTING:
  21. case PHY_READY:
  22. case PHY_PENDING:
  23. break;
  24. case PHY_UP:
  25. needs_aneg = true;
  26. phydev->link_timeout = PHY_AN_TIMEOUT;
  27. break;
  28. case PHY_AN:
  29. err = phy_read_status(phydev);
  30. if (err < 0)
  31. break;
  32. /* If the link is down, give up on negotiation for now */
  33. if (!phydev->link) {
  34. phydev->state = PHY_NOLINK;
  35. netif_carrier_off(phydev->attached_dev);
  36. phydev->adjust_link(phydev->attached_dev);
  37. break;
  38. }
  39. /* Check if negotiation is done. Break if there's an error */
  40. err = phy_aneg_done(phydev);
  41. if (err < 0)
  42. break;
  43. /* If AN is done, we're running */
  44. if (err > 0) {
  45. phydev->state = PHY_RUNNING;
  46. netif_carrier_on(phydev->attached_dev);
  47. phydev->adjust_link(phydev->attached_dev);
  48. } else if (0 == phydev->link_timeout--)
  49. needs_aneg = true;
  50. break;
  51. case PHY_NOLINK:
  52. if (phy_interrupt_is_valid(phydev))
  53. break;
  54. err = phy_read_status(phydev);
  55. if (err)
  56. break;
  57. if (phydev->link) {
  58. if (AUTONEG_ENABLE == phydev->autoneg) {
  59. err = phy_aneg_done(phydev);
  60. if (err < 0)
  61. break;
  62. if (!err) {
  63. phydev->state = PHY_AN;
  64. phydev->link_timeout = PHY_AN_TIMEOUT;
  65. break;
  66. }
  67. }
  68. phydev->state = PHY_RUNNING;
  69. netif_carrier_on(phydev->attached_dev);
  70. phydev->adjust_link(phydev->attached_dev);
  71. }
  72. break;
  73. case PHY_FORCING:
  74. err = genphy_update_link(phydev);
  75. if (err)
  76. break;
  77. if (phydev->link) {
  78. phydev->state = PHY_RUNNING;
  79. netif_carrier_on(phydev->attached_dev);
  80. } else {
  81. if (0 == phydev->link_timeout--)
  82. needs_aneg = true;
  83. }
  84. phydev->adjust_link(phydev->attached_dev);
  85. break;
  86. case PHY_RUNNING:
  87. /* Only register a CHANGE if we are polling or ignoring
  88. * interrupts and link changed since latest checking.
  89. */
  90. if (!phy_interrupt_is_valid(phydev)) {
  91. old_link = phydev->link;
  92. err = phy_read_status(phydev);
  93. if (err)
  94. break;
  95. if (old_link != phydev->link)
  96. phydev->state = PHY_CHANGELINK;
  97. }
  98. /*
  99. * Failsafe: check that nobody set phydev->link=0 between two
  100. * poll cycles, otherwise we won't leave RUNNING state as long
  101. * as link remains down.
  102. */
  103. if (!phydev->link && phydev->state == PHY_RUNNING) {
  104. phydev->state = PHY_CHANGELINK;
  105. dev_err(&phydev->dev, "no link in PHY_RUNNING\n");
  106. }
  107. break;
  108. case PHY_CHANGELINK:
  109. err = phy_read_status(phydev);
  110. if (err)
  111. break;
  112. if (phydev->link) {
  113. phydev->state = PHY_RUNNING;
  114. netif_carrier_on(phydev->attached_dev);
  115. } else {
  116. phydev->state = PHY_NOLINK;
  117. netif_carrier_off(phydev->attached_dev);
  118. }
  119. phydev->adjust_link(phydev->attached_dev);
  120. if (phy_interrupt_is_valid(phydev))
  121. err = phy_config_interrupt(phydev,
  122. PHY_INTERRUPT_ENABLED);
  123. break;
  124. case PHY_HALTED:
  125. if (phydev->link) {
  126. phydev->link = 0;
  127. netif_carrier_off(phydev->attached_dev);
  128. phydev->adjust_link(phydev->attached_dev);
  129. do_suspend = true;
  130. }
  131. break;
  132. case PHY_RESUMING:
  133. if (AUTONEG_ENABLE == phydev->autoneg) {
  134. err = phy_aneg_done(phydev);
  135. if (err < 0)
  136. break;
  137. /* err > 0 if AN is done.
  138. * Otherwise, it's 0, and we're still waiting for AN
  139. */
  140. if (err > 0) {
  141. err = phy_read_status(phydev);
  142. if (err)
  143. break;
  144. if (phydev->link) {
  145. phydev->state = PHY_RUNNING;
  146. netif_carrier_on(phydev->attached_dev);
  147. } else {
  148. phydev->state = PHY_NOLINK;
  149. }
  150. phydev->adjust_link(phydev->attached_dev);
  151. } else {
  152. phydev->state = PHY_AN;
  153. phydev->link_timeout = PHY_AN_TIMEOUT;
  154. }
  155. } else {
  156. err = phy_read_status(phydev);
  157. if (err)
  158. break;
  159. if (phydev->link) {
  160. phydev->state = PHY_RUNNING;
  161. netif_carrier_on(phydev->attached_dev);
  162. } else {
  163. phydev->state = PHY_NOLINK;
  164. }
  165. phydev->adjust_link(phydev->attached_dev);
  166. }
  167. break;
  168. }
  169. mutex_unlock(&phydev->lock);
  170. if (needs_aneg)
  171. err = phy_start_aneg(phydev);
  172. else if (do_suspend)
  173. phy_suspend(phydev);
  174. if (err < 0)
  175. phy_error(phydev);
  176. dev_dbg(&phydev->dev, "PHY state change %s -> %s\n",
  177. phy_state_to_str(old_state), phy_state_to_str(phydev->state));
  178. queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
  179. PHY_STATE_TIME * HZ);
  180. }

PHY状态机分析的更多相关文章

  1. 以太网PHY寄存器分析【转】

    转自:https://blog.csdn.net/Firefly_cjd/article/details/79825869 以太网PHY寄存器分析    1 1.以太网PHY标准寄存器分析    2 ...

  2. openswan发送状态机分析

    openswan发送状态机分析 1. 函数调用关系 2. 函数说明 如果按用户空间.内核空间划分的话,此部分代码更多是运行在内核空间的. 2.1 ipsec_tunnel_init_devices() ...

  3. osip状态机分析

    转载于:http://blog.csdn.net/lbc2100/article/details/48342889 OSIP的核心是系统状态机,在不同情况下,系统处于不同的状态,在某一状态下当系统发生 ...

  4. Memcached 状态机分析

    worker线程拿到了这个连接之后,就应该是分配给这个连接一个结构体,包括这个连接所有的状态,都写buf等,这个结构体就是conn,然后这个worker线程会在它自己的event_base加入对这个新 ...

  5. Thrift线程和状态机分析

    目录 目录 1 1. 工作线程和IO线程 1 2. TNonblockingServer::TConnection::transition() 2 3. RPC函数被调用过程 3 4. 管道和任务队列 ...

  6. 基于335X的Linux网口驱动分析

    基于335X的linux网口驱动分析 一. 系统构成 1.  硬件平台 AM335X 2.  LINUX内核版本 4.4.12 二. 网口驱动构架(mdio部分) mdio网口驱动部分 使用 总线.设 ...

  7. capwap协议重点分析

    一.     CAPWAP概述 CAPWAP由两个部分组成:CAPWAP协议和无线BINDING协议. (1)CAPWAP协议是一个通用的隧道协议,完成AP发现AC等基本协议功能,和具体的无线接入技术 ...

  8. [RM 状态机详解4] RMNode状态机详解

    摘要 RMNode状态机是ResourceManager的四个状态机(RMApp,RMAppAttempt,RMContainer,RMNode)中最简单的一个,状态机如图1所示.RMNode是Res ...

  9. [RM 状态机详解1] RMApp状态机详解

    概述 Apache Hadoop 2.0在Hadoop 1.0基础上做了许多的重构工作,代码上的重构最大的变化在于引入状态机处理各个角色的状态与变迁,使用状态机是得代码结构更加清晰,方便异步处理各种操 ...

  10. linux网络设备—PHY

    一.结构体 1.PHY设备 struct phy_device { struct phy_driver *drv; //PHY设备驱动 struct mii_bus *bus; //对应的MII总线 ...

随机推荐

  1. 腾讯会议如何在Linux下的安装与使用

    腾讯会议官网https://meeting.tencent.com/download?mfrom=OfficialIndex_TopBanner1_Download下载 腾讯会议官网只提供了deb版的 ...

  2. error while loading shared libraries: libSM.so.6: cannot open shared object file: No such file or di

    前言 运行 ida软件报错, 但是我的系统中存在 libSM.so.6 解决办法 首先查看系统中的 libsm.so.6 ldconfig -p |grep -i libsm.so.6 输出: lib ...

  3. Oracle 两字符串相似度比较

    select SYS.UTL_MATCH.edit_distance_similarity('为中华之举起而读书','为中华') from dual;

  4. 第三十节:fillder抓取APP数据之小程序

    1.下载fillder ,fillder官网:https://www.telerik.com/fiddler 2.安装好后设置fillder: 工具->选项,打开设置面板.选择HTTPS选项卡. ...

  5. 【Java进阶】五分钟快速掌握JVM优化概念、常用命令、工具、JUC、多线程、GC等知识

    〇.概述 (一)资料 史上最全最详细的JVM优化方案:http://www.360doc.com/content/22/0513/10/34195792_1031121509.shtml (二)内容概 ...

  6. 【Java EE】Day04 MySQL多表、事务、事务隔离级别、DCL

    一.多表查询 1.概述 笛卡尔积:两集合的所有组成情况 多表查询:消除笛卡尔积得到的无用数据 2.分类 内连接查询(满足指定条件无空值,只显示有关联的数据) 隐式内连接:使用where限制消除无用数据 ...

  7. 【云原生 • DevOps】一文掌握容器管理工具 Rancher

    一.容器管理工具 Rancher 介绍Rancher 是一个开源的企业级全栈化容器部署及管理平台,其实就是一个 Docker 的图形化管理界面.它为容器提供基础架构服务,可以让 CNI 兼容的网络服务 ...

  8. Codeforces Round #838 (Div. 2) D. GCD Queries

    题意 有个长度为n的排列p,[0,1,2,...n-1],你可以进行至多2*n次询问,每次询问两个i,j,返回gcd(pi,pj),让你在规定时间内猜出0在哪两个位置之一 思路 这是一道交互题,询问的 ...

  9. 5、Idea同时选择多处光标进行编辑

    1.按住Alt+Shift,然后用鼠标左键点击文本,可以让光标在多个位置出现2.每个光标都会同时输入你正在输入的文本3.ESC退出 搜索 复制

  10. [python] NetworkX实例

    文章目录 NetworkX实例 1. 基础Basic 2. 绘图Drawing 3. 图标Graph NetworkX实例 代码下载地址 NetworkX 2.4版本的通用示例性示例.本教程介绍了约定 ...