linux以太網驅動總結

linux以太網驅動總結

工作中涉及linux以太網驅動,涉及代碼:drivers/net/ethernet/stmicro/,drivers/net/phy/,進行一下總結。
概要:
1.以太網硬件
2.軟件初始化probe, open
3.數據發送過程
4.數據接收過程
5.設備無關層
6.bring up以太網功能
7.傳輸過程中傳輸中斷的問題

1.以太網硬件
MAC:通常集成在ARM芯片中,功能類似於一個controller,以太網協議層數據傳送給MAC,由MAC通過DMA發送到外部接口,外部接口連接着PHY。或者接收從PHY傳過來的信號,DMA搬運到內存中存儲。
PHY:通常是一個獨立芯片,有數字和模擬兩部分,也可以集成在ARM芯片內部。負責把從MAC傳送過來的數據轉換成可以在網線上傳輸的信號,或者接收網線上傳輸過來的信號,轉換成數字信號回傳給MAC。分爲百兆PHY和千兆PHY。
PHY配置:自協商模式開啓/關閉; 自協商關閉狀態下,配置爲強制full duplex, half duplex, 強制1000Mbps/100Mbps/10Mbps;WOL開啓/關閉。
MAC和PHY之間的接口分爲RMII接口(百兆),RGMII接口(千兆)。
RMII接口:
這裏寫圖片描述
數據傳輸信號線TX0, TX1, RX0,RX1,clock
控制口:MDC, MDIO
RGMII接口:
這裏寫圖片描述
數據傳輸信號線TX0-3, RXD0-3,TX clock, RX clock
控制口:MDC, MDIO
MDC,MDIO用於控制信號的傳輸,MAC對PHY的讀寫數據通過MDIO接口傳送。
TX,RX,信號線用於數據信號的傳輸。

2.軟件初始化
我們使用的驅動是stmicro驅動,所以基於該驅動代碼來介紹
probe
1.讀取dts文件中的ethernet配置,讀取MAC基地址,rgmii or rmii, 配置寄存器,讀取和保存從uboot傳過來的MAC地址。
2.alloc,init net_device struct, 註冊ops: stmmac_netdev_ops, register net_device. clock enable.
stmmac_hw_init:註冊mac ops, dma ops.
dwmac1000_ops, dwmac1000_dma_ops,
3.尋找phy: stmmac_mdio_register
BUS:bus_register(&mdio_bus_type)
driver: driver_register註冊phy driver.
device: 讀取phy id, phy_device_create, dev.bus = &mdio_bus_type
mdio_bus_type裏面有一個match函數,通過phyid來match phy device和phy driver
stmmac_open
ifconfig eth0 up時會調用到ndo_open回調,實際調用stmmac_open
1.stmmac_init_phy, 如果沒有匹配上phy driver, 就賦予通用phy driver, 初始化phy, 啓動delayed work: phy_state_machine,
2.alloc&init dma descriptor struct array, sk_buff address array (tx, rx)
這裏寫圖片描述
3.MAC init
dma mode, descriptor base address, set mac address,
4.request_irq, 註冊ISR
5.napi_enable, netif_start_queue.

3.數據發送
每填充一個descriptor, cur_tx++, 每回收一個descriptor, dirty_tx++,
如果dirty_tx != cur_tx, 說明有等待dma傳送的數據。
調用stmmac_xmit, 註冊爲ndo_start_xmit的回調函數。
這裏寫圖片描述
TX 發送完畢回收內存
stmmac_tx_clean,
一次stmmac_tx_clean調用會通過while循環把隊列中所有已經完成發送的descriptor全部回收。
stmmac_tx_clean可通過DMA ISR調用,也可以通過timer ISR調用到。
這裏寫圖片描述
4.數據接收
這裏寫圖片描述
關於skb
TX端的skb是從上層傳送過來的,我們需要把skb->data地址 dma_map_single到 tx descriptor中,發送完成後,再dma_ummap_single, 調用dev_free_skb, 應該是通知上層,這個skb已經處理完畢。
RX端的skb,是在驅動中alloc的,接收的數據填充到skb中,然後通過napi_gro_receive把skb傳送到上層
Q:驅動怎麼知道傳送給上層的skb中的空間已經可以作爲下一次傳送的空間來覆蓋數據?
A:傳給上層的skb不會再使用,會重新獲取到新的skb.
調試打印函數:通過修改default_msg_level, 設置打印功能。

5.設備無關層
在協議層和設備驅動程序之間,是skb的傳遞,類似於其他驅動程序中的core層,與具體設備無關。
skb向上傳遞:
這裏寫圖片描述
skb向下傳遞:
這裏寫圖片描述

6.bring up以太網功能
檢查寄存器基地址,寄存器定義,寄存器配置(百兆,千兆,rmii,rgmii,內部,外部phy), pinmux, 檢查phy的配置.
probe失敗可能原因:
1.MAC reset失敗。檢查電源,clock。
2.無法讀取phy id。檢查phy的電源,clock,pinmux.
能正確顯示link狀態,但是數據不通:
1.檢查寄存器配置,pinmux, 主要是rmii, rgmii相關配置
2.檢查phy driver是否正確匹配上,phy driver中的phy id與 phy device 中的phy id如果不一致的話,phy driver就匹配不成功,導致phy config函數沒有執行到。
7.傳輸過程中傳輸中斷的問題
tx方向的傳輸中斷。增加每秒運行一次的work queue, 檢查在dma隊列中是否有待發送的數據(已經交給dma),如果有,記下隊列index, 過5秒之後再檢查這個待發送的數據是否已發送完成,如果還未完成,認爲TX傳輸中止,reset ethernet.
rx方向的傳輸中斷。每條檢查一次,檢查phy的狀態,如果狀態異常,則reset ethernet. 還可以仿照TX方向增加監控和恢復機制。
在reset ethernet時,需要注意kernel panic。 reset過程是,停止TX,RX,釋放之前alloc的所有memory, 重新alloc memory, 初始化mac, 初始化phy。出現panic的原因是,驅動代碼還在使用已經被釋放了的memory。因爲已經停止了TX,RX,按道理不會再運行TX,RX部分的代碼了。最後發現是tx timer handler裏面會操作memory。當停止TX,RX之後, 釋放所有memory, 然後tx timer handler觸發,操作被釋放的memory, 導致panic. 解決方法是,減少tx timer的expire時間,並且在停止TX之後,增加delay, 使tx timer handler完成之後,再釋放memory.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章