以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】

以太网驱动的流程浅析(四)-以太网驱动probe流程

Author:张昺华
Email:[email protected]
Time:2019年3月23日星期六

此文也在我的个人公众号以及《Linux内核之旅》上有发表:以太网驱动的流程浅析(四)-以太网驱动probe流程

很喜欢一群人在研究技术,一起做有意思的东西,一起分享技术带给我们的快乐,也希望中国有更多的人热爱技术,喜欢一起研究、分享技术,然后可以一起用我们的技术来做一些好玩的东西,可以为这个社会创造一些东西来改善人们的生活。

如下是本人调试过程中的一点经验分享,以太网驱动架构毕竟涉及的东西太多,如下仅仅是针对加载流程和围绕这个问题产生的分析过程和驱动加载流程部分,并不涉及以太网协议层的数据流程分析。

【硬件环境】 Imx6ul

【Linux kernel版本】 Linux4.1.15

【以太网phy】 Realtek8201f

1.1. 以太网驱动probe流程

1.1 以太网初始化

fec_main.c   fec_probe
=>fec_enet_mii_init

   =>of_get_child_by_name(pdev->dev.of_node, "mdio");
     of_mdiobus_register(fep->mii_bus, node);

               =>rc = of_mdiobus_register_phy(mdio, child, addr);

                 => phy = get_phy_device(mdio, addr, is_c45);
                    rc = phy_device_register(phy);

以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第1张图片

搞驱动的都知道,probe是drvier的入口函数:
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第2张图片

这个 probe中主要做了哪些事情呢?以下我只写主要的一些,不是全部的。
struct net_device *ndev;这里对net_device进行初始化,分配内存

接下来做如下动作,注释都很明显,我就不解释了,
struct fec_enet_private *fep;

以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第3张图片

获取时钟:
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第4张图片

使能clk,fec_enet_clk_enable(ndev, true);
复位phy,硬件复位,具体取决于不同phy的datasheet的reset时序,fec_reset_phy(pdev);
一些初始化动作,fec_enet_init(ndev);由于代码注释写的很好,上代码:

1.2 获取以太网mac地址

这里获取mac 地址的流程我要说一下,之前有讲过流程,我这里再提一下:
1) 模块化参数设置,如果没有跳到步骤2
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第5张图片

2) device tree中设置,如果没有跳到步骤3;
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第6张图片

3) from flash / fuse / via platform data,如果没有跳到步骤4;
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第7张图片

4) FEC mac registers set by bootloader===》即靠usb方式下载mac address ,如果没有跳到步骤5;
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第8张图片

5) 靠kernel算一个随机数mac address出来,然后写入mac
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第9张图片

所以最后一种方式就是kernel会自己算一个mac地址出来,我这里有个前提是这个是freescale(现在被nxp收购了)的控制器代码这样写的,我不确定其他厂商的控制器是否也是这样的流程,技术讲究严谨,所以这里不能一概而论。当然这个mac 地址也是可以用户自己在dts中进行自行配置的。
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第10张图片
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第11张图片

这里就是kernel随机数的接口了,会总随机池中获取一个随机数并返回。
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第12张图片

大家看到那些获取mac address的步骤中有这样的函数
is_valid_ether_addr,用来检测以太网地址是否正确的
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第13张图片

因此我们从代码中可以看出,内核认为全0或者是全FF的以太网地址是不正确的,
获取了mac 地址后,就会通过寄存器写入mac中
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第14张图片

CONFIG_ARCH_MXC因为我们使用的是这个宏,因此:
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第15张图片

否则:

设置buffer传输的基地址
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第16张图片

提供一些以太网控制器的操作接口,应用层调用socket通信最终的实现接口方式,并且提供开源工具ethtool工具的底层操作接口支持

以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第17张图片
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第18张图片

所以有些人用ethtool工具发现不同平台可能不一样,同样的命令有些可能返回不同,或者功能不支持,就可以猜想一下可能是因为不同厂商的控制器驱动这里的实现问题导致,部分接口可能没有实现或者有bug等等,这些就要具体问题具体分析了,有些板子可能某些接口根本都没实现,自然ethtool的一些命令就无法正常使用了。

最后进行控制器对phy的复位动作
fec_restart(ndev);
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第19张图片

流程如下:
1) Whack a reset. We should wait for this. For i.MX6SX SOC, enet use AXI bus, we use disable MAC , instead of reset MAC itself.
2)enet-mac reset will reset mac address registers too, so need to reconfigure it.
3) Clear any outstanding interrupt.
4) Reset tx SKB buffers.
5) Enable MII mode
6) The phy interface and speed need to get configured,
7) configure the gasket: RMII, 50 MHz, no loopback, no echo; MII, 25 MHz, no loopback, no echo
8) Setup multicast filter.
9) And last, enable the transmit and receive processing
10) Enable interrupts we wish to service
11) Init the interrupt coalescing
fec_enet_init函数的流程到此结束
我们继续回归到fec_probe函数,然后是注册中断处理函数
以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】_第20张图片

4. 网址分享

http://stackoverflow.com/questions/5308090/set-ip-address-using-siocsifaddr-ioctl
http://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.commtrf2/ioctl_socket_control_operations.htm
https://lkml.org/lkml/2017/2/3/396
linux PHY驱动
http://www.latelee.org/programming-under-linux/linux-phy-driver.html
Linux PHY几个状态的跟踪
http://www.latelee.org/programming-under-linux/linux-phy-state.html
第十六章PHY -基于Linux3.10
https://blog.csdn.net/shichaog/article/details/44682931

```

End

你可能感兴趣的:(以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】)