From owner-svn-src-projects@FreeBSD.ORG Fri Apr 3 18:12:12 2015 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C3D5DB65; Fri, 3 Apr 2015 18:12:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A416DE42; Fri, 3 Apr 2015 18:12:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t33ICC1b004156; Fri, 3 Apr 2015 18:12:12 GMT (envelope-from sbruno@FreeBSD.org) Received: (from sbruno@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t33ICCRT004151; Fri, 3 Apr 2015 18:12:12 GMT (envelope-from sbruno@FreeBSD.org) Message-Id: <201504031812.t33ICCRT004151@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: sbruno set sender to sbruno@FreeBSD.org using -f From: Sean Bruno Date: Fri, 3 Apr 2015 18:12:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r281045 - projects/em_mq/sys/dev/e1000 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Apr 2015 18:12:13 -0000 Author: sbruno Date: Fri Apr 3 18:12:11 2015 New Revision: 281045 URL: https://svnweb.freebsd.org/changeset/base/281045 Log: Synchronize and check queue_status better (yet more stolen from igb) Modified: projects/em_mq/sys/dev/e1000/if_em.c projects/em_mq/sys/dev/e1000/if_em.h Modified: projects/em_mq/sys/dev/e1000/if_em.c ============================================================================== --- projects/em_mq/sys/dev/e1000/if_em.c Fri Apr 3 18:01:51 2015 (r281044) +++ projects/em_mq/sys/dev/e1000/if_em.c Fri Apr 3 18:12:11 2015 (r281045) @@ -899,7 +899,8 @@ em_resume(device_t dev) for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { EM_TX_LOCK(txr); #ifdef EM_MULTIQUEUE - if (!drbr_empty(ifp, txr->br)) + if (((txr->queue_status & EM_QUEUE_DEPLETED) == 0) && + !drbr_empty(ifp, txr->br)) em_mq_start_locked(ifp, txr); #else if (!if_sendq_empty(ifp)) @@ -957,7 +958,7 @@ em_start_locked(if_t ifp, struct tx_ring /* Set timeout in case hardware has problems transmitting. */ txr->watchdog_time = ticks; - txr->queue_status = EM_QUEUE_WORKING; + txr->queue_status |= EM_QUEUE_WORKING; } return; @@ -1057,14 +1058,14 @@ em_mq_start_locked(if_t ifp, struct tx_r if (enq > 0) { /* Set the watchdog */ - txr->queue_status = EM_QUEUE_WORKING; + txr->queue_status |= EM_QUEUE_WORKING; txr->watchdog_time = ticks; } - if (txr->tx_avail < EM_MAX_SCATTER) + if (txr->tx_avail < (adapter->num_tx_desc / 8)) em_txeof(txr); if (txr->tx_avail < EM_MAX_SCATTER) - if_setdrvflagbits(ifp, IFF_DRV_OACTIVE,0); + txr->queue_status |= EM_QUEUE_DEPLETED; return (err); } @@ -1588,7 +1589,8 @@ em_msix_tx(void *arg) EM_TX_LOCK(txr); em_txeof(txr); #ifdef EM_MULTIQUEUE - if (!drbr_empty(ifp, txr->br)) + if (((txr->queue_status & EM_QUEUE_DEPLETED) == 0) && + !drbr_empty(ifp, txr->br)) em_mq_start_locked(ifp, txr); #else if (!if_sendq_empty(ifp)) @@ -2251,6 +2253,7 @@ em_local_timer(void *arg) struct tx_ring *txr = adapter->tx_rings; struct rx_ring *rxr = adapter->rx_rings; u32 trigger; + int hung = 0, busy = 0; EM_CORE_LOCK_ASSERT(adapter); @@ -2274,14 +2277,24 @@ em_local_timer(void *arg) ** and the HUNG state will be static if set. */ for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { - if ((txr->queue_status == EM_QUEUE_HUNG) && + if ((txr->queue_status & EM_QUEUE_HUNG) && (adapter->pause_frames == 0)) - goto hung; + ++hung; + if (txr->queue_status & EM_QUEUE_DEPLETED) + ++busy; /* Schedule a TX tasklet if needed */ - if (txr->tx_avail <= EM_MAX_SCATTER) + if ((txr->queue_status & EM_QUEUE_IDLE) == 0) taskqueue_enqueue(txr->tq, &txr->tx_task); } + if (hung == adapter->num_tx_queues) + goto timeout; + if (busy == adapter->num_tx_queues) + if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); + else if ((if_getdrvflags(adapter->ifp) & IFF_DRV_OACTIVE) && + (busy < adapter->num_tx_queues)) + if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); + adapter->pause_frames = 0; callout_reset(&adapter->timer, hz, em_local_timer, adapter); #ifndef DEVICE_POLLING @@ -2289,7 +2302,7 @@ em_local_timer(void *arg) E1000_WRITE_REG(&adapter->hw, E1000_ICS, trigger); #endif return; -hung: +timeout: /* Looks like we're hung */ device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); device_printf(adapter->dev, @@ -2301,11 +2314,9 @@ hung: txr->me, txr->tx_avail, txr->next_to_clean); if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); adapter->watchdog_events++; - adapter->pause_frames = 0; em_init_locked(adapter); } - static void em_update_link_status(struct adapter *adapter) { @@ -2370,10 +2381,11 @@ em_update_link_status(struct adapter *ad if (bootverbose) device_printf(dev, "Link is Down\n"); adapter->link_active = 0; - /* Link down, disable watchdog */ + /* This can sleep */ + if_link_state_change(ifp, LINK_STATE_DOWN); + /* Reset queue state */ for (int i = 0; i < adapter->num_tx_queues; i++, txr++) txr->queue_status = EM_QUEUE_IDLE; - if_link_state_change(ifp, LINK_STATE_DOWN); } } @@ -3411,7 +3423,6 @@ em_setup_transmit_ring(struct tx_ring *t /* Set number of descriptors available */ txr->tx_avail = adapter->num_tx_desc; - txr->queue_status = EM_QUEUE_IDLE; /* Clear checksum offload context. */ txr->last_hw_offload = 0; @@ -3932,17 +3943,10 @@ em_txeof(struct tx_ring *txr) ** will examine this and do a reset if needed. */ if ((!processed) && ((ticks - txr->watchdog_time) > EM_WATCHDOG)) - txr->queue_status = EM_QUEUE_HUNG; + txr->queue_status |= EM_QUEUE_HUNG; - /* - * If we have a minimum free, clear IFF_DRV_OACTIVE - * to tell the stack that it is OK to send packets. - * Notice that all writes of OACTIVE happen under the - * TX lock which, with a single queue, guarantees - * sanity. - */ - if (txr->tx_avail >= EM_MAX_SCATTER) - if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); + if (txr->tx_avail >= (adapter->num_tx_desc / 8)) + txr->queue_status &= ~EM_QUEUE_DEPLETED; /* Disable watchdog if all clean */ if (txr->tx_avail == adapter->num_tx_desc) { Modified: projects/em_mq/sys/dev/e1000/if_em.h ============================================================================== --- projects/em_mq/sys/dev/e1000/if_em.h Fri Apr 3 18:01:51 2015 (r281044) +++ projects/em_mq/sys/dev/e1000/if_em.h Fri Apr 3 18:12:11 2015 (r281045) @@ -191,6 +191,7 @@ #define EM_QUEUE_IDLE 0 #define EM_QUEUE_WORKING 1 #define EM_QUEUE_HUNG 2 +#define EM_QUEUE_DEPLETED 4 /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be