From owner-p4-projects@FreeBSD.ORG Sun Mar 13 00:28:41 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 40C0D16A4D0; Sun, 13 Mar 2005 00:28:41 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F356916A4CE for ; Sun, 13 Mar 2005 00:28:40 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id CBAED43D2F for ; Sun, 13 Mar 2005 00:28:40 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j2D0SeuQ090625 for ; Sun, 13 Mar 2005 00:28:40 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j2D0Se0I090622 for perforce@freebsd.org; Sun, 13 Mar 2005 00:28:40 GMT (envelope-from sam@freebsd.org) Date: Sun, 13 Mar 2005 00:28:40 GMT Message-Id: <200503130028.j2D0Se0I090622@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 72991 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Mar 2005 00:28:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=72991 Change 72991 by sam@sam_ebb on 2005/03/13 00:27:42 replace m_defrag with a private version that does what the driver needs with much less overhead Affected files ... .. //depot/projects/wifi/sys/dev/ath/if_ath.c#75 edit Differences ... ==== //depot/projects/wifi/sys/dev/ath/if_ath.c#75 (text+ko) ==== @@ -3269,6 +3269,89 @@ ath_tx_cleanupq(sc, &sc->sc_txq[i]); } +/* + * Defragment an mbuf chain, returning at most maxfrags separate + * mbufs+clusters. If this is not possible NULL is returned and + * the original mbuf chain is left in it's present (potentially + * modified) state. We use two techniques: collapsing consecutive + * mbufs and replacing consecutive mbufs by a cluster. + */ +static struct mbuf * +ath_defrag(struct mbuf *m0, int how, int maxfrags) +{ + struct mbuf *m, *n, *n2, **prev; + u_int curfrags; + + /* + * Calculate the current number of frags. + */ + curfrags = 0; + for (m = m0; m != NULL; m = m->m_next) + curfrags++; + /* + * First, try to collapse mbufs. Note that we always collapse + * towards the front so we don't need to deal with moving the + * pkthdr. This may be suboptimal if the first mbuf has much + * less data than the following. + */ + m = m0; +again: + for (;;) { + n = m->m_next; + if (n == NULL) + break; + if (n->m_len < M_TRAILINGSPACE(m)) { + bcopy(mtod(n, void *), mtod(m, char *) + m->m_len, + n->m_len); + m->m_len += n->m_len; + m->m_next = n->m_next; + m_free(n); + if (--curfrags <= maxfrags) + return m0; + } else + m = n; + } + KASSERT(maxfrags > 1, + ("maxfrags %u, but normal collapse failed", maxfrags)); + /* + * Collapse consecutive mbufs to a cluster. + */ + prev = &m0->m_next; /* NB: not the first mbuf */ + while ((n = *prev) != NULL) { + if ((n2 = n->m_next) != NULL && + n->m_len + n2->m_len < MCLBYTES) { + m = m_getcl(how, MT_DATA, 0); + if (m == NULL) + goto bad; + bcopy(mtod(n, void *), mtod(m, void *), n->m_len); + bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len, + n2->m_len); + m->m_len = n->m_len + n2->m_len; + m->m_next = n2->m_next; + *prev = m; + m_free(n); + m_free(n2); + if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */ + return m0; + /* + * Still not there, try the normal collapse + * again before we allocate another cluster. + */ + goto again; + } + prev = &n->m_next; + } + /* + * No place where we can collapse to a cluster; punt. + * This can occur if, for example, you request 2 frags + * but the packet requires that both be clusters (we + * never reallocate the first mbuf to avoid moving the + * packet header). + */ +bad: + return NULL; +} + static int ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0) @@ -3287,6 +3370,7 @@ const HAL_RATE_TABLE *rt; HAL_BOOL shortPreamble; struct ath_node *an; + struct mbuf *m; wh = mtod(m0, struct ieee80211_frame *); iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; @@ -3361,12 +3445,14 @@ */ if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */ sc->sc_stats.ast_tx_linear++; - m0 = m_defrag(m0, M_DONTWAIT); + m = ath_defrag(m0, M_DONTWAIT, ATH_TXDESC); if (m0 == NULL) { + m_freem(m0); sc->sc_stats.ast_tx_nombuf++; m_freem(m0); return ENOMEM; } + m0 = m; error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, bf->bf_segs, &bf->bf_nseg, BUS_DMA_NOWAIT);