[ISSUE]NETDEV WATCHDOG: eth0 (enc424j600): transmit queue 0 timed out

1, How this log output ?

in drivers/net/enc424j600.c,
enc424j600_send_packet will stop netdev_queue, recording trans starting time.
1411 static int enc424j600_send_packet(struct sk_buff *skb, struct net_device *ndev)
1412 {
1413     struct enc424j600_net *priv = netdev_priv(ndev);
1414
1415     if (netif_msg_tx_queued(priv))
1416         printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
1417
1418     netif_stop_queue(ndev);  //stop netdev_queue
1419     //start trans
1420 //  printk("<%d:%d",skb->len,skb->data_len);
1421
1422     /* save the timestamp */
1423     priv->netdev->trans_start = jiffies; 
1424 //  printk("enc424j600 ts=%d\n",priv->netdev->trans_start);
1425     /* Remember the skb for deferred processing */
1426     priv->tx_skb = skb;
1427     schedule_work(&priv->tx_work);
1428
1429     return 0;
1430 }

when one packet finished transmitting, a TXIF interrupt will be generated,
netif_wake_queue() will be called and the netdev_queue will be awaken. 

then another packet can be started transmit using enc424j600_send_packet.
1453 static irqreturn_t enc424j600_irq(int irq, void *dev_id)
1454 {
1455     struct enc424j600_net *priv = dev_id;
1456
1457     schedule_work(&priv->irq_work);
1458
1459     return IRQ_HANDLED;
1460 }

1722 static int __devinit enc424j600_probe(struct spi_device *spi)
1723 {
.....
1749     INIT_WORK(&priv->irq_work, enc424j600_irq_work_handler);
.....
 }

1310 static void enc424j600_irq_work_handler(struct work_struct *work)
1311 {
1312     struct enc424j600_net *priv =
1313         container_of(work, struct enc424j600_net, irq_work);
1314     u16 eir;
1315
1316     if (netif_msg_intr(priv))
1317         printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
1318
1319     /* disable further interrupts */
1320     enc424j600_clear_bits(priv, EIEH, INTIE);
....
....
1345         /* TX complete handler */
1346         if ((eirl & TXIF) != 0){
1347             enc424j600_int_tx_handler(priv);
1348         }
1349
1350         /* TX Error handler */
1351         if ((eirl & TXABTIF) != 0){
1352             enc424j600_int_tx_err_handler(priv);
1353         }
....
....
1364     /* re-enable interrupts */
1365     enc424j600_set_bits(priv, EIEH, INTIE);
1366     if (netif_msg_intr(priv))
1367         printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __func__);
1368 }

1213 /**
1214  * Handle completed transmit.
1215  * \param priv The enc424j600 structure.
1216  */
1217 static void enc424j600_int_tx_handler(struct enc424j600_net *priv)
1218 {
1219     if (netif_msg_intr(priv))
1220         printk(KERN_DEBUG DRV_NAME
1221             ": intTX\n");
1222
1223     enc424j600_tx_clear(priv, false);
1224 }

1166 static void enc424j600_tx_clear(struct enc424j600_net *priv, bool err)
1167 {
1168     struct net_device *ndev = priv->netdev;
1169
1170     if (err)
1171         ndev->stats.tx_errors++;
1172     else
1173         ndev->stats.tx_packets++;
1174
1175     if (priv->tx_skb) {
1176         if (!err)
1177             ndev->stats.tx_bytes += priv->tx_skb->len;
1178         dev_kfree_skb(priv->tx_skb);
1179         priv->tx_skb = NULL;
1180     }
1181
1182     netif_wake_queue(ndev);  //awake netdev_queue
1183 }

a watchdog is setup to prevent the ethernet from transmitting timeout. the watchdog time interval is
set in enc424j600.c, each internal end the watchdog will call dev_watchdog() in net/sched/sch_generic.c .
in dev_watchdog(), it will check if ethernet transmition timeout(sch_generic.c:247~255):
when a packet is being transmitted(netif_tx_queue_stopped(txq) return true,sending queue is stopped),
and  the transmitted packed has being transmitted for over dev->watchdog_timeo time (
time_after(jiffies, (trans_start + dev->watchdog_timeo)) return ture), it means the transmitting
is timeout, log info as below will be output:
"WARNING: at net/sched/sch_generic.c:264 dev_watchdog+0x21d/0x230()
NETDEV WATCHDOG: eth0 (enc424j600): transmit queue 0 timed out"

in drivers/net/enc424j600:
1822     dev->netdev_ops = &enc424j600_netdev_ops;
1823     dev->watchdog_timeo = TX_TIMEOUT;   //here to set watchdog time interval
1824     SET_ETHTOOL_OPS(dev, &enc424j600_ethtool_ops);


in net/sched/sch_generic.c:
842 void dev_init_scheduler(struct net_device *dev)
843 {
844     dev->qdisc = &noop_qdisc;
845     netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc);
846     dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
847
848     setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);
849 }

226 static void dev_watchdog(unsigned long arg)
227 {
228     struct net_device *dev = (struct net_device *)arg;
229
230     netif_tx_lock(dev);
231     if (!qdisc_tx_is_noop(dev)) {
232         if (netif_device_present(dev) &&
233             netif_running(dev) &&
234             netif_carrier_ok(dev)) {
235             int some_queue_timedout = 0;
236             unsigned int i;
237             unsigned long trans_start;
238
239             for (i = 0; i < dev->num_tx_queues; i++) {
240                 struct netdev_queue *txq;
241
242                 txq = netdev_get_tx_queue(dev, i);
243                 /*
244                  * old device drivers set dev->trans_start
245                  */
246                 trans_start = txq->trans_start ? : dev->trans_start;
247                 if (netif_tx_queue_stopped(txq) &&
248                     time_after(jiffies, (trans_start +
249                              dev->watchdog_timeo))) {
250                     some_queue_timedout = 1;
251                     printk("jiffies=%d,trans_start=%d,timeo=%d\n"
252                             ,jiffies,trans_start,dev->watchdog_timeo
253                             );
254                     break;
255                 }

256             }
257
258             if (some_queue_timedout) {
259                 char drivername[64];
260                 WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u ti    med out\n",
261                        dev->name, netdev_drivername(dev, drivername, 64), i);
262                 dev->netdev_ops->ndo_tx_timeout(dev);
263             }
264             if (!mod_timer(&dev->watchdog_timer,
265                        round_jiffies(jiffies +
266                              dev->watchdog_timeo)))
267                 dev_hold(dev);
268         }
269     }
270     netif_tx_unlock(dev);
271
272     dev_put(dev);
273 }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值