FreeBSD/sys/dev/ixl/if_ixlv.c
/*********************************************************************
 *  Timer routine
 *
 *  This routine checks for link status,updates statistics,
 *  and runs the watchdog check.
 *
 **********************************************************************/
Timer routine
This routine checks for link status,updates statistics,
and runs the watchdog check.
Timer routine This routine checks for link status updates statistics and runs the watchdog check .
static void
ixlv_local_timer(void *arg)
{
	struct ixlv_sc	*sc = arg;
	struct i40e_hw		*hw = &sc->hw;
	struct ixl_vsi		*vsi = &sc->vsi;
	struct ixl_queue	*que = vsi->queues;
	device_t		dev = sc->dev;
	int			hung = 0;
	u32			mask, val;
	IXLV_CORE_LOCK_ASSERT(sc);
	if (sc->init_state == IXLV_RESET_PENDING)
		return;
	val = rd32(hw, I40E_VFGEN_RSTAT) &
	    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
	if (val != I40E_VFR_VFACTIVE
	    && val != I40E_VFR_COMPLETED) {
		DDPRINTF(dev, "reset in progress! (%d)", val);
		return;
	}
	ixlv_request_stats(sc);
	taskqueue_enqueue(sc->tq, &sc->aq_irq);
	mask = (I40E_VFINT_DYN_CTLN1_INTENA_MASK |
	    I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
	    I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK);
	for (int i = 0; i < vsi->num_queues; i++,que++) {
		if (que->busy)
			wr32(hw, I40E_VFINT_DYN_CTLN1(que->me), mask);
		if (que->busy == IXL_QUEUE_HUNG) {
			++hung;
			vsi->active_queues &= ~((u64)1 << que->me);
			continue;
		} else {
			if ((vsi->active_queues & ((u64)1 << que->me)) == 0)
				vsi->active_queues |= ((u64)1 << que->me);
		}
		if (que->busy >= IXL_MAX_TX_BUSY) {
			device_printf(dev,"Warning queue %d "
			    "appears to be hung!\n", i);
			que->busy = IXL_QUEUE_HUNG;
			++hung;
		}
	}
	if (hung == vsi->num_queues)
		goto hung;
	callout_reset(&sc->timer, hz, ixlv_local_timer, sc);
	return;
hung:
	device_printf(dev, "Local Timer: TX HANG DETECTED - Resetting!!\n");
	sc->init_state = IXLV_RESET_REQUIRED;
	ixlv_init_locked(sc);
}
static void ixlv_local_timer ( void * arg ) { struct ixlv_sc * sc = arg ; struct i40e_hw * hw = & sc -> hw ; struct ixl_vsi * vsi = & sc -> vsi ; struct ixl_queue * que = vsi -> queues ; device_t dev = sc -> dev ; int hung = 0 ; u32 mask , val ; IXLV_CORE_LOCK_ASSERT ( sc ) ; if ( sc -> init_state == IXLV_RESET_PENDING ) return ; val = rd32 ( hw , I40E_VFGEN_RSTAT ) & I40E_VFGEN_RSTAT_VFR_STATE_MASK ; if ( val != I40E_VFR_VFACTIVE && val != I40E_VFR_COMPLETED ) { DDPRINTF ( dev , " " , val ) ; return ; } ixlv_request_stats ( sc ) ; taskqueue_enqueue ( sc -> tq , & sc -> aq_irq ) ; mask = ( I40E_VFINT_DYN_CTLN1_INTENA_MASK | I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK | I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK ) ; for ( int i = 0 ; i < vsi -> num_queues ; i ++ , que ++ ) { if ( que -> busy ) wr32 ( hw , I40E_VFINT_DYN_CTLN1 ( que -> me ) , mask ) ; if ( que -> busy == IXL_QUEUE_HUNG ) { ++ hung ; vsi -> active_queues &= ~ ( ( u64 ) 1 << que -> me ) ; continue ; } else { if ( ( vsi -> active_queues & ( ( u64 ) 1 << que -> me ) ) == 0 ) vsi -> active_queues |= ( ( u64 ) 1 << que -> me ) ; } if ( que -> busy >= IXL_MAX_TX_BUSY ) { device_printf ( dev , " " " \n " , i ) ; que -> busy = IXL_QUEUE_HUNG ; ++ hung ; } } if ( hung == vsi -> num_queues ) goto hung ; callout_reset ( & sc -> timer , hz , ixlv_local_timer , sc ) ; return ; hung : device_printf ( dev , " \n " ) ; sc -> init_state = IXLV_RESET_REQUIRED ; ixlv_init_locked ( sc ) ; }
Timer routine
  This routine checks for link status,updates statistics,
  and runs the watchdog check.
Timer routine This routine checks for link status updates statistics and runs the watchdog check .
/* If Reset is in progress just bail */ /* Check for when PF triggers a VF reset */ /* clean and process any events */ /*
	** Check status on the queues for a hang
	*/ /* Any queues with outstanding work get a sw irq */ /*
		** Each time txeof runs without cleaning, but there
		** are uncleaned descriptors it increments busy. If
		** we get to 5 we declare it hung.
		*/ /* Mark the queue as inactive */ /* Check if we've come back from hung */ /* Only reset when all queues show hung */