FreeBSD/sys/dev/e1000/if_igb.c
/*********************************************************************
 *  Timer routine:
 *  	This routine checks for link status,
 *	updates statistics, and does the watchdog.
 *
 **********************************************************************/
Timer routine:
This routine checks for link status,
updates statistics, and does the watchdog.
Timer routine : This routine checks for link status updates statistics and does the watchdog .
static void
igb_local_timer(void *arg)
{
	struct adapter		*adapter = arg;
	device_t		dev = adapter->dev;
	struct ifnet		*ifp = adapter->ifp;
	struct tx_ring		*txr = adapter->tx_rings;
	struct igb_queue	*que = adapter->queues;
	int			hung = 0, busy = 0;
	IGB_CORE_LOCK_ASSERT(adapter);
	igb_update_link_status(adapter);
	igb_update_stats_counters(adapter);
	for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
		if ((txr->queue_status & IGB_QUEUE_HUNG) &&
		    (adapter->pause_frames == 0))
			++hung;
		if (txr->queue_status & IGB_QUEUE_DEPLETED)
			++busy;
		if ((txr->queue_status & IGB_QUEUE_IDLE) == 0)
			taskqueue_enqueue(que->tq, &que->que_task);
	}
	if (hung == adapter->num_queues)
		goto timeout;
	if (busy == adapter->num_queues)
		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
	else if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) &&
	    (busy < adapter->num_queues))
		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
	adapter->pause_frames = 0;
	callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
#ifndef DEVICE_POLLING
	E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->que_mask);
#endif
	return;
timeout:
	device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
	device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", txr->me,
            E1000_READ_REG(&adapter->hw, E1000_TDH(txr->me)),
            E1000_READ_REG(&adapter->hw, E1000_TDT(txr->me)));
	device_printf(dev,"TX(%d) desc avail = %d,"
            "Next TX to Clean = %d\n",
            txr->me, txr->tx_avail, txr->next_to_clean);
	adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
	adapter->watchdog_events++;
	igb_init_locked(adapter);
}
static void igb_local_timer ( void * arg ) { struct adapter * adapter = arg ; device_t dev = adapter -> dev ; struct ifnet * ifp = adapter -> ifp ; struct tx_ring * txr = adapter -> tx_rings ; struct igb_queue * que = adapter -> queues ; int hung = 0 , busy = 0 ; IGB_CORE_LOCK_ASSERT ( adapter ) ; igb_update_link_status ( adapter ) ; igb_update_stats_counters ( adapter ) ; for ( int i = 0 ; i < adapter -> num_queues ; i ++ , que ++ , txr ++ ) { if ( ( txr -> queue_status & IGB_QUEUE_HUNG ) && ( adapter -> pause_frames == 0 ) ) ++ hung ; if ( txr -> queue_status & IGB_QUEUE_DEPLETED ) ++ busy ; if ( ( txr -> queue_status & IGB_QUEUE_IDLE ) == 0 ) taskqueue_enqueue ( que -> tq , & que -> que_task ) ; } if ( hung == adapter -> num_queues ) goto timeout ; if ( busy == adapter -> num_queues ) ifp -> if_drv_flags |= IFF_DRV_OACTIVE ; else if ( ( ifp -> if_drv_flags & IFF_DRV_OACTIVE ) && ( busy < adapter -> num_queues ) ) ifp -> if_drv_flags &= ~ IFF_DRV_OACTIVE ; adapter -> pause_frames = 0 ; callout_reset ( & adapter -> timer , hz , igb_local_timer , adapter ) ; #ifndef DEVICE_POLLING E1000_WRITE_REG ( & adapter -> hw , E1000_EICS , adapter -> que_mask ) ; #endif return ; timeout : device_printf ( adapter -> dev , " \n " ) ; device_printf ( dev , " \n " , txr -> me , E1000_READ_REG ( & adapter -> hw , E1000_TDH ( txr -> me ) ) , E1000_READ_REG ( & adapter -> hw , E1000_TDT ( txr -> me ) ) ) ; device_printf ( dev , " " " \n " , txr -> me , txr -> tx_avail , txr -> next_to_clean ) ; adapter -> ifp -> if_drv_flags &= ~ IFF_DRV_RUNNING ; adapter -> watchdog_events ++ ; igb_init_locked ( adapter ) ; }
Timer routine:
      This routine checks for link status,
      updates statistics, and does the watchdog.
Timer routine : This routine checks for link status updates statistics and does the watchdog .
/*
        ** Check the TX queues status
	**	- central locked handling of OACTIVE
	**	- watchdog only if all queues show hung
        */ /* Schedule all queue interrupts - deadlock protection */