帶你一文搞懂 Linux 網(wǎng)絡(luò) Phy 驅(qū)動(dòng)
概述

上圖來自 瑞昱半導(dǎo)體 (RealTek) 的 RTL8201F 系列網(wǎng)卡 PHY 芯片手冊(cè)。按OSI 7層網(wǎng)絡(luò)模型劃分,網(wǎng)卡PHY 芯片(圖中的RTL8201F)位于物理層,對(duì)應(yīng)的軟件層就是本文討論的 PHY 驅(qū)動(dòng)層;而 MAC 位于 數(shù)據(jù)鏈路層,也是通常軟件上所說的網(wǎng)卡驅(qū)動(dòng)層,它不是本文的重點(diǎn),不做展開。另外,可通過 MDIO 接口對(duì) PHY 芯片進(jìn)行配置(如PHY芯片寄存器讀寫),而 PHY 和 MAC 通過 MII/RMII 進(jìn)行數(shù)據(jù)傳輸。
PHY芯片通過MII/GMII/RMII/SGMII/XGMII等多種媒體獨(dú)立接口(介質(zhì)無關(guān)接口)與數(shù)據(jù)鏈路層的MAC芯片相連,并通過MDIO接口實(shí)現(xiàn)對(duì)PHY 狀態(tài)的監(jiān)控、配置和管理。
PHY與MAC整體的連接框圖:

數(shù)據(jù)結(jié)構(gòu)
每個(gè) phy 芯片會(huì)創(chuàng)建一個(gè) struct phy_device 類型的設(shè)備,對(duì)應(yīng)的有 struct phy_driver 類型的驅(qū)動(dòng),這兩者實(shí)際上是掛載在 mdio_bus_type 總線上的,mac 會(huì)被注冊(cè)成 struct net_device。

phy_device
phy_driver
mii_bus
net_device
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ?


零聲白金VIP體驗(yàn)卡(含基礎(chǔ)架構(gòu)/高性能存儲(chǔ)/golang/QT/音視頻/Linux內(nèi)核)課程:?

phy 設(shè)備的注冊(cè)
以網(wǎng)卡 Fec 為例,網(wǎng)卡驅(qū)動(dòng)在初始化 fec_probe() 時(shí)遍歷 dts 的定義,創(chuàng)建相應(yīng) struct phy_device 類型的設(shè)備,主要步驟為:
注冊(cè)網(wǎng)絡(luò)設(shè)備 net_device
申請(qǐng)隊(duì)列和 DMA
申請(qǐng) MDIO 總線
創(chuàng)建并注冊(cè) Phy 設(shè)備
phy 驅(qū)動(dòng)的注冊(cè)
genphy_driver 通用驅(qū)動(dòng)
內(nèi)核中有 genphy_driver 通用驅(qū)動(dòng),以及專有驅(qū)動(dòng)(這里以 NXP TJA 驅(qū)動(dòng)為例),分別如下:
genphy_driver 的 struct phy_driver 的注冊(cè)過程如下:
其中一個(gè)關(guān)鍵點(diǎn)是 mdio driver 的 probe 函數(shù)是一個(gè)通用函數(shù) phy_probe:
其中通用 phy 驅(qū)動(dòng)會(huì)調(diào)用函數(shù) genphy_read_abilities 來讀取狀態(tài)寄存器來確定 phy 芯片的能力:
NXP TJA 專有驅(qū)動(dòng)
NXP TJA 驅(qū)動(dòng)的 struct phy_driver 的注冊(cè)過程如下:
根據(jù)上面的分析,由于存在 phydev->drv->probe,所以會(huì)調(diào)用其注冊(cè)的函數(shù) tja11xx_probe。
網(wǎng)卡 fec 和 Phy 的協(xié)作
在 linux 內(nèi)核中,以太網(wǎng) mac 會(huì)被注冊(cè)成 struct net_device,phy 芯片會(huì)被注冊(cè)成 struct phy_device。 phy_device 的狀態(tài)怎么傳遞給 net_device,讓其在 link 狀態(tài)變化時(shí)做出對(duì)應(yīng)的配置改變,這個(gè)任務(wù)就落在上述的 struct phylink 中介身上。
下面就以 fec 網(wǎng)口驅(qū)動(dòng)為例,展示一下網(wǎng)卡 fec 和 phy 的協(xié)作過程。整個(gè) phy 驅(qū)動(dòng)的主要調(diào)用流程如下圖所示:

一個(gè) phy 驅(qū)動(dòng)的原理其實(shí)是非常簡(jiǎn)單的,一般流程如下:
用輪詢/中斷的方式通過 mdio 總線讀取 phy 芯片的狀態(tài)。
在 phy link 狀態(tài)變化的情況下,正確配置 mac 的狀態(tài)。(例如:根據(jù) phy 自協(xié)商的速率 10/100/1000M 把 mac 配置成對(duì)應(yīng)速率)
phy 芯片狀態(tài)在 phy 設(shè)備注冊(cè)的時(shí)候已經(jīng)體現(xiàn),這里詳細(xì)講下如何在 phy link 狀態(tài)變化的情況下,正確配置 mac 的狀態(tài)。
自協(xié)商配置
具體啟動(dòng) phy 自協(xié)商的代碼流程如下:
link 狀態(tài)讀取
phy link 狀態(tài)讀取的代碼流程如下:
link 狀態(tài)通知
phy 的 link 狀態(tài)變化怎么通知給 netdev,并且讓 mac 做出相應(yīng)的配置改變,這個(gè)是通過一個(gè)中介 phylink 來實(shí)現(xiàn)的。
原文作者:人人極客社區(qū)
