Date: Sun, 5 Dec 2004 07:06:19 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 66439 for review Message-ID: <200412050706.iB576JHM062718@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=66439 Change 66439 by sam@sam_ebb on 2004/12/05 07:05:37 Revamp descriptor allocation to improve success on systems with fragment memory and for forthcoming multi-*ssid support. o encapsulate descriptor+buffer state in new ath_dmadesc struct o manage tx+rx+beacon dma state independently o remove some assumptions about there being only one beacon frame o improve error handling on failures during tx/rx setup Affected files ... .. //depot/projects/wifi/sys/dev/ath/if_ath.c#38 edit .. //depot/projects/wifi/sys/dev/ath/if_athvar.h#15 edit Differences ... ==== //depot/projects/wifi/sys/dev/ath/if_ath.c#38 (text+ko) ==== @@ -122,6 +122,8 @@ static void ath_bstuck_proc(void *, int); static void ath_beacon_free(struct ath_softc *); static void ath_beacon_config(struct ath_softc *); +static void ath_descdma_cleanup(struct ath_softc *sc, + struct ath_descdma *, ath_bufhead *); static int ath_desc_alloc(struct ath_softc *); static void ath_desc_free(struct ath_softc *); static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *); @@ -236,6 +238,8 @@ #define KEYPRINTF(sc, k, ix, mac) #endif +MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers"); + int ath_attach(u_int16_t devid, struct ath_softc *sc) { @@ -1679,12 +1683,17 @@ static int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic = ni->ni_ic; struct ath_buf *bf; struct mbuf *m; int error; - bf = sc->sc_bcbuf; + bf = STAILQ_FIRST(&sc->sc_bbuf); + if (bf == NULL) { + DPRINTF(sc, ATH_DEBUG_BEACON, "%s: no dma buffers\n", __func__); + sc->sc_stats.ast_be_nombuf++; /* XXX */ + return ENOMEM; /* XXX */ + } if (bf->bf_m != NULL) { bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); m_freem(bf->bf_m); @@ -1724,8 +1733,8 @@ #define USE_SHPREAMBLE(_ic) \ (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\ == IEEE80211_F_SHPREAMBLE) - struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = bf->bf_node; + struct ieee80211com *ic = ni->ni_ic; struct mbuf *m = bf->bf_m; struct ath_hal *ah = sc->sc_ah; struct ath_node *an = ATH_NODE(ni); @@ -1798,8 +1807,9 @@ ath_beacon_proc(void *arg, int pending) { struct ath_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - struct ath_buf *bf = sc->sc_bcbuf; + struct ath_buf *bf = STAILQ_FIRST(&sc->sc_bbuf); + struct ieee80211_node *ni = bf->bf_node; + struct ieee80211com *ic = ni->ni_ic; struct ath_hal *ah = sc->sc_ah; struct mbuf *m; int ncabq, error, otherant; @@ -1935,14 +1945,15 @@ static void ath_beacon_free(struct ath_softc *sc) { - struct ath_buf *bf = sc->sc_bcbuf; + struct ath_buf *bf; - if (bf->bf_m != NULL) { - bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); - m_freem(bf->bf_m); - bf->bf_m = NULL; - bf->bf_node = NULL; - } + STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) + if (bf->bf_m != NULL) { + bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); + m_freem(bf->bf_m); + bf->bf_m = NULL; + bf->bf_node = NULL; + } } /* @@ -2088,121 +2099,162 @@ } static int -ath_desc_alloc(struct ath_softc *sc) +ath_descdma_setup(struct ath_softc *sc, + struct ath_descdma *dd, ath_bufhead *head, + const char *name, int nbuf, int ndesc) { -#define DS2PHYS(_sc, _ds) \ - ((_sc)->sc_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_sc)->sc_desc)) - int i, bsize, error; +#define DS2PHYS(_dd, _ds) \ + ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) + struct ifnet *ifp = &sc->sc_if; struct ath_desc *ds; struct ath_buf *bf; + int i, bsize, error; + DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers %u desc/buf\n", + __func__, name, nbuf, ndesc); + + dd->dd_name = name; + /* allocate descriptors */ - sc->sc_desc_len = sizeof(struct ath_desc) * - (ATH_TXBUF * ATH_TXDESC + ATH_RXBUF + 1); - error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &sc->sc_ddmamap); - if (error != 0) + dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; + error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &dd->dd_dmamap); + if (error != 0) { + if_printf(ifp, "unable to create dmamap for %s descriptors, " + "error %u\n", dd->dd_name, error); return error; + } - error = bus_dmamem_alloc(sc->sc_dmat, (void**) &sc->sc_desc, - BUS_DMA_NOWAIT, &sc->sc_ddmamap); - if (error != 0) + error = bus_dmamem_alloc(sc->sc_dmat, (void**) &dd->dd_desc, + BUS_DMA_NOWAIT, &dd->dd_dmamap); + if (error != 0) { + if_printf(ifp, "unable to alloc memory for %u %s descriptors, " + "error %u\n", nbuf * ndesc, dd->dd_name, error); goto fail0; + } - error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, - sc->sc_desc, sc->sc_desc_len, - ath_load_cb, &sc->sc_desc_paddr, + error = bus_dmamap_load(sc->sc_dmat, dd->dd_dmamap, + dd->dd_desc, dd->dd_desc_len, + ath_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT); - if (error != 0) + if (error != 0) { + if_printf(ifp, "unable to map %s descriptors, error %u\n", + dd->dd_name, error); goto fail1; + } - ds = sc->sc_desc; - DPRINTF(sc, ATH_DEBUG_ANY, "%s: DMA map: %p (%lu) -> %p (%lu)\n", - __func__, ds, (u_long) sc->sc_desc_len, (caddr_t) sc->sc_desc_paddr, - /*XXX*/ (u_long) sc->sc_desc_len); + ds = dd->dd_desc; + DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n", + __func__, dd->dd_name, ds, (u_long) dd->dd_desc_len, + (caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len); - /* allocate buffers */ - bsize = sizeof(struct ath_buf) * (ATH_TXBUF + ATH_RXBUF + 1); - bf = malloc(bsize, M_DEVBUF, M_NOWAIT | M_ZERO); - if (bf == NULL) + /* allocate rx buffers */ + bsize = sizeof(struct ath_buf) * nbuf; + bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO); + if (bf == NULL) { + if_printf(ifp, "malloc of %s buffers failed, size %u\n", + dd->dd_name, bsize); goto fail2; - sc->sc_bufptr = bf; - - STAILQ_INIT(&sc->sc_rxbuf); - for (i = 0; i < ATH_RXBUF; i++, bf++, ds++) { - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(sc, ds); - error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, - &bf->bf_dmamap); - if (error != 0) - break; - STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); } + dd->dd_bufptr = bf; - STAILQ_INIT(&sc->sc_txbuf); - for (i = 0; i < ATH_TXBUF; i++, bf++, ds += ATH_TXDESC) { + STAILQ_INIT(head); + for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(sc, ds); + bf->bf_daddr = DS2PHYS(dd, ds); error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, - &bf->bf_dmamap); - if (error != 0) - break; - STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); + &bf->bf_dmamap); + if (error != 0) { + if_printf(ifp, "unable to create dmamap for %s " + "buffer %u, error %u\n", dd->dd_name, i, error); + ath_descdma_cleanup(sc, dd, head); + return error; + } + STAILQ_INSERT_TAIL(head, bf, bf_list); } - - /* beacon buffer */ - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(sc, ds); - error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); - if (error != 0) - return error; - sc->sc_bcbuf = bf; return 0; - fail2: - bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap); + bus_dmamap_unload(sc->sc_dmat, dd->dd_dmamap); fail1: - bus_dmamem_free(sc->sc_dmat, sc->sc_desc, sc->sc_ddmamap); + bus_dmamem_free(sc->sc_dmat, dd->dd_desc, dd->dd_dmamap); fail0: - bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap); - sc->sc_ddmamap = NULL; + bus_dmamap_destroy(sc->sc_dmat, dd->dd_dmamap); + memset(dd, 0, sizeof(*dd)); return error; #undef DS2PHYS } static void -ath_desc_free(struct ath_softc *sc) +ath_descdma_cleanup(struct ath_softc *sc, + struct ath_descdma *dd, ath_bufhead *head) { struct ath_buf *bf; + struct ieee80211_node *ni; - bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap); - bus_dmamem_free(sc->sc_dmat, sc->sc_desc, sc->sc_ddmamap); - bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap); + bus_dmamap_unload(sc->sc_dmat, dd->dd_dmamap); + bus_dmamem_free(sc->sc_dmat, dd->dd_desc, dd->dd_dmamap); + bus_dmamap_destroy(sc->sc_dmat, dd->dd_dmamap); - /* - * NB: TX queues have already been freed in ath_draintxq(), - * which must be called before calling this function. - */ - - STAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list) - bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap); - STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { + STAILQ_FOREACH(bf, head, bf_list) { if (bf->bf_m) { - bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); - bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap); m_freem(bf->bf_m); bf->bf_m = NULL; } + if (bf->bf_dmamap != NULL) { + bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap); + bf->bf_dmamap = NULL; + } + ni = bf->bf_node; + bf->bf_node = NULL; + if (ni != NULL) { + /* + * Reclaim node reference. + */ + ieee80211_free_node(ni); + } } - if (sc->sc_bcbuf != NULL) { - bus_dmamap_unload(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap); - bus_dmamap_destroy(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap); - sc->sc_bcbuf = NULL; + + STAILQ_INIT(head); + free(dd->dd_bufptr, M_ATHDEV); + memset(dd, 0, sizeof(*dd)); +} + +static int +ath_desc_alloc(struct ath_softc *sc) +{ + int error; + + error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, + "rx", ATH_RXBUF, 1); + if (error != 0) + return error; + + error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, + "tx", ATH_TXBUF, ATH_TXDESC); + if (error != 0) { + ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); + return error; + } + + error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf, + "beacon", 1, 1); + if (error != 0) { + ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); + ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); + return error; } + return 0; +} - STAILQ_INIT(&sc->sc_rxbuf); - STAILQ_INIT(&sc->sc_txbuf); - free(sc->sc_bufptr, M_DEVBUF); - sc->sc_bufptr = NULL; +static void +ath_desc_free(struct ath_softc *sc) +{ + + if (sc->sc_bdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf); + if (sc->sc_txdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); + if (sc->sc_rxdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); } static struct ieee80211_node * @@ -2296,11 +2348,9 @@ struct ath_hal *ah = sc->sc_ah; int error; struct mbuf *m; -struct mbuf *morig; /*XXX*/ struct ath_desc *ds; m = bf->bf_m; -morig = m; /* XXX */ if (m == NULL) { /* * NB: by assigning a page to the rx dma buffer we @@ -2320,7 +2370,8 @@ bf->bf_m = m; m->m_pkthdr.len = m->m_len = m->m_ext.ext_size; - error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m, + error = bus_dmamap_load_mbuf(sc->sc_dmat, + bf->bf_dmamap, m, ath_mbuf_load_cb, bf, BUS_DMA_NOWAIT); if (error != 0) { @@ -2333,7 +2384,6 @@ KASSERT(bf->bf_nseg == 1, ("%s: multi-segment packet; nseg %u", __func__, bf->bf_nseg)); } - KASSERT(m->m_next == NULL, ("m_next %p morig %p (2)", m->m_next, morig)); bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREREAD); /* @@ -2428,8 +2478,8 @@ ath_rx_proc(void *arg, int npending) { #define PA2DESC(_sc, _pa) \ - ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \ - ((_pa) - (_sc)->sc_desc_paddr))) + ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \ + ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) struct ath_softc *sc = arg; struct ath_buf *bf; struct ieee80211com *ic = &sc->sc_ic; @@ -2482,10 +2532,6 @@ #endif if (status == HAL_EINPROGRESS) break; - if (m->m_next != NULL) { /* XXX */ - if_printf(ifp, "m_next %p, patching!\n", m->m_next); - m->m_next = NULL; - } STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list); if (ds->ds_rxstat.rs_more) { /* @@ -2535,7 +2581,7 @@ len = ds->ds_rxstat.rs_datalen; if (len >= sizeof (struct ieee80211_frame)) { bus_dmamap_sync(sc->sc_dmat, - bf->bf_dmamap, + bf->bf_dmamap, BUS_DMASYNC_POSTREAD); ieee80211_notify_michael_failure(ic, mtod(m, struct ieee80211_frame *), @@ -2562,7 +2608,7 @@ * when the rx descriptor is setup again to receive * another frame. */ - bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, + bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); bf->bf_m = NULL; @@ -2956,7 +3002,6 @@ bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); bf->bf_m = m0; bf->bf_node = ni; /* NB: held reference */ -{ struct mbuf *n; bf->bf_nm = 0; for (n = bf->bf_m; n != NULL; n = n->m_next) bf->bf_mshadow[bf->bf_nm++] = n; }/*XXX*/ /* setup descriptors */ ds = bf->bf_desc; @@ -3548,8 +3593,8 @@ ath_stoprecv(struct ath_softc *sc) { #define PA2DESC(_sc, _pa) \ - ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \ - ((_pa) - (_sc)->sc_desc_paddr))) + ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \ + ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) struct ath_hal *ah = sc->sc_ah; ath_hal_stoppcurecv(ah); /* disable PCU */ ==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#15 (text+ko) ==== @@ -83,16 +83,28 @@ struct ath_buf { STAILQ_ENTRY(ath_buf) bf_list; int bf_nseg; - bus_dmamap_t bf_dmamap; /* DMA map of the buffer */ struct ath_desc *bf_desc; /* virtual addr of desc */ bus_addr_t bf_daddr; /* physical addr of desc */ + bus_dmamap_t bf_dmamap; /* DMA map for mbuf chain */ struct mbuf *bf_m; /* mbuf for buf */ struct ieee80211_node *bf_node; /* pointer to the node */ bus_size_t bf_mapsize; #define ATH_MAX_SCATTER 64 bus_dma_segment_t bf_segs[ATH_MAX_SCATTER]; -struct mbuf *bf_mshadow[ATH_MAX_SCATTER];/*XXX*/ -int bf_nm; +}; +typedef STAILQ_HEAD(, ath_buf) ath_bufhead; + +/* + * DMA state for tx/rx descriptors. + */ +struct ath_descdma { + const char* dd_name; + struct ath_desc *dd_desc; /* descriptors */ + bus_addr_t dd_desc_paddr; /* physical addr of dd_desc */ + bus_addr_t dd_desc_len; /* size of dd_desc */ + bus_dma_segment_t dd_dseg; + bus_dmamap_t dd_dmamap; /* DMA map for descriptors */ + struct ath_buf *dd_bufptr; /* associated buffers */ }; /* @@ -191,36 +203,32 @@ } u_rx_rt; int sc_rx_th_len; - struct ath_desc *sc_desc; /* TX/RX descriptors */ - bus_dma_segment_t sc_dseg; - bus_dmamap_t sc_ddmamap; /* DMA map for descriptors */ - bus_addr_t sc_desc_paddr; /* physical addr of sc_desc */ - bus_addr_t sc_desc_len; /* size of sc_desc */ - struct task sc_fataltask; /* fatal int processing */ - STAILQ_HEAD(, ath_buf) sc_rxbuf; /* receive buffer */ + struct ath_descdma sc_rxdma; /* RX descriptos */ + ath_bufhead sc_rxbuf; /* receive buffer */ u_int32_t *sc_rxlink; /* link ptr in last RX desc */ struct task sc_rxtask; /* rx int processing */ struct task sc_rxorntask; /* rxorn int processing */ u_int8_t sc_defant; /* current default antenna */ u_int8_t sc_rxotherant; /* rx's on non-default antenna*/ + struct ath_descdma sc_txdma; /* TX descriptors */ + ath_bufhead sc_txbuf; /* transmit buffer */ + struct mtx sc_txbuflock; /* txbuf lock */ int sc_tx_timer; /* transmit timeout */ - STAILQ_HEAD(, ath_buf) sc_txbuf; /* transmit buffer */ - struct mtx sc_txbuflock; /* txbuf lock */ u_int sc_txqsetup; /* h/w queues setup */ u_int sc_txintrperiod;/* tx interrupt batching */ struct ath_txq sc_txq[HAL_NUM_TX_QUEUES]; struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */ struct task sc_txtask; /* tx int processing */ + struct ath_descdma sc_bdma; /* beacon descriptors */ + ath_bufhead sc_bbuf; /* beacon buffers */ u_int sc_bhalq; /* HAL q for outgoing beacons */ u_int sc_bmisscount; /* missed beacon transmits */ u_int32_t sc_ant_tx[8]; /* recent tx frames/antenna */ struct ath_txq *sc_cabq; /* tx q for cab frames */ - struct ath_buf *sc_bcbuf; /* beacon buffer */ - struct ath_buf *sc_bufptr; /* allocated buffer ptr */ struct ieee80211_beacon_offsets sc_boff;/* dynamic update state */ struct task sc_bmisstask; /* bmiss int processing */ struct task sc_bstucktask; /* stuck beacon processing */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412050706.iB576JHM062718>