ath_rxbuf_init fixes...

I've simplified the buffer initialization code so that it 
always allocates things as if there were one or more monitor VAPs.  This is 
defensive since monitor VAPs can are created and/or destroyed while the radio is
up. 

The old logic was basically changing the behavior of the initialization function
dynamically based on the presence of a monitor VAP but could lead to a mixed set
of buffers.

The revised code keeps all the buffers the same and make sure there is room for a radiotap
or prism header if necessary in advance.

Without this change, even after adding a monitor VAP you are going to pull SKBs that are too small for a while.



git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3518 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
mtaylor 2008-04-10 05:59:23 +00:00
parent 25a3a9f3db
commit fcb3fdbe90

View File

@ -6236,74 +6236,54 @@ static int
ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
struct sk_buff *skb;
struct ath_desc *ds;
#if 0
/* Free the prior skb, if present */
if (bf->bf_skb != NULL) {
ieee80211_dev_kfree_skb(&bf->bf_skb);
if (bf->bf_skbaddr != 0) {
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
bf->bf_skbaddr = 0;
}
}
#endif
skb = bf->bf_skb;
if (skb == NULL) {
if (sc->sc_nmonvaps > 0) {
u_int off;
struct ath_desc *ds = NULL;
/* NB: Always use the same size for buffer allocations so that dynamically
* adding a monitor mode VAP to a running driver doesn't cause havoc. */
unsigned int extra = A_MAX(sizeof(struct ath_rx_radiotap_header),
A_MAX(sizeof(struct wlan_ng_prism2_header),
ATHDESC_HEADER_SIZE));
/*
* Allocate buffer for monitor mode with space for the
* physical layer header at the start and/or any monitoring headers such
* as prism or radiotap. See extra, above.
*/
skb = ieee80211_dev_alloc_skb(sc->sc_rxbufsize +
extra + sc->sc_cachelsz - 1);
if (skb == NULL) {
DPRINTF(sc, ATH_DEBUG_ANY,
"Dropping; skbuff allocation failed; size: %u!\n",
sc->sc_rxbufsize + extra + sc->sc_cachelsz - 1);
sc->sc_stats.ast_rx_nobuf++;
/* NB: I'm being cautious by unmapping and releasing the SKB every time.
* XXX: I could probably keep rolling, but the DMA map/unmap logic doesn't
* seem clean enough and cycling the skb through the free function and
* slab allocator seems to scrub any un-reset values. */
if (bf->bf_skb != NULL) {
KASSERT(bf->bf_skbaddr, ("bf->bf_skbaddr is 0"));
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
ieee80211_dev_kfree_skb(&bf->bf_skb);
}
if (!bf->bf_skb) {
int size = sc->sc_rxbufsize + extra + sc->sc_cachelsz - 1;
int offset = 0;
bf->bf_skb = ath_alloc_skb(size,
sc->sc_cachelsz);
if (!bf->bf_skb) {
EPRINTF(sc, "%s: ERROR: skb initialization failed; size: %u!\n",
__func__, size);
return -ENOMEM;
}
/*
* Reserve space for the Prism header.
* Reserve space for the header.
*/
skb_reserve(skb, sizeof(struct wlan_ng_prism2_header));
/*
* Align to cache line.
*/
off = ((unsigned long) skb->data) % sc->sc_cachelsz;
if (off != 0)
skb_reserve(skb, sc->sc_cachelsz - off);
} else {
skb_reserve(bf->bf_skb, extra);
/*
* Cache-line-align. This is important (for the
* 5210 at least) as not doing so causes bogus data
* in rx'd frames.
*/
skb = ath_alloc_skb(sc->sc_rxbufsize, sc->sc_cachelsz);
if (skb == NULL) {
offset = ((unsigned long)bf->bf_skb->data) % sc->sc_cachelsz;
if (offset != 0)
skb_reserve(bf->bf_skb, sc->sc_cachelsz - offset);
}
bf->bf_skb->dev = sc->sc_dev;
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
bf->bf_skb->data, sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
if (!bf->bf_skbaddr) {
DPRINTF(sc, ATH_DEBUG_ANY,
"Dropping; skbuff allocation failed; size: %u!\n",
sc->sc_rxbufsize);
sc->sc_stats.ast_rx_nobuf++;
"%s: ERROR: skb dma bus mapping failed!\n",
__func__);
return -ENOMEM;
}
}
skb->dev = sc->sc_dev;
bf->bf_skb = skb;
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
skb->data, sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
}
/*
* Setup descriptors. For receive we always terminate
* the descriptor list with a self-linked entry so we'll
@ -6323,7 +6303,7 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
ds->ds_link = bf->bf_daddr; /* link to self */
ds->ds_data = bf->bf_skbaddr;
ath_hal_setuprxdesc(ah, ds,
skb_tailroom(skb), /* buffer size */
skb_tailroom(bf->bf_skb), /* buffer size */
0);
if (sc->sc_rxlink != NULL)
*sc->sc_rxlink = bf->bf_daddr;