Module Name: src
Committed By: jmcneill
Date: Thu Aug 7 02:28:52 UTC 2014
Modified Files:
src/sys/dev/pci: if_wpi.c if_wpivar.h
Log Message:
simplify wpi_rx_intr rbuf handling and add some more bus_dmamap_sync; fixes
stalls when downloading large files for me
To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/pci/if_wpi.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_wpivar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_wpi.c
diff -u src/sys/dev/pci/if_wpi.c:1.64 src/sys/dev/pci/if_wpi.c:1.65
--- src/sys/dev/pci/if_wpi.c:1.64 Tue Aug 5 21:54:39 2014
+++ src/sys/dev/pci/if_wpi.c Thu Aug 7 02:28:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wpi.c,v 1.64 2014/08/05 21:54:39 jmcneill Exp $ */
+/* $NetBSD: if_wpi.c,v 1.65 2014/08/07 02:28:52 jmcneill Exp $ */
/*-
* Copyright (c) 2006, 2007
@@ -18,7 +18,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.64 2014/08/05 21:54:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.65 2014/08/07 02:28:52 jmcneill Exp $");
/*
* Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
@@ -536,7 +536,6 @@ wpi_alloc_rbuf(struct wpi_softc *sc)
rbuf = SLIST_FIRST(&sc->rxq.freelist);
if (rbuf != NULL) {
SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
- sc->rxq.nb_free_entries --;
}
mutex_exit(&sc->rxq.freelist_mtx);
@@ -558,8 +557,6 @@ wpi_free_rbuf(struct mbuf* m, void *buf,
mutex_enter(&sc->rxq.freelist_mtx);
SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
mutex_exit(&sc->rxq.freelist_mtx);
- /* No need to protect this with a mutex, see wpi_rx_intr */
- sc->rxq.nb_free_entries ++;
if (__predict_true(m != NULL))
pool_cache_put(mb_cache, m);
@@ -593,7 +590,6 @@ wpi_alloc_rpool(struct wpi_softc *sc)
SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
}
- ring->nb_free_entries = WPI_RBUF_COUNT;
return 0;
}
@@ -1471,7 +1467,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m, *mnew;
- int data_off;
+ int data_off, error;
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_POSTREAD);
@@ -1505,68 +1501,56 @@ wpi_rx_intr(struct wpi_softc *sc, struct
/* Compute where are the useful datas */
data_off = (char*)(head + 1) - mtod(data->m, char*);
- /*
- * If the number of free entry is too low
- * just dup the data->m socket and reuse the same rbuf entry
- * Note that thi test is not protected by a mutex because the
- * only path that causes nb_free_entries to decrease is through
- * this interrupt routine, which is not re-entrent.
- * What may not be obvious is that the safe path is if that test
- * evaluates as true, so nb_free_entries can grow any time.
- */
- if (sc->rxq.nb_free_entries <= WPI_RBUF_LOW_LIMIT) {
-
- /* Prepare the mbuf for the m_dup */
- data->m->m_pkthdr.len = data->m->m_len = le16toh(head->len);
- data->m->m_data = (char*) data->m->m_data + data_off;
-
- m = m_dup(data->m,0,M_COPYALL,M_DONTWAIT);
-
- /* Restore the m_data pointer for future use */
- data->m->m_data = (char*) data->m->m_data - data_off;
-
- if (m == NULL) {
- ifp->if_ierrors++;
- return;
- }
- } else {
- int error;
+ MGETHDR(mnew, M_DONTWAIT, MT_DATA);
+ if (mnew == NULL) {
+ ifp->if_ierrors++;
+ return;
+ }
- MGETHDR(mnew, M_DONTWAIT, MT_DATA);
- if (mnew == NULL) {
- ifp->if_ierrors++;
- return;
- }
+ rbuf = wpi_alloc_rbuf(sc);
+ if (rbuf == NULL) {
+ m_freem(mnew);
+ ifp->if_ierrors++;
+ return;
+ }
- rbuf = wpi_alloc_rbuf(sc);
- KASSERT(rbuf != NULL);
+ /* attach Rx buffer to mbuf */
+ MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
+ rbuf);
+ mnew->m_flags |= M_EXT_RW;
- /* attach Rx buffer to mbuf */
- MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
- rbuf);
- mnew->m_flags |= M_EXT_RW;
+ bus_dmamap_unload(sc->sc_dmat, data->map);
- bus_dmamap_unload(sc->sc_dmat, data->map);
- m = data->m;
- data->m = mnew;
+ error = bus_dmamap_load(sc->sc_dmat, data->map,
+ mtod(mnew, void *), WPI_RBUF_SIZE, NULL,
+ BUS_DMA_NOWAIT | BUS_DMA_READ);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "couldn't load rx mbuf: %d\n", error);
+ m_freem(mnew);
+ ifp->if_ierrors++;
error = bus_dmamap_load(sc->sc_dmat, data->map,
mtod(data->m, void *), WPI_RBUF_SIZE, NULL,
BUS_DMA_NOWAIT | BUS_DMA_READ);
- if (error) {
+ if (error)
panic("%s: bus_dmamap_load failed: %d\n",
device_xname(sc->sc_dev), error);
- }
+ return;
+ }
- /* update Rx descriptor */
- ring->desc[ring->cur] = htole32(rbuf->paddr);
- bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
- ring->desc_dma.size,
- BUS_DMASYNC_PREWRITE);
+ /* new mbuf loaded successfully */
+ m = data->m;
+ data->m = mnew;
- m->m_data = (char*)m->m_data + data_off;
- m->m_pkthdr.len = m->m_len = le16toh(head->len);
- }
+ /* update Rx descriptor */
+ ring->desc[ring->cur] = htole32(rbuf->paddr);
+ bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+ ring->desc_dma.size,
+ BUS_DMASYNC_PREWRITE);
+
+ m->m_data = (char*)m->m_data + data_off;
+ m->m_pkthdr.len = m->m_len = le16toh(head->len);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
@@ -1698,10 +1682,11 @@ wpi_notif_intr(struct wpi_softc *sc)
hw = le32toh(sc->shared->next);
while (sc->rxq.cur != hw) {
struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
- struct wpi_rx_desc *desc = mtod(data->m, struct wpi_rx_desc *);
+ struct wpi_rx_desc *desc;
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_POSTREAD);
+ desc = mtod(data->m, struct wpi_rx_desc *);
DPRINTFN(4, ("rx notification qid=%x idx=%d flags=%x type=%d "
"len=%d\n", desc->qid, desc->idx, desc->flags,
@@ -2699,6 +2684,8 @@ wpi_setup_beacon(struct wpi_softc *sc, s
desc->segs[1].addr = htole32(data->map->dm_segs[0].ds_addr);
desc->segs[1].len = htole32(data->map->dm_segs[0].ds_len);
+ bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+ ring->desc_dma.map->dm_mapsize, BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -2932,6 +2919,8 @@ wpi_scan(struct wpi_softc *sc, uint16_t
desc->segs[0].addr = htole32(data->map->dm_segs[0].ds_addr);
desc->segs[0].len = htole32(data->map->dm_segs[0].ds_len);
+ bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,
+ ring->desc_dma.map->dm_mapsize, BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
Index: src/sys/dev/pci/if_wpivar.h
diff -u src/sys/dev/pci/if_wpivar.h:1.16 src/sys/dev/pci/if_wpivar.h:1.17
--- src/sys/dev/pci/if_wpivar.h:1.16 Tue Aug 5 21:54:39 2014
+++ src/sys/dev/pci/if_wpivar.h Thu Aug 7 02:28:52 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wpivar.h,v 1.16 2014/08/05 21:54:39 jmcneill Exp $ */
+/* $NetBSD: if_wpivar.h,v 1.17 2014/08/07 02:28:52 jmcneill Exp $ */
/*-
* Copyright (c) 2006
@@ -104,7 +104,6 @@ struct wpi_rx_ring {
struct wpi_rbuf rbuf[WPI_RBUF_COUNT];
SLIST_HEAD(, wpi_rbuf) freelist;
kmutex_t freelist_mtx;
- int nb_free_entries;
int cur;
};