From owner-freebsd-net@FreeBSD.ORG Wed Sep 26 13:53:32 2012 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B9839106567D for ; Wed, 26 Sep 2012 13:53:32 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from bigwig.baldwin.cx (bigknife-pt.tunnel.tserv9.chi1.ipv6.he.net [IPv6:2001:470:1f10:75::2]) by mx1.freebsd.org (Postfix) with ESMTP id 77ED78FC30 for ; Wed, 26 Sep 2012 13:53:32 +0000 (UTC) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id A7476B978; Wed, 26 Sep 2012 09:53:31 -0400 (EDT) From: John Baldwin To: Vijay Singh Date: Wed, 26 Sep 2012 09:53:27 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110714-p20; KDE/4.5.5; amd64; ; ) References: <201208170941.54482.jhb@freebsd.org> In-Reply-To: MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201209260953.27806.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.7 (bigwig.baldwin.cx); Wed, 26 Sep 2012 09:53:31 -0400 (EDT) Cc: freebsd-net@freebsd.org, Jack Vogel Subject: Re: ixgbe rx & tx locks X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Sep 2012 13:53:32 -0000 On Tuesday, September 25, 2012 4:19:01 pm Vijay Singh wrote: > > Vijay, can you test this to see if it helps with your test case? > > > >> Jack > > John, apologies for the delay. I have some data to share now. > > With your patch, the transmit side lock contention is all gone. > However I still see receive side contention. I have MSI/X enabled, > with one hw queue per-port. Well, that's progress at least. Jack, can you ok this patch? It is just the changes to adjust the deferred tx handling and doesn't include any watchdog changes. The igb fix is just a comestic nit: Index: dev/e1000/if_igb.h =================================================================== --- dev/e1000/if_igb.h (revision 240960) +++ dev/e1000/if_igb.h (working copy) @@ -299,9 +299,9 @@ struct igb_tx_buffer *tx_buffers; #if __FreeBSD_version >= 800000 struct buf_ring *br; + struct task txq_task; #endif bus_dma_tag_t txtag; - struct task txq_task; u32 bytes; u32 packets; Index: dev/ixgbe/ixgbe.c =================================================================== --- dev/ixgbe/ixgbe.c (revision 240960) +++ dev/ixgbe/ixgbe.c (working copy) @@ -104,13 +104,15 @@ static int ixgbe_attach(device_t); static int ixgbe_detach(device_t); static int ixgbe_shutdown(device_t); -static void ixgbe_start(struct ifnet *); -static void ixgbe_start_locked(struct tx_ring *, struct ifnet *); #if __FreeBSD_version >= 800000 static int ixgbe_mq_start(struct ifnet *, struct mbuf *); static int ixgbe_mq_start_locked(struct ifnet *, struct tx_ring *, struct mbuf *); static void ixgbe_qflush(struct ifnet *); +static void ixgbe_deferred_mq_start(void *, int); +#else +static void ixgbe_start(struct ifnet *); +static void ixgbe_start_locked(struct tx_ring *, struct ifnet *); #endif static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); static void ixgbe_init(void *); @@ -631,6 +633,7 @@ { struct adapter *adapter = device_get_softc(dev); struct ix_queue *que = adapter->queues; + struct tx_ring *txr = adapter->tx_rings; u32 ctrl_ext; INIT_DEBUGOUT("ixgbe_detach: begin"); @@ -645,8 +648,11 @@ ixgbe_stop(adapter); IXGBE_CORE_UNLOCK(adapter); - for (int i = 0; i < adapter->num_queues; i++, que++) { + for (int i = 0; i < adapter->num_queues; i++, que++, txr++) { if (que->tq) { +#if __FreeBSD_version >= 800000 + taskqueue_drain(que->tq, &txr->txq_task); +#endif taskqueue_drain(que->tq, &que->que_task); taskqueue_free(que->tq); } @@ -708,6 +714,7 @@ } +#if __FreeBSD_version < 800000 /********************************************************************* * Transmit entry point * @@ -779,7 +786,7 @@ return; } -#if __FreeBSD_version >= 800000 +#else /* ** Multiqueue Transmit driver ** @@ -807,7 +814,7 @@ IXGBE_TX_UNLOCK(txr); } else { err = drbr_enqueue(ifp, txr->br, m); - taskqueue_enqueue(que->tq, &que->que_task); + taskqueue_enqueue(que->tq, &txr->txq_task); } return (err); @@ -873,6 +880,22 @@ } /* + * Called from a taskqueue to drain queued transmit packets. + */ +static void +ixgbe_deferred_mq_start(void *arg, int pending) +{ + struct tx_ring *txr = arg; + struct adapter *adapter = txr->adapter; + struct ifnet *ifp = adapter->ifp; + + IXGBE_TX_LOCK(txr); + if (!drbr_empty(ifp, txr->br)) + ixgbe_mq_start_locked(ifp, txr, NULL); + IXGBE_TX_UNLOCK(txr); +} + +/* ** Flush all ring buffers */ static void @@ -2230,6 +2258,9 @@ { device_t dev = adapter->dev; struct ix_queue *que = adapter->queues; +#if __FreeBSD_version >= 800000 + struct tx_ring *txr = adapter->tx_rings; +#endif int error, rid = 0; /* MSI RID at 1 */ @@ -2249,6 +2280,9 @@ * Try allocating a fast interrupt and the associated deferred * processing contexts. */ +#if __FreeBSD_version >= 800000 + TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr); +#endif TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, taskqueue_thread_enqueue, &que->tq); @@ -2295,9 +2329,10 @@ { device_t dev = adapter->dev; struct ix_queue *que = adapter->queues; + struct tx_ring *txr = adapter->tx_rings; int error, rid, vector = 0; - for (int i = 0; i < adapter->num_queues; i++, vector++, que++) { + for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) { rid = vector + 1; que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); @@ -2327,6 +2362,9 @@ if (adapter->num_queues > 1) bus_bind_intr(dev, que->res, i); +#if __FreeBSD_version >= 800000 + TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr); +#endif TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que); que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT, taskqueue_thread_enqueue, &que->tq); @@ -2570,12 +2608,13 @@ ifp->if_softc = adapter; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ixgbe_ioctl; - ifp->if_start = ixgbe_start; #if __FreeBSD_version >= 800000 ifp->if_transmit = ixgbe_mq_start; ifp->if_qflush = ixgbe_qflush; +#else + ifp->if_start = ixgbe_start; + IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2); #endif - ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 2; ether_ifattach(ifp, adapter->hw.mac.addr); Index: dev/ixgbe/ixgbe.h =================================================================== --- dev/ixgbe/ixgbe.h (revision 240960) +++ dev/ixgbe/ixgbe.h (working copy) @@ -314,6 +314,7 @@ char mtx_name[16]; #if __FreeBSD_version >= 800000 struct buf_ring *br; + struct task txq_task; #endif #ifdef IXGBE_FDIR u16 atr_sample; -- John Baldwin