日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

netdev: dev_watchdog timer(结合stmmac 分析)

發(fā)布時(shí)間:2023/12/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 netdev: dev_watchdog timer(结合stmmac 分析) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

分析netdev看門狗定時(shí)器

?

1. dev_watchdog()作為定時(shí)器回調(diào)函數(shù)會被周期執(zhí)行

在dev_watchdog()中,如果 if (netif_xmit_stopped(txq) && time_after(jiffies, (trans_start + dev->watchdog_timeo)))?成立,執(zhí)行some_queue_timedout = 1,?然后便調(diào)用ndo_tx_timeout。

ndo_tx_timeout函數(shù)便是網(wǎng)卡發(fā)送異常(數(shù)據(jù)發(fā)不出去等)時(shí)的超時(shí)處理函數(shù)。它會調(diào)用 stmmac_tx_timeout重新啟動transmission。

if (some_queue_timedout) {WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n",dev->name, netdev_drivername(dev), i);dev->netdev_ops->ndo_tx_timeout(dev); }

?

2. dev_watchdog()執(zhí)行ndo_tx_timeout的條件

if (netif_xmit_stopped(txq) && time_after(jiffies, (trans_start + dev->watchdog_timeo)))

?

2.1 time_after(jiffies, (trans_start + dev->watchdog_timeo))

即queue發(fā)送超時(shí)

1)dev->watchdog_timeo為定時(shí)周期

2)在 __netdev_start_xmit中,如果 ndo_start_xmit返回 NETDEV_TX_OK(這并不代表數(shù)據(jù)已經(jīng)通過DMA發(fā)送出去),便調(diào)用 txq_trans_update更新txq->trans_start。在dev_watchdog中,會將txq->trans_start賦值給trans_start。

?

2.2 netif_xmit_stopped(txq)

queue已經(jīng)停止發(fā)送

static inline bool netif_xmit_stopped(const struct netdev_queue *dev_queue) {return dev_queue->state & QUEUE_STATE_ANY_XOFF; }#define QUEUE_STATE_ANY_XOFF (QUEUE_STATE_DRV_XOFF | QUEUE_STATE_STACK_XOFF) #define QUEUE_STATE_DRV_XOFF (1 << __QUEUE_STATE_DRV_XOFF) #define QUEUE_STATE_STACK_XOFF (1 << __QUEUE_STATE_STACK_XOFF)

1)__QUEUE_STATE_STACK_XOFF

清除__QUEUE_STATE_STACK_XOFF:

如果DMA發(fā)送完成,在中斷服務(wù)程序 stmmac_dma_interrupt() ->? stmmac_poll() ->? stmmac_tx_clean() ->? netdev_tx_completed_queue() ->? test_and_clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state)? 清除

?

設(shè)置__QUEUE_STATE_STACK_XOFF:

發(fā)送時(shí),在stmmac_xmit() ->?netdev_tx_sent_queue() ->?set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state)?設(shè)置

?

所以如果dma中斷沒有被觸發(fā),或是觸發(fā)了但是發(fā)送沒有完成,則netif_xmit_stopped()返回1

static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue,unsigned int bytes) { #ifdef CONFIG_BQLdql_queued(&dev_queue->dql, bytes);if (likely(dql_avail(&dev_queue->dql) >= 0))return;set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);/* check again in case another CPU has just made room avail */if (unlikely(dql_avail(&dev_queue->dql) >= 0))clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state); #endif }static inline void netdev_tx_reset_queue(struct netdev_queue *q) { #ifdef CONFIG_BQLclear_bit(__QUEUE_STATE_STACK_XOFF, &q->state);dql_reset(&q->dql); #endif }static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue,unsigned int pkts, unsigned int bytes) { #ifdef CONFIG_BQLif (unlikely(!bytes))return;dql_completed(&dev_queue->dql, bytes);if (dql_avail(&dev_queue->dql) < 0)return;if (test_and_clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state))netif_schedule_queue(dev_queue); #endif }

2) __QUEUE_STATE_DRV_XOFF

主要針對網(wǎng)卡queue,當(dāng)queue滿或不足以進(jìn)行下一個(gè)傳輸時(shí),會調(diào)用netif_tx_stop_queue通知上層停止發(fā)送。當(dāng)queue恢復(fù)時(shí),調(diào)用netif_tx_wake_queue通知上層重新開始傳輸。

?

清除__QUEUE_STATE_DRV_XOFF:

stmmac_open ->?stmmac_start_all_queues ->?netif_tx_start_queue ->?clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state)

stmmac_dma_interrupt ->?stmmac_poll -> stmmac_tx_clean ->?netif_tx_wake_queue

?

設(shè)置__QUEUE_STATE_DRV_XOFF:

static __always_inline void netif_tx_start_queue(struct netdev_queue *dev_queue) {clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); }void netif_tx_wake_queue(struct netdev_queue *dev_queue) {if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state)) {struct Qdisc *q;rcu_read_lock();q = rcu_dereference(dev_queue->qdisc);__netif_schedule(q);rcu_read_unlock();} }static __always_inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) {set_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); }

?

總結(jié)

以上是生活随笔為你收集整理的netdev: dev_watchdog timer(结合stmmac 分析)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。