Index: if_ath_rx_edma.c =================================================================== --- if_ath_rx_edma.c (revision 248985) +++ if_ath_rx_edma.c (working copy) @@ -384,16 +384,17 @@ /* * Completed descriptor. - * - * In the future we'll call ath_rx_pkt(), but it first - * has to be taught about EDMA RX queues (so it can - * access sc_rxpending correctly.) */ DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Q%d: completed!\n", __func__, qtype); npkts++; /* + * We've been synced already, so unmap. + */ + bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); + + /* * Remove the FIFO entry and place it on the completion * queue. */ @@ -468,6 +469,7 @@ struct ath_rx_status *rs; int16_t nf; ath_bufhead rxlist; + struct mbuf *m; TAILQ_INIT(&rxlist); @@ -492,12 +494,11 @@ m_adj(bf->bf_m, sc->sc_rx_statuslen); /* Handle the frame */ - /* - * Note: this may or may not free bf->bf_m and sync/unmap - * the frame. - */ + rs = &bf->bf_status.ds_rxstat; - if (ath_rx_pkt(sc, rs, bf->bf_rxstatus, tsf, nf, qtype, bf)) + m = bf->bf_m; + bf->bf_m = NULL; + if (ath_rx_pkt(sc, rs, bf->bf_rxstatus, tsf, nf, qtype, bf, m)) ngood++; } @@ -653,8 +654,11 @@ /* Allocate buffer */ bf = TAILQ_FIRST(&sc->sc_rxbuf); /* XXX shouldn't happen upon startup? */ - if (bf == NULL) + if (bf == NULL) { + device_printf(sc->sc_dev, "%s: nothing on rxbuf?!\n", + __func__); return (NULL); + } /* Remove it from the free list */ TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list); @@ -748,13 +752,15 @@ * hardware. */ bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, - BUS_DMASYNC_PREREAD); + BUS_DMASYNC_PREWRITE); /* Write to the RX FIFO */ - DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Q%d: putrxbuf=%p\n", + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: Q%d: putrxbuf=%p (0x%jx)\n", __func__, qtype, - bf->bf_desc); + bf->bf_desc, + (uintmax_t) bf->bf_daddr); ath_hal_putrxbuf(sc->sc_ah, bf->bf_daddr, qtype); re->m_fifo_depth++; Index: if_ath_rx.c =================================================================== --- if_ath_rx.c (revision 248998) +++ if_ath_rx.c (working copy) @@ -502,12 +502,21 @@ } } +/* + * Process a single packet. + * + * The mbuf must already be synced, unmapped and removed from bf->bf_m + * by this stage. + * + * The mbuf must be consumed by this routine - either passed up the + * net80211 stack, put on the holding queue, or freed. + */ int ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, - uint64_t tsf, int nf, HAL_RX_QUEUE qtype, struct ath_buf *bf) + uint64_t tsf, int nf, HAL_RX_QUEUE qtype, struct ath_buf *bf, + struct mbuf *m) { struct ath_hal *ah = sc->sc_ah; - struct mbuf *m = bf->bf_m; uint64_t rstamp; int len, type; struct ifnet *ifp = sc->sc_ifp; @@ -548,10 +557,6 @@ /* Process DFS radar events */ if ((rs->rs_phyerr == HAL_PHYERR_RADAR) || (rs->rs_phyerr == HAL_PHYERR_FALSE_RADAR_EXT)) { - /* Since we're touching the frame data, sync it */ - bus_dmamap_sync(sc->sc_dmat, - bf->bf_dmamap, - BUS_DMASYNC_POSTREAD); /* Now pass it to the radar processing code */ ath_dfs_process_phy_err(sc, m, rstamp, rs); } @@ -593,9 +598,6 @@ /* XXX frag's and qos frames */ len = rs->rs_datalen; if (len >= sizeof (struct ieee80211_frame)) { - bus_dmamap_sync(sc->sc_dmat, - bf->bf_dmamap, - BUS_DMASYNC_POSTREAD); ath_handle_micerror(ic, mtod(m, struct ieee80211_frame *), sc->sc_splitmic ? @@ -619,35 +621,20 @@ */ if (ieee80211_radiotap_active(ic) && (rs->rs_status & sc->sc_monpass)) { - bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); /* NB: bpf needs the mbuf length setup */ len = rs->rs_datalen; m->m_pkthdr.len = m->m_len = len; - bf->bf_m = NULL; ath_rx_tap(ifp, m, rs, rstamp, nf); #ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT ath_rx_tap_vendor(ifp, m, rs, rstamp, nf); #endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */ ieee80211_radiotap_rx_all(ic, m); - m_freem(m); } /* XXX pass MIC errors up for s/w reclaculation */ + m_freem(m); m = NULL; goto rx_next; } rx_accept: - /* - * Sync and unmap the frame. At this point we're - * committed to passing the mbuf somewhere so clear - * bf_m; this means a new mbuf must be allocated - * when the rx descriptor is setup again to receive - * another frame. - */ - 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; - len = rs->rs_datalen; m->m_len = len; @@ -665,6 +652,7 @@ m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = len; re->m_rxpending = m; + m = NULL; goto rx_next; } else if (re->m_rxpending != NULL) { /* @@ -744,7 +732,7 @@ /* NB: in particular this captures ack's */ ieee80211_radiotap_rx_all(ic, m); } - m_freem(m); + m_freem(m); m = NULL; goto rx_next; } @@ -788,6 +776,7 @@ */ type = ieee80211_input(ni, m, rs->rs_rssi, nf); ieee80211_free_node(ni); + m = NULL; /* * Arrange to update the last rx timestamp only for * frames from our ap when operating in station mode. @@ -799,8 +788,15 @@ is_good = 1; } else { type = ieee80211_input_all(ic, m, rs->rs_rssi, nf); + m = NULL; } + /* + * At this point we have passed the frame up the stack; thus + * the mbuf is no longer ours. + */ + + /* * Track rx rssi and do any rx antenna management. */ ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi); @@ -837,6 +833,16 @@ ath_led_event(sc, 0); } rx_next: + /* + * Debugging - complain if we didn't NULL the mbuf pointer + * here. + */ + if (m != NULL) { + device_printf(sc->sc_dev, + "%s: mbuf %p should've been freed!\n", + __func__, + m); + } return (is_good); } @@ -952,7 +958,10 @@ /* * Process a single frame. */ - if (ath_rx_pkt(sc, rs, status, tsf, nf, HAL_RX_QUEUE_HP, bf)) + 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; + if (ath_rx_pkt(sc, rs, status, tsf, nf, HAL_RX_QUEUE_HP, bf, m)) ngood++; rx_proc_next: TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); Index: if_ath_rx.h =================================================================== --- if_ath_rx.h (revision 248985) +++ if_ath_rx.h (working copy) @@ -58,7 +58,7 @@ extern int ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, uint64_t tsf, int nf, HAL_RX_QUEUE qtype, - struct ath_buf *bf); + struct ath_buf *bf, struct mbuf *m); extern void ath_recv_setup_legacy(struct ath_softc *sc);