ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux Mii management/mdio子系统分析之五 PHY状态机分析及其与net_device的关联

2020-03-08 18:04:54  阅读:748  来源: 互联网

标签:Mii 状态 management PHY 状态机 phy device net


      前面几章基本上完成了mdio模块驱动模型的分析,本篇文章主要讲述phy device的状态机以及phy device与net_device的关联。Phy device主要是对phy的抽象,而net_device主要是对mac的抽象,而mdio总线以及mii_bus主要用于对phy设备的控制(包括设置phy设备的工作模式、速率模式、是否为自适应、phy的link状态等),而net_device需要根据phy的工作模式、速率模式、phy的link状态进行状态的同步,因此需要将net_device与phy device进行绑定与解绑。本章主要分为两个方面:

一、phy_device与net_device的绑定与解绑

 

二、phy device的状态机

 

 

一、phy_device与net_device的绑定与解绑操作。

 

什么时候实现phy_devicenet_device的绑定与解绑操作?

我们从现有各厂家的net_device驱动可以看到,大致存在两种模式:

  1. 在net_device的probe接口中,根据传递的mdio_bus_id、phy_id,查找phy_device并完成net_device与phy_device的关联;在net_device的remove接口中,完成net_device与phy_device的解绑操作;
  2. 在net_device->netdev_ops->ndo_open接口中,据传递的mdio_bus_id、phy_id,查找phy_device并完成net_device与phy_device的关联;在nnet_device->netdev_ops->ndo_stop中,完成net_device与phy_device的解绑操作(即应用层执行ifconfig xxx up/down操作时调用ndo_open/ndo_stop)。

 

关于phy_device与net_device的绑定与解绑主要涉及如下几个函数phy_connect、phy_disconnect

下面我们分析下这两个接口的主要工呢

 

phy_connect分析

该接口主要用来进行一个net_device类型的变量与phy_device类型的变量的关联、设置phy_device的状态为PHY_READY,并启动phy_device的状态机,详细处理流程如下图所示

  1. 确认phy_device是否存在(根据传递的phy_device_id,在mdio_bus_type中查找phy_deviec);
  2. 若phy_device存在,则进行net_device与phy_device的相互关联(phy_device->attached_dev、net_device->phydev),并调用phy_driver->config_init完成对phy device的初始化;
  3. 启动phy_device的状态机对应的延迟队列。

 

 

 

phy_disconnect分析

 

phy_disconnect的操作刚好与phy_connect接口的操作相反,主要提供的功能如下:

  1. 若phy_device支持中断,则调用phy_stop_interrupts关闭中断,并free该中断;
  2. 调用phy_stop_machine接口,关闭该phy_device的状态机对应的延迟队列;
  3. 解除net_device与phy_device关联,若该phy_device是与genphy_driver绑定,则调用device_release_driver解除它们之间的绑定关系。

 

 

 

 

phy_device irq相关说明

     在上面的介绍中,我们提到了phy_device的中断,针对phy_device的中断而言,当两个phy之间的link up/down的变化后(两个phy完成速率协商或者连接断开时),则会触发该中断,从而触发phy_device的状态机的转变(状态转换至PHY_RUNNING/PHY_NOLINK)。

       那若phy_device不支持中断模式呢?那就使用PHY_POLL模式,在该模式下则当phy_device处于PHY_RUNNING状态时,则将phy_device状态自动切换至PHY_CHANGELINK状态,而在PHY_CHANGELINK状态下通过对phy_device的状态寄存器,确定phy_device处于link up/down状态。这类似于之前介绍的MMC部分的mmc card的在位检测模式(若支持中断则通过中断方式通知mmc card的在位与否;若不支持中断,则进行周期1s的延迟队列的调度进行轮询检测)。但与mmc模块不同的是,针对phy_device的状态机对应的延迟队列而言,不管其phy_device是否支持link up/down中断,其状态机对应延迟队列均为周期1s执行(不支持中断则由phy_device的状态机自动切换phy的状态进行检测,支持中断则由中断处理函数中进行状态的切换)。

如下即为执行完phy_connect操作后,针对支持phy_device中断处理接口(phy_interrupt)以及其底半部处理接口(phy_change)与phy_state_machine之间的关联。

 

 

phy device的状态机

 

         在调用phy_connect完成net_device与phy_device的关联后,则启动phy_device的状态机流转对应的延迟队列调度接口,进行phy_device的状态流转操作。如下图为phy_device的状态流程图,下面详细说明下各状态的流转说明:

  1. 当调用phy_device_create创建一个phy_device或者调用phy_remove移除phy_device时,即将phy_device的状态设置为PHY_DOWN;
  2. PHY_START状态,目前在linux3.10的内核中,没有将phy_device的状态切换至PHY_START步骤,因此先跳过;
  3. 当调用phy_connect完成phy_device与net_device的绑定后,即将phy_device的状态设置为PHY_READY状态;或者在phy_device_register、phy_driver_register时完成phy_device与phy_driver的绑定后,也会将其状态设置为PHY_READY。
  4. 当系统调用phy_start接口,且其状态为PHY_READY时,则将其状态流转至PHY_UP状态(一般在net_device->net_ops->ndo_start中,完成phy_connect调用后,则调用phy_start将phy状态流转至PHY_UP);
  5. 在PHY_UP状态时,若该phy_device设置了自适应,则自动将其状态流转至PHY_AN;若该PHY_DEVICE设置为FORCE状态,则自动将其状态流转至PHY_FORCING;
  6. 在PHY_AN状态下,根据读取的phy_device的状态寄存器,若linkup,则将其状态流转至PHY_RUNNING;否则将其状态流转至PHY_NOLINK;
  7. 在PHY_NOLINK状态下,根据读取的phy_device的状态寄存器,若linkup,则将其状态流转至PHY_RUNNING;
  8. 在PHY_FORCING状态下,若读取phy_device的状态寄存器,为linkup,则将其状态流转至PHY_RUNNING;
  9. PHY_RUNNING状态下,若phy_device不支持中断,则将其状态设置为PHY_CHANGELINK,进行phy_device linkup状态的轮询检测;
  10. 在PHY_CHANGELINK状态下,根据读取的phy_device的状态寄存器,若linkup,则将其状态流转至PHY_RUNNING;否则则将其状态设置为PHY_NOLINK;
  11. 当各驱动模块调用phy_stop接口后,则phy_device的状态跳转至PHY_HALTED状态(无条件跳转,一般在net_device->netdev_ops->ndo_stop中会调用phy_stop);
  12. 仅在phy_device处于PHY_HALTED状态时,方才会流转至该PHY_RESUMING状态,该状态可跳转至PHY_AN、PHY_NOLINK、PHY_RUNNING。

 

 

 

以上即为phy_device的状态,当phy_device处于PHY_RUNNING状态时(此时调用netif_carrier_on设置net_device状态),说明两端的phy协商成功,可进行数据通信。以上phy_device的状态流转由接口phy_state_machine实现,该接口的流程图如下:

主要说明如下:

  1. 当phy_device处于PHY_UP状态时,则phy_device状态机处理接口,设置needs_aneg为1,调用phy_start_ange接口,进入PHY_AN状态或PHY_FORCING状态,进行phy_device的状态的协商;
  2. 在PHY_AN状态时,则phy_state_machine判断是否需要将状态跳转至PHY_RUNNING或PHY_NOLINK;
  3. 在PHY_RUNNING状态时,若phy_device不支持中断,则将其状态跳转至PHY_CHANNGELINK状态,由phy_state_machine接口来轮询判断phy_device的状态是否跳转至PHY_RUNNING/PHY_NOLINK;

而像PHY_DOWN、PHY_START、PHY_READY、PHY_UP、PHY_HALTED、

PHY_RESUMING这几个状态,一般由外部模块调用相应的接口进行跳转,而非phy_state_machine自动流转。
 

 

针对net_device也有相应的状态定义,如下图所示主要涉及如下几个状态

enum netdev_state_t {

__LINK_STATE_START,

__LINK_STATE_PRESENT,

__LINK_STATE_NOCARRIER,

__LINK_STATE_LINKWATCH_PENDING,

__LINK_STATE_DORMANT,

};

 

  1. 当net_device注册至系统时,即设置__LINK_STATE_PRESENT;
  2. 当执行ifconfig xxx up,启用一个net_device时,则将其状态设置为__LINK_STATE_START(记住此时并不代表phy已完成协商且处于linkup状态),并在调用net_device->netdev_ops->ndo_open时,设置__LINK_STATE_NOCARRIER;
  3. 当调用phy_connect完成phy_device与net_device的绑定以及启动phy_device的状态机后,且phy_device跳转至PHY_RUNNING的同时,清除__LINK_STATE_NOCARRIER位,此时方才表明可进行数据通信。

 

 

      以上即是本次的主要内容,主要涉及phy_device与net_device之间的关联建立以及phy_device的状态机流转相关的内容。当phy_device处于PHY_RUNNING状态时,则将net_device的状态设置为carrier_on,即可进行mac层及mac层以上的数据通信工作。

标签:Mii,状态,management,PHY,状态机,phy,device,net
来源: https://blog.csdn.net/lickylin/article/details/104718409

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有