乙太網驅動的流程淺析(四) 乙太網驅動probe流程 Author:張昺華 Email:[email protected] Time:2019年3月23日星期六 此文也在我的個人公眾號以及《Linux內核之旅》上有發表: "乙太網驅動的流程淺析(四) 乙太網驅動probe流程" 乙太網驅動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是drvier的入口函數:
這個 probe中主要做了哪些事情呢?以下我只寫主要的一些,不是全部的。
struct net_device *ndev;這裡對net_device進行初始化,分配記憶體
接下來做如下動作,註釋都很明顯,我就不解釋了,
struct fec_enet_private *fep;
獲取時鐘:
使能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
2) device tree中設置,如果沒有跳到步驟3;
3) from flash / fuse / via platform data,如果沒有跳到步驟4;
4) FEC mac registers set by bootloader===》即靠usb方式下載mac address ,如果沒有跳到步驟5;
5) 靠kernel算一個隨機數mac address出來,然後寫入mac
所以最後一種方式就是kernel會自己算一個mac地址出來,我這裡有個前提是這個是freescale(現在被nxp收購了)的控制器代碼這樣寫的,我不確定其他廠商的控制器是否也是這樣的流程,技術講究嚴謹,所以這裡不能一概而論。當然這個mac 地址也是可以用戶自己在dts中進行自行配置的。
這裡就是kernel隨機數的介面了,會總隨機池中獲取一個隨機數並返回。
大家看到那些獲取mac address的步驟中有這樣的函數
is_valid_ether_addr,用來檢測乙太網地址是否正確的
因此我們從代碼中可以看出,內核認為全0或者是全FF的乙太網地址是不正確的,
獲取了mac 地址後,就會通過寄存器寫入mac中
CONFIG_ARCH_MXC因為我們使用的是這個巨集,因此:
否則:
設置buffer傳輸的基地址
提供一些乙太網控制器的操作介面,應用層調用socket通信最終的實現介面方式,並且提供開源工具ethtool工具的底層操作介面支持
所以有些人用ethtool工具發現不同平臺可能不一樣,同樣的命令有些可能返回不同,或者功能不支持,就可以猜想一下可能是因為不同廠商的控制器驅動這裡的實現問題導致,部分介面可能沒有實現或者有bug等等,這些就要具體問題具體分析了,有些板子可能某些介面根本都沒實現,自然ethtool的一些命令就無法正常使用了。
最後進行控制器對phy的複位動作
fec_restart(ndev);
流程如下:
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函數,然後是註冊中斷處理函數
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
```