stmmac 中断处理
1.?發送中斷
1.1.?DMA發送完數據后產生中斷,調用 stmmac_interrupt服務程序
?
1.2. stmmac_interrupt?通過調用?stmmac_dma_interrupt?處理DMA相關中斷(包括發送和接收)。在stmmac_dma_interrupt中,通過NAPI機制觸發軟中斷,調用stmmac_poll處理相關事件。
?
1.3.?stmmac_poll調用stmmac_tx_clean回收資源,以及queue操作
1)通過dma_unmap_single解除dma映射
dma_unmap_single(priv->device, tx_q->tx_skbuff_dma[entry].buf, tx_q->tx_skbuff_dma[entry].len, DMA_TO_DEVICE);
2)釋放skb
dev_consume_skb_any(skb);
3)清空descriptor:des2和des3,?將其賦值0
release_tx_desc()
4)設置queue的狀態?,如果queue是停止狀態(__QUEUE_STATE_STACK_XOFF?或?__QUEUE_STATE_DRV_XOFF被置位),但是現在已經滿足開啟條件,則喚醒queue。? ?
在stmmac_xmit發送時如果停止了queue,現在如果條件滿足,會重新恢復queue。
netdev_tx_completed_queue(netdev_get_tx_queue(priv->dev, queue),pkts_compl, bytes_compl);if (unlikely(netif_tx_queue_stopped(netdev_get_tx_queue(priv->dev,queue))) &&stmmac_tx_avail(priv, queue) > STMMAC_TX_THRESH) {netif_dbg(priv, tx_done, priv->dev,"%s: restart transmit\n", __func__);netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, queue));}在netdev_tx_completed_queue中,test_and_clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state),如果test_and_clear_bit返回真,調用 netif_schedule_queue(q)重新開始調度queue
在netif_tx_wake_queue中,test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state),如果test_and_clear_bit返回真,調用 __netif_schedule(q)重新開始調度queue
?
?
2.?接收中斷
2.1.?DMA產生中斷,調用 stmmac_interrupt服務程序
?
2.2. stmmac_interrupt?通過調用?stmmac_dma_interrupt?處理DMA相關中斷(包括發送和接收)。在stmmac_dma_interrupt中,通過NAPI機制觸發軟中斷,調用stmmac_poll接收數據包。
?
2.3. 在stmmac_poll中調用如下代碼收數據包
work_done = stmmac_rx(priv, budget, rx_q->queue_index);if (work_done < budget) {napi_complete_done(napi, work_done);stmmac_enable_dma_irq(priv, chan);}return work_done;1)調用stmmac_rx接收,budget為循環讀取dma?descriptor(通過處理descriptor來獲取數據包,每個descriptor對應一個數據包)的最大次數,work_done為實際循環的次數。
2)if (work_done < budget) 代表實際循環讀取dma?descriptor的次數小于最大次數budget,代表已經處理完所有需要被處理的descriptor,取完所有的數據包。這時,調用stmmac_enable_dma_irq()開啟中斷,再次接收數據。如果work_done = budget,代表可能還有數據包需要處理,那么這些數據包留到net_rx_action再次調用stmmac_poll時處理。
3)return work_done;?該返回值會被net_rx_action使用。
?
2.4. 在stmmac_rx中,循環收包,循環次數while (count < limit)。每次循環以DMA?descriptor為處理單位,即每次循環時從一個descriptor指定的buffer讀取一個數據包,再通過 napi_gro_receive?送給協議層,處理完后count++。這里limit = budget。
?
2.5. 調用 stmmac_rx_refill重新填充descriptor。
在觸發DMA中斷前,DMA已經將網卡收到的數據包搬到descriptor指定的buffer,而這個buffer又采用了zero-copy機制,所以直接將該buffer的地址copy給一個skb,再將此skb送到協議層處理,最后再調用 stmmac_rx_refill重新填充descriptor并設置buffer。之前descriptor指定的buffer地址已經被賦值給skb,由協議層負責該skb(buffer)的管理(釋放內存等)。
?
2.6.?總結:
這里有三種“一次獲取多個數據包”的情況
1)一次軟中斷可能會多次調用net_rx_action
2)net_rx_action可能會多次調用stmmac_poll
3)stmmac_poll處理多個descriptor
?
?
總結
以上是生活随笔為你收集整理的stmmac 中断处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地狱边境第十关怎么过(2013年人民文学
- 下一篇: 苹果鼠标怎么充电_“智能”还是“多功能”