from
一、硬體布局
每個網絡卡(mac)都有自己的專用dma engine,如上圖的 tsec 和 e1000 網絡卡intel82546。
上圖中的紅色線就是乙太網資料流,dma與ddr打交道需要其他模組的協助,如tsec,pci controller
乙太網資料在tsecddr pci_controllerddr之間的流動,cpu的core是不需要介入的
只有在資料流動結束時(接收完、傳送完),dma engine才會以外部中斷的方式告訴cpu的core
二、dma engine
上面是dma engine的框圖,以接收為例:
1.在system memory中為dma開闢一端連續空間,用來bd陣列 (一致性dma記憶體)
bd是給dma engine使用的,所以不同的裝置,bd結構不同,但是大致都有狀態、長度、指標3個成員。
2.初始化bd陣列,status為e,length為0
在system memory中再開闢一塊一塊的記憶體,可以不連續,用來存放乙太網包
將這些記憶體塊的匯流排位址賦給buf(dma對映)
3.當mac接收乙太網資料流,放在了rx fifo中
4.當乙個乙太網包接收完全後,dma engine依次做以下事情
fetch bd:開始乙個個的遍歷bd陣列,直到當前bd狀態為empty為止
update bd:更新bd狀態為ready
move data:把資料從rx fifo中搬移到system memory中dma對映的部分
generate interrupt:資料搬移完了,產生外部中斷給cpu core
5.cpu core處理外部中斷,此時乙太網資料已經在system memory中dma對映的部分了
解除dma對映,更新bd狀態為empty
再開闢一端記憶體,將這塊記憶體的匯流排位址賦給bd的指標字段
三、核心中dma相關api
void *dma_alloc_cohrent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
功能:分配一致性dma記憶體,返回這塊記憶體的虛擬位址ea, 這塊記憶體的實體地址儲存在 dma_handle
dev: null也行
size: 分配空間的大小
dma_handle: 用來儲存記憶體的匯流排位址(實體地址)
注意:一致性dma對映,bd所佔記憶體就是靠dma_alloc_cohrent來分配的。
dma_addr_t *dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction);
功能:將一塊連續的記憶體 buffer 對映為dma記憶體來使用。對映後,cpu不能再操作這塊 buffer
返回:這塊buffer的匯流排位址(實體地址)
dev: null也行
buffer: 一塊連續記憶體的虛擬位址ea
size: 連續記憶體的大小
dma_data_direction: dma資料流的方向
注意:流式dma對映,乙太網包所佔記憶體先通過kmalloc來分配,然後通過dma_map_single來對映給bd的
四、e1000驅動中的dma
網絡卡驅動中使用dma的套路差不多都一樣,以e1000驅動為例講一下(tsec驅動的dma見這裡)
4.1 載入e1000網絡卡驅動
e1000_probe()
4.1 啟動e1000網絡卡
e1000_open() //當使用者敲ifconfig up命令時,最終呼叫網絡卡驅動的open函式
-->e1000_setup_all_rx_resources(adapter)
-->e1000_setup_rx_resources(adapter, &adapter->rx_ring[i])
//給rx bd分配一致性dma記憶體
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
-->e1000_configure(adapter)
-->e1000_configure_rx(adapter)
adapter->clean_rx = e1000_clean_rx_irq;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
-->呼叫 adapter->alloc_rx_buf鉤子函式,即 e1000_alloc_rx_buffers
--> skb = netdev_alloc_skb(netdev, bufsz); //呼叫kmalloc新建乙個skb
buffer_info->dma = pci_map_single(pdev,
skb->data,
adapter->rx_buffer_len,
pci_dma_fromdevice); //給skb->data建立dma對映
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);//初始化bd的buf指標
-->e1000_request_irq(adapter);
//掛rx 中斷isr函式為 e1000_intr()
最終bd資料結構應該是下面這個樣子
4.2 e1000的中斷
注意:e1000產生rx中斷時,乙太網資料報已經在系統記憶體中,即在skb->data裡面
下面的中斷處理過程就簡略了,詳細的看這裡
do_irq()
e1000_clean_rx_irq()
網路資料報收發流程 3 E1000網絡卡和DMA
標籤 資料報乙太網資料流 原文出處 一 硬體布局 每個網絡卡 mac 都有自己的專用dma engine,如上圖的 tsec 和 e1000 網絡卡intel82546。上圖中的紅色線就是乙太網資料流,dma與ddr打交道需要其他模組的協助,如tsec,pci controller 乙太網資料在 t...
網路資料報收發流程 二 不配置NAPI的情況
不配置napi的時候,網路裝置不使用自己的napi struct結構,所有網路裝置驅動都使用同乙個napi struct,即cpu私有變數 get cpu var softnet data backlog 每當收到資料報時,網路裝置驅動會把 get cpu var softnet data back...
網路資料報收發流程 2 不配置NAPI的情況
標籤 資料報網路 原文出處 不配置napi的時候,網路裝置不使用自己的napi struct結構,所有網路裝置驅動都使用同乙個napi struct,即cpu私有變數 get cpu var softnet data backlog 每當收到資料報時,網路裝置驅動會把 get cpu var sof...