summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2007-08-22 19:50:26 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2007-08-22 19:50:26 +0000
commitdd654a77e55db513af679bbba472472b1a70b096 (patch)
treec9f8ff688e9c7177f65961021b52f5c013d175b6 /sys/dev/pci
parent72cafb89b9cca2393b2fb7a479b1f103493f645b (diff)
when running out of rx buffers, allocate a new mbuf and copy the rx
buffer into it using m_copym2() instead of just dropping the received frame. otherwise, it may happen that all rx buffers are queued by tcp_input() waiting for a frame that will never arrive because we are dropping it. when it happens, rx stop working and it is hard to recover from this. the problem is not visible when using WEP because WEP decryption is currently done by software and that rx buffers are copied into mbufs by the software decryption code. while i'm here, increase the number of rx buffers allocated by wpi(4) from 80 to 96 to limit the number of copies. problem and solution found by bluhm@ - thanks.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_wpi.c48
-rw-r--r--sys/dev/pci/if_wpivar.h4
2 files changed, 30 insertions, 22 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index ff0e688e9d3..44a9ce828d5 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.50 2007/08/10 16:29:27 jasper Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.51 2007/08/22 19:50:25 damien Exp $ */
/*-
* Copyright (c) 2006, 2007
@@ -1234,30 +1234,38 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
return;
}
- MGETHDR(mnew, M_DONTWAIT, MT_DATA);
- if (mnew == NULL) {
- ifp->if_ierrors++;
- return;
- }
- if ((rbuf = wpi_alloc_rbuf(sc)) == NULL) {
- m_freem(mnew);
- ifp->if_ierrors++;
- return;
- }
- /* attach Rx buffer to mbuf */
- MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf, rbuf);
-
m = data->m;
- data->m = mnew;
-
- /* update Rx descriptor */
- ring->desc[ring->cur] = htole32(rbuf->paddr);
-
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_data = (caddr_t)(head + 1);
m->m_pkthdr.len = m->m_len = letoh16(head->len);
+ if ((rbuf = SLIST_FIRST(&sc->rxq.freelist)) != NULL) {
+ MGETHDR(mnew, M_DONTWAIT, MT_DATA);
+ if (mnew == NULL) {
+ ifp->if_ierrors++;
+ return;
+ }
+
+ /* attach Rx buffer to mbuf */
+ MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, 0, wpi_free_rbuf,
+ rbuf);
+ SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
+
+ data->m = mnew;
+
+ /* update Rx descriptor */
+ ring->desc[ring->cur] = htole32(rbuf->paddr);
+ } else {
+ /* no free rbufs, copy frame */
+ m = m_copym2(m, 0, M_COPYALL, M_DONTWAIT);
+ if (m == NULL) {
+ /* no free mbufs either, drop frame */
+ ifp->if_ierrors++;
+ return;
+ }
+ }
+
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
struct mbuf mb;
@@ -1389,7 +1397,7 @@ wpi_notif_intr(struct wpi_softc *sc)
hw = letoh32(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 = (void *)data->m->m_ext.ext_buf;
DPRINTFN(4, ("rx notification qid=%x idx=%d flags=%x type=%d "
"len=%d\n", desc->qid, desc->idx, desc->flags, desc->type,
diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h
index 09daa0c80c3..921afe74bdf 100644
--- a/sys/dev/pci/if_wpivar.h
+++ b/sys/dev/pci/if_wpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpivar.h,v 1.12 2007/06/16 14:15:37 damien Exp $ */
+/* $OpenBSD: if_wpivar.h,v 1.13 2007/08/22 19:50:25 damien Exp $ */
/*-
* Copyright (c) 2006, 2007
@@ -80,7 +80,7 @@ struct wpi_tx_ring {
int cur;
};
-#define WPI_RBUF_COUNT (WPI_RX_RING_COUNT + 16)
+#define WPI_RBUF_COUNT (WPI_RX_RING_COUNT + 32)
struct wpi_softc;