From owner-svn-src-stable-10@FreeBSD.ORG Sun May 11 17:18:11 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DD96E23B; Sun, 11 May 2014 17:18:10 +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 C915E2447; Sun, 11 May 2014 17:18:10 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4BHIAps084925; Sun, 11 May 2014 17:18:10 GMT (envelope-from gnn@svn.freebsd.org) Received: (from gnn@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4BHI9eT084919; Sun, 11 May 2014 17:18:09 GMT (envelope-from gnn@svn.freebsd.org) Message-Id: <201405111718.s4BHI9eT084919@svn.freebsd.org> From: "George V. Neville-Neil" Date: Sun, 11 May 2014 17:18:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r265884 - in stable/10/sys/dev/sfxge: . common X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 May 2014 17:18:11 -0000 Author: gnn Date: Sun May 11 17:18:09 2014 New Revision: 265884 URL: http://svnweb.freebsd.org/changeset/base/265884 Log: MFC: 263302, 264461, 264772 263302: fix mbuf leak if it does not fit in software queue 264461: Commit various fixes for the SolarFlare drivers, in particular this set of patches fixes support for systems with > 32 cores. Details include sfxge: RXQ index (not label) comes from FW in flush done/failed events Change the second argument name of the efx_rxq_flush_done_ev_t and efx_rxq_flush_failed_ev_t prototypes to highlight that RXQ index (not label) comes from FW in flush done and failed events. sfxge: TXQ index (not label) comes from FW in flush done event Change the second argument name of the efx_txq_flush_done_ev_t prototype to highlight that TXQ index (not label) comes from FW in flush done event. sfxge: use TXQ type as label to support more than 32 TXQs There are 3 TXQs in event queue 0 and 1 TXQ (with TCP/UDP checksum offload) in all other event queues. 264772: Check that port is started when MAC filter is set The MAC filter set may be called without softc_lock held in the case of SIOCADDMULTI and SIOCDELMULTI ioctls. The ioctl handler checks IFF_DRV_RUNNING flag which implies port started, but it is not guaranteed to remain. softc_lock shared lock can't be held in the case of these ioctls processing, since it results in failure where kernel complains that non-sleepable lock is held in sleeping thread. Both problems are repeatable on LAG with LACP proto bring up. Submitted by: Andrew Rybchenko Sponsored by: Solarflare Communications, Inc. Modified: stable/10/sys/dev/sfxge/common/efx.h stable/10/sys/dev/sfxge/common/efx_ev.c stable/10/sys/dev/sfxge/common/efx_tx.c stable/10/sys/dev/sfxge/sfxge_ev.c stable/10/sys/dev/sfxge/sfxge_port.c stable/10/sys/dev/sfxge/sfxge_tx.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/sfxge/common/efx.h ============================================================================== --- stable/10/sys/dev/sfxge/common/efx.h Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/common/efx.h Sun May 11 17:18:09 2014 (r265884) @@ -1360,17 +1360,17 @@ typedef __checkReturn boolean_t typedef __checkReturn boolean_t (*efx_rxq_flush_done_ev_t)( __in_opt void *arg, - __in uint32_t label); + __in uint32_t rxq_index); typedef __checkReturn boolean_t (*efx_rxq_flush_failed_ev_t)( __in_opt void *arg, - __in uint32_t label); + __in uint32_t rxq_index); typedef __checkReturn boolean_t (*efx_txq_flush_done_ev_t)( __in_opt void *arg, - __in uint32_t label); + __in uint32_t txq_index); typedef __checkReturn boolean_t (*efx_software_ev_t)( Modified: stable/10/sys/dev/sfxge/common/efx_ev.c ============================================================================== --- stable/10/sys/dev/sfxge/common/efx_ev.c Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/common/efx_ev.c Sun May 11 17:18:09 2014 (r265884) @@ -407,24 +407,24 @@ efx_ev_driver( switch (EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBCODE)) { case FSE_AZ_TX_DESCQ_FLS_DONE_EV: { - uint32_t label; + uint32_t txq_index; EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE); - label = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); + txq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); - EFSYS_PROBE1(tx_descq_fls_done, uint32_t, label); + EFSYS_PROBE1(tx_descq_fls_done, uint32_t, txq_index); EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL); - should_abort = eecp->eec_txq_flush_done(arg, label); + should_abort = eecp->eec_txq_flush_done(arg, txq_index); break; } case FSE_AZ_RX_DESCQ_FLS_DONE_EV: { - uint32_t label; + uint32_t rxq_index; uint32_t failed; - label = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID); + rxq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID); failed = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL); EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL); @@ -433,15 +433,15 @@ efx_ev_driver( if (failed) { EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_FAILED); - EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, label); + EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, rxq_index); - should_abort = eecp->eec_rxq_flush_failed(arg, label); + should_abort = eecp->eec_rxq_flush_failed(arg, rxq_index); } else { EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE); - EFSYS_PROBE1(rx_descq_fls_done, uint32_t, label); + EFSYS_PROBE1(rx_descq_fls_done, uint32_t, rxq_index); - should_abort = eecp->eec_rxq_flush_done(arg, label); + should_abort = eecp->eec_rxq_flush_done(arg, rxq_index); } break; Modified: stable/10/sys/dev/sfxge/common/efx_tx.c ============================================================================== --- stable/10/sys/dev/sfxge/common/efx_tx.c Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/common/efx_tx.c Sun May 11 17:18:09 2014 (r265884) @@ -290,7 +290,7 @@ efx_tx_qcreate( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX); EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS == (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH)); - EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS); + /* EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);*/ EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit); if (!ISP2(n) || !(n & EFX_TXQ_NDESCS_MASK)) { Modified: stable/10/sys/dev/sfxge/sfxge_ev.c ============================================================================== --- stable/10/sys/dev/sfxge/sfxge_ev.c Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/sfxge_ev.c Sun May 11 17:18:09 2014 (r265884) @@ -150,17 +150,18 @@ sfxge_ev_exception(void *arg, uint32_t c } static boolean_t -sfxge_ev_rxq_flush_done(void *arg, uint32_t label) +sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index) { struct sfxge_evq *evq; struct sfxge_softc *sc; struct sfxge_rxq *rxq; unsigned int index; + unsigned int label; uint16_t magic; evq = (struct sfxge_evq *)arg; sc = evq->sc; - rxq = sc->rxq[label]; + rxq = sc->rxq[rxq_index]; KASSERT(rxq != NULL, ("rxq == NULL")); @@ -168,6 +169,7 @@ sfxge_ev_rxq_flush_done(void *arg, uint3 index = rxq->index; evq = sc->evq[index]; + label = rxq_index; KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level")); magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label; @@ -180,17 +182,18 @@ sfxge_ev_rxq_flush_done(void *arg, uint3 } static boolean_t -sfxge_ev_rxq_flush_failed(void *arg, uint32_t label) +sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index) { struct sfxge_evq *evq; struct sfxge_softc *sc; struct sfxge_rxq *rxq; unsigned int index; + unsigned int label; uint16_t magic; evq = (struct sfxge_evq *)arg; sc = evq->sc; - rxq = sc->rxq[label]; + rxq = sc->rxq[rxq_index]; KASSERT(rxq != NULL, ("rxq == NULL")); @@ -198,6 +201,7 @@ sfxge_ev_rxq_flush_failed(void *arg, uin index = rxq->index; evq = sc->evq[index]; + label = rxq_index; KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label")); magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label; @@ -209,18 +213,27 @@ sfxge_ev_rxq_flush_failed(void *arg, uin return (B_FALSE); } +static struct sfxge_txq * +sfxge_get_txq_by_label(struct sfxge_evq *evq, enum sfxge_txq_type label) +{ + unsigned int index; + + KASSERT((evq->index == 0 && label < SFXGE_TXQ_NTYPES) || + (label == SFXGE_TXQ_IP_TCP_UDP_CKSUM), ("unexpected txq label")); + index = (evq->index == 0) ? label : (evq->index - 1 + SFXGE_TXQ_NTYPES); + return evq->sc->txq[index]; +} + static boolean_t sfxge_ev_tx(void *arg, uint32_t label, uint32_t id) { struct sfxge_evq *evq; - struct sfxge_softc *sc; struct sfxge_txq *txq; unsigned int stop; unsigned int delta; evq = (struct sfxge_evq *)arg; - sc = evq->sc; - txq = sc->txq[label]; + txq = sfxge_get_txq_by_label(evq, label); KASSERT(txq != NULL, ("txq == NULL")); KASSERT(evq->index == txq->evq_index, @@ -251,16 +264,17 @@ done: } static boolean_t -sfxge_ev_txq_flush_done(void *arg, uint32_t label) +sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index) { struct sfxge_evq *evq; struct sfxge_softc *sc; struct sfxge_txq *txq; + unsigned int label; uint16_t magic; evq = (struct sfxge_evq *)arg; sc = evq->sc; - txq = sc->txq[label]; + txq = sc->txq[txq_index]; KASSERT(txq != NULL, ("txq == NULL")); KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED, @@ -269,6 +283,7 @@ sfxge_ev_txq_flush_done(void *arg, uint3 /* Resend a software event on the correct queue */ evq = sc->evq[txq->evq_index]; + label = txq->type; KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label")); magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label; @@ -325,7 +340,7 @@ sfxge_ev_software(void *arg, uint16_t ma break; } case SFXGE_MAGIC_TX_QFLUSH_DONE: { - struct sfxge_txq *txq = sc->txq[label]; + struct sfxge_txq *txq = sfxge_get_txq_by_label(evq, label); KASSERT(txq != NULL, ("txq == NULL")); KASSERT(evq->index == txq->evq_index, Modified: stable/10/sys/dev/sfxge/sfxge_port.c ============================================================================== --- stable/10/sys/dev/sfxge/sfxge_port.c Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/sfxge_port.c Sun May 11 17:18:09 2014 (r265884) @@ -320,10 +320,21 @@ sfxge_mac_filter_set(struct sfxge_softc struct sfxge_port *port = &sc->port; int rc; - KASSERT(port->init_state == SFXGE_PORT_STARTED, ("port not started")); - mtx_lock(&port->lock); - rc = sfxge_mac_filter_set_locked(sc); + /* + * The function may be called without softc_lock held in the + * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler + * checks IFF_DRV_RUNNING flag which implies port started, but + * it is not guaranteed to remain. softc_lock shared lock can't + * be held in the case of these ioctls processing, since it + * results in failure where kernel complains that non-sleepable + * lock is held in sleeping thread. Both problems are repeatable + * on LAG with LACP proto bring up. + */ + if (port->init_state == SFXGE_PORT_STARTED) + rc = sfxge_mac_filter_set_locked(sc); + else + rc = 0; mtx_unlock(&port->lock); return rc; } Modified: stable/10/sys/dev/sfxge/sfxge_tx.c ============================================================================== --- stable/10/sys/dev/sfxge/sfxge_tx.c Sun May 11 16:49:31 2014 (r265883) +++ stable/10/sys/dev/sfxge/sfxge_tx.c Sun May 11 17:18:09 2014 (r265884) @@ -27,6 +27,21 @@ * SUCH DAMAGE. */ +/* Theory of operation: + * + * Tx queues allocation and mapping + * + * One Tx queue with enabled checksum offload is allocated per Rx channel + * (event queue). Also 2 Tx queues (one without checksum offload and one + * with IP checksum offload only) are allocated and bound to event queue 0. + * sfxge_txq_type is used as Tx queue label. + * + * So, event queue plus label mapping to Tx queue index is: + * if event queue index is 0, TxQ-index = TxQ-label * [0..SFXGE_TXQ_NTYPES) + * else TxQ-index = SFXGE_TXQ_NTYPES + EvQ-index - 1 + * See sfxge_get_txq_by_label() sfxge_ev.c + */ + #include __FBSDID("$FreeBSD$"); @@ -536,6 +551,7 @@ sfxge_tx_packet_add(struct sfxge_txq *tx return (0); fail: + m_freem(m); return (rc); } @@ -1177,7 +1193,7 @@ sfxge_tx_qstart(struct sfxge_softc *sc, } /* Create the common code transmit queue. */ - if ((rc = efx_tx_qcreate(sc->enp, index, index, esmp, + if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp, SFXGE_NDESCS, txq->buf_base_id, flags, evq->common, &txq->common)) != 0) goto fail;