FreeBSD/sys/dev/cxgb/cxgb_sge.c
/**
 *	sge_timer_cb - perform periodic maintenance of an SGE qset
 *	@data: the SGE queue set to maintain
 *
 *	Runs periodically from a timer to perform maintenance of an SGE queue
 *	set.  It performs two tasks:
 *
 *	a) Cleans up any completed Tx descriptors that may still be pending.
 *	Normal descriptor cleanup happens when new packets are added to a Tx
 *	queue so this timer is relatively infrequent and does any cleanup only
 *	if the Tx queue has not seen any new packets in a while.  We make a
 *	best effort attempt to reclaim descriptors, in that we don't wait
 *	around if we cannot get a queue's lock (which most likely is because
 *	someone else is queueing new packets and so will also handle the clean
 *	up).  Since control queues use immediate data exclusively we don't
 *	bother cleaning them up here.
 *
 *	b) Replenishes Rx queues that have run out due to memory shortage.
 *	Normally new Rx buffers are added when existing ones are consumed but
 *	when out of memory a queue can become empty.  We try to add only a few
 *	buffers here, the queue will be replenished fully as these new buffers
 *	are used up if memory shortage has subsided.
 *	
 *	c) Return coalesced response queue credits in case a response queue is
 *	starved.
 *
 *	d) Ring doorbells for T304 tunnel queues since we have seen doorbell 
 *	fifo overflows and the FW doesn't implement any recovery scheme yet.
 */
perform periodic maintenance of an SGE qset
@data: the SGE queue set to maintain

Runs periodically from a timer to perform maintenance of an SGE queue
set.  It performs two tasks.

a) Cleans up any completed Tx descriptors that may still be pending.
Normal descriptor cleanup happens when new packets are added to a Tx
queue so this timer is relatively infrequent and does any cleanup only
if the Tx queue has not seen any new packets in a while.  We make a
best effort attempt to reclaim descriptors, in that we don't wait
around if we cannot get a queue's lock (which most likely is because
someone else is queueing new packets and so will also handle the clean
up).  Since control queues use immediate data exclusively we don't
bother cleaning them up here.

b) Replenishes Rx queues that have run out due to memory shortage.
Normally new Rx buffers are added when existing ones are consumed but
when out of memory a queue can become empty.  We try to add only a few
buffers here, the queue will be replenished fully as these new buffers
are used up if memory shortage has subsided.

c) Return coalesced response queue credits in case a response queue is
starved.

d) Ring doorbells for T304 tunnel queues since we have seen doorbell
fifo overflows and the FW doesn't implement any recovery scheme yet.
perform periodic maintenance of an SGE qset @data : the SGE queue set to maintain Runs periodically from a timer to perform maintenance of an SGE queue set . It performs two tasks . a ) Cleans up any completed Tx descriptors that may still be pending . Normal descriptor cleanup happens when new packets are added to a Tx queue so this timer is relatively infrequent and does any cleanup only if the Tx queue has not seen any new packets in a while . We make a best effort attempt to reclaim descriptors in that we don ' t wait around if we cannot get a queue ' s lock ( which most likely is because someone else is queueing new packets and so will also handle the clean up ) . Since control queues use immediate data exclusively we don ' t bother cleaning them up here . b ) Replenishes Rx queues that have run out due to memory shortage . Normally new Rx buffers are added when existing ones are consumed but when out of memory a queue can become empty . We try to add only a few buffers here the queue will be replenished fully as these new buffers are used up if memory shortage has subsided . c ) Return coalesced response queue credits in case a response queue is starved . d ) Ring doorbells for T304 tunnel queues since we have seen doorbell fifo overflows and the FW doesn ' t implement any recovery scheme yet .
static void
sge_timer_cb(void *arg)
{
	adapter_t *sc = arg;
	if ((sc->flags & USING_MSIX) == 0) {
		struct port_info *pi;
		struct sge_qset *qs;
		struct sge_txq  *txq;
		int i, j;
		int reclaim_ofl, refill_rx;
		if (sc->open_device_map == 0) 
			return;
		for (i = 0; i < sc->params.nports; i++) {
			pi = &sc->port[i];
			for (j = 0; j < pi->nqsets; j++) {
				qs = &sc->sge.qs[pi->first_qset + j];
				txq = &qs->txq[0];
				reclaim_ofl = txq[TXQ_OFLD].processed - txq[TXQ_OFLD].cleaned;
				refill_rx = ((qs->fl[0].credits < qs->fl[0].size) || 
				    (qs->fl[1].credits < qs->fl[1].size));
				if (reclaim_ofl || refill_rx) {
					taskqueue_enqueue(sc->tq, &pi->timer_reclaim_task);
					break;
				}
			}
		}
	}
	if (sc->params.nports > 2) {
		int i;
		for_each_port(sc, i) {
			struct port_info *pi = &sc->port[i];
			t3_write_reg(sc, A_SG_KDOORBELL, 
				     F_SELEGRCNTX | 
				     (FW_TUNNEL_SGEEC_START + pi->first_qset));
		}
	}	
	if (((sc->flags & USING_MSIX) == 0 || sc->params.nports > 2) &&
	    sc->open_device_map != 0)
		callout_reset(&sc->sge_timer_ch, TX_RECLAIM_PERIOD, sge_timer_cb, sc);
}
static void sge_timer_cb ( void * arg ) { adapter_t * sc = arg ; if ( ( sc -> flags & USING_MSIX ) == 0 ) { struct port_info * pi ; struct sge_qset * qs ; struct sge_txq * txq ; int i , j ; int reclaim_ofl , refill_rx ; if ( sc -> open_device_map == 0 ) return ; for ( i = 0 ; i < sc -> params . nports ; i ++ ) { pi = & sc -> port [ i ] ; for ( j = 0 ; j < pi -> nqsets ; j ++ ) { qs = & sc -> sge . qs [ pi -> first_qset + j ] ; txq = & qs -> txq [ 0 ] ; reclaim_ofl = txq [ TXQ_OFLD ] . processed - txq [ TXQ_OFLD ] . cleaned ; refill_rx = ( ( qs -> fl [ 0 ] . credits < qs -> fl [ 0 ] . size ) || ( qs -> fl [ 1 ] . credits < qs -> fl [ 1 ] . size ) ) ; if ( reclaim_ofl || refill_rx ) { taskqueue_enqueue ( sc -> tq , & pi -> timer_reclaim_task ) ; break ; } } } } if ( sc -> params . nports > 2 ) { int i ; for_each_port ( sc , i ) { struct port_info * pi = & sc -> port [ i ] ; t3_write_reg ( sc , A_SG_KDOORBELL , F_SELEGRCNTX | ( FW_TUNNEL_SGEEC_START + pi -> first_qset ) ) ; } } if ( ( ( sc -> flags & USING_MSIX ) == 0 || sc -> params . nports > 2 ) && sc -> open_device_map != 0 ) callout_reset ( & sc -> sge_timer_ch , TX_RECLAIM_PERIOD , sge_timer_cb , sc ) ; }
sge_timer_cb - perform periodic maintenance of an SGE qset
      @data: the SGE queue set to maintain
sge_timer_cb - perform periodic maintenance of an SGE qset @data : the SGE queue set to maintain