Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic If defined(RTW_DEBUG), provide a sysctl (hw.rtw.r...
details: https://anonhg.NetBSD.org/src/rev/dd3d666343dd
branches: trunk
changeset: 572279:dd3d666343dd
user: dyoung <dyoung%NetBSD.org@localhost>
date: Tue Dec 28 22:21:15 2004 +0000
description:
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
diffstat:
sys/dev/ic/rtw.c | 156 ++++++++++++++++++++++++++++++++----------------------
1 files changed, 93 insertions(+), 63 deletions(-)
diffs (truncated from 375 to 300 lines):
diff -r eef1506855ad -r dd3d666343dd sys/dev/ic/rtw.c
--- a/sys/dev/ic/rtw.c Tue Dec 28 22:07:04 2004 +0000
+++ b/sys/dev/ic/rtw.c Tue Dec 28 22:21:15 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtw.c,v 1.30 2004/12/27 20:04:45 dyoung Exp $ */
+/* $NetBSD: rtw.c,v 1.31 2004/12/28 22:21:15 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.30 2004/12/27 20:04:45 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.31 2004/12/28 22:21:15 dyoung Exp $");
#include "bpfilter.h"
@@ -90,6 +90,7 @@
#ifdef RTW_DEBUG
int rtw_debug = 0;
+int rtw_rxbufs_limit = RTW_RXQLEN;
#endif /* RTW_DEBUG */
#define NEXT_ATTACH_STATE(sc, state) do { \
@@ -108,6 +109,7 @@
static void rtw_print_txdesc(struct rtw_softc *, const char *,
struct rtw_txctl *, struct rtw_txdesc_blk *, int);
static int rtw_sysctl_verify_debug(SYSCTLFN_PROTO);
+static int rtw_sysctl_verify_rxbufs_limit(SYSCTLFN_PROTO);
#endif /* RTW_DEBUG */
/*
@@ -139,6 +141,16 @@
rtw_sysctl_verify_debug, 0, &rtw_debug, 0,
CTL_CREATE, CTL_EOL)) != 0)
goto err;
+
+ /* Limit rx buffers, for simulating resource exhaustion. */
+ if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
+ "rxbufs_limit",
+ SYSCTL_DESCR("Set rx buffers limit"),
+ rtw_sysctl_verify_rxbufs_limit, 0, &rtw_rxbufs_limit, 0,
+ CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
#endif /* RTW_DEBUG */
/* set fallback RF programming method */
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
@@ -203,6 +215,12 @@
return rtw_sysctl_verify(SYSCTLFN_CALL(rnode), 0, RTW_DEBUG_MAX);
}
+static int
+rtw_sysctl_verify_rxbufs_limit(SYSCTLFN_ARGS)
+{
+ return rtw_sysctl_verify(SYSCTLFN_CALL(rnode), 0, RTW_RXQLEN);
+}
+
static void
rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where)
{
@@ -574,14 +592,6 @@
}
static __inline void
-rtw_rxctls_setup(struct rtw_rxctl *descs)
-{
- int i;
- for (i = 0; i < RTW_RXQLEN; i++)
- descs[i].srx_mbuf = NULL;
-}
-
-static __inline void
rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_rxctl *descs,
u_int ndescs)
{
@@ -1024,22 +1034,22 @@
}
static __inline void
-rtw_rxdescs_sync(bus_dma_tag_t dmat, bus_dmamap_t dmap, u_int desc0, u_int
- nsync, int ops)
+rtw_rxdescs_sync(bus_dma_tag_t dmat, bus_dmamap_t dmap, int desc0, int nsync,
+ int ndesc, int ops)
{
- KASSERT(nsync <= RTW_RXQLEN);
+ KASSERT(nsync <= ndesc);
/* sync to end of ring */
- if (desc0 + nsync > RTW_RXQLEN) {
+ if (desc0 + nsync > ndesc) {
bus_dmamap_sync(dmat, dmap,
offsetof(struct rtw_descs, hd_rx[desc0]),
- sizeof(struct rtw_rxdesc) * (RTW_RXQLEN - desc0), ops);
- nsync -= (RTW_RXQLEN - desc0);
+ sizeof(struct rtw_rxdesc) * (ndesc - desc0), ops);
+ nsync -= (ndesc - desc0);
desc0 = 0;
}
- KASSERT(desc0 < RTW_RXQLEN);
- KASSERT(nsync <= RTW_RXQLEN);
- KASSERT(desc0 + nsync <= RTW_RXQLEN);
+ KASSERT(desc0 < ndesc);
+ KASSERT(nsync <= ndesc);
+ KASSERT(desc0 + nsync <= ndesc);
/* sync what remains */
bus_dmamap_sync(dmat, dmap,
@@ -1087,6 +1097,8 @@
for (i = 0; i < RTW_RXQLEN; i++) {
srx = &desc[i];
+ if (srx->srx_mbuf == NULL)
+ continue;
bus_dmamap_sync(dmat, srx->srx_dmamap, 0,
srx->srx_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(dmat, srx->srx_dmamap);
@@ -1106,8 +1118,10 @@
return ENOBUFS;
MCLGET(m, M_DONTWAIT);
- if (m == NULL)
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
return ENOBUFS;
+ }
m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
@@ -1129,31 +1143,37 @@
static int
rtw_rxctl_init_all(bus_dma_tag_t dmat, struct rtw_rxctl *desc,
- u_int *next, const char *dvname)
+ int *ndesc, const char *dvname)
{
- int i, rc;
+ int i, rc = 0;
struct rtw_rxctl *srx;
for (i = 0; i < RTW_RXQLEN; i++) {
srx = &desc[i];
- if ((rc = rtw_rxbuf_alloc(dmat, srx)) == 0)
- continue;
- printf("%s: failed rtw_rxbuf_alloc after %d buffers, rc = %d\n",
- dvname, i, rc);
- if (i == 0) {
- rtw_rxbufs_release(dmat, desc);
- return rc;
+ /* we're in rtw_init, so there should be no mbufs allocated */
+ KASSERT(srx->srx_mbuf == NULL);
+#ifdef RTW_DEBUG
+ if (i == rtw_rxbufs_limit) {
+ printf("%s: TEST hit %d-buffer limit\n", dvname, i);
+ rc = ENOBUFS;
+ break;
+ }
+#endif /* RTW_DEBUG */
+ if ((rc = rtw_rxbuf_alloc(dmat, srx)) != 0) {
+ printf("%s: rtw_rxbuf_alloc failed, %d buffers, "
+ "rc %d\n", dvname, i, rc);
+ break;
}
}
- *next = 0;
- return 0;
+ *ndesc = i;
+ return rc;
}
static __inline void
rtw_rxdesc_init(bus_dma_tag_t dmat, bus_dmamap_t dmam,
- struct rtw_rxdesc *hrx, struct rtw_rxctl *srx, int idx, int kick)
+ struct rtw_rxdesc *hrx, struct rtw_rxctl *srx, int idx, int ndesc, int kick)
{
- int is_last = (idx == RTW_RXQLEN - 1);
+ int is_last = (idx == ndesc - 1);
uint32_t ctl, octl, obuf;
obuf = hrx->hrx_buf;
@@ -1187,16 +1207,16 @@
static void
rtw_rxdesc_init_all(bus_dma_tag_t dmat, bus_dmamap_t dmam,
- struct rtw_rxdesc *desc, struct rtw_rxctl *ctl, int kick)
+ struct rtw_rxdesc *desc, struct rtw_rxctl *ctl, int ndesc, int kick)
{
int i;
struct rtw_rxdesc *hrx;
struct rtw_rxctl *srx;
- for (i = 0; i < RTW_RXQLEN; i++) {
+ for (i = 0; i < ndesc; i++) {
hrx = &desc[i];
srx = &ctl[i];
- rtw_rxdesc_init(dmat, dmam, hrx, srx, i, kick);
+ rtw_rxdesc_init(dmat, dmam, hrx, srx, i, ndesc, kick);
}
}
@@ -1241,11 +1261,12 @@
struct ieee80211_node *ni;
struct ieee80211_frame *wh;
- KASSERT(sc->sc_rxnext < RTW_RXQLEN);
-
- for (next = sc->sc_rxnext; ; next = (next + 1) % RTW_RXQLEN) {
+ KASSERT(sc->sc_rxnext < sc->sc_nrxdesc);
+
+ for (next = sc->sc_rxnext; ; next = (next + 1) % sc->sc_nrxdesc) {
rtw_rxdescs_sync(sc->sc_dmat, sc->sc_desc_dmamap,
- next, 1, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ next, 1, sc->sc_nrxdesc,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
hrx = &sc->sc_rxdesc[next];
srx = &sc->sc_rxctl[next];
@@ -1270,7 +1291,8 @@
/* sometimes the NIC skips to the 0th descriptor */
rtw_rxdescs_sync(sc->sc_dmat, sc->sc_desc_dmamap,
- 0, 1, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ 0, 1, sc->sc_nrxdesc,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
hrx = &sc->sc_rxdesc[0];
if ((hrx->hrx_stat & htole32(RTW_RXSTAT_OWN)) != 0)
break;
@@ -1352,8 +1374,7 @@
break;
case ENOBUFS:
printf("%s: rtw_rxbuf_alloc(, %d) failed, "
- "dropping this packet\n", sc->sc_dev.dv_xname,
- next);
+ "dropping packet\n", sc->sc_dev.dv_xname, next);
goto next;
default:
/* XXX shorten rx ring, instead? */
@@ -1393,12 +1414,12 @@
ieee80211_release_node(&sc->sc_ic, ni);
next:
rtw_rxdesc_init(sc->sc_dmat, sc->sc_desc_dmamap,
- hrx, srx, next, 0);
+ hrx, srx, next, sc->sc_nrxdesc, 0);
}
- KASSERT(sc->sc_rxnext < RTW_RXQLEN);
-
sc->sc_rxnext = next;
+ KASSERT(sc->sc_rxnext < sc->sc_nrxdesc);
+
return;
}
@@ -1558,8 +1579,9 @@
for (desc = 0; desc < RTW_RXQLEN; desc++) {
hrx = &sc->sc_rxdesc[desc];
- printf("%s: ctl %08x rsvd0/rssi %08x buf/tsftl %08x "
+ printf("%s: %sctl %08x rsvd0/rssi %08x buf/tsftl %08x "
"rsvd1/tsfth %08x\n", __func__,
+ (desc >= sc->sc_nrxdesc) ? "UNUSED " : "",
le32toh(hrx->hrx_ctl), le32toh(hrx->hrx_rssi),
le32toh(hrx->hrx_buf), le32toh(hrx->hrx_tsfth));
}
@@ -1593,26 +1615,30 @@
(uintptr_t)RTW_RING_BASE(sc, hd_rx)));
}
-static void
+static int
rtw_swring_setup(struct rtw_softc *sc)
{
+ int rc;
rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk[0]);
rtw_txctl_blk_init_all(&sc->sc_txctl_blk[0]);
+ if ((rc = rtw_rxctl_init_all(sc->sc_dmat, sc->sc_rxctl, &sc->sc_nrxdesc,
+ sc->sc_dev.dv_xname)) != 0 && sc->sc_nrxdesc == 0) {
+ printf("%s: could not allocate rx buffers\n",
+ sc->sc_dev.dv_xname);
+ return rc;
+ }
rtw_rxdescs_sync(sc->sc_dmat, sc->sc_desc_dmamap,
- 0, RTW_RXQLEN, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
- rtw_rxctl_init_all(sc->sc_dmat, sc->sc_rxctl, &sc->sc_rxnext,
- sc->sc_dev.dv_xname);
+ 0, sc->sc_nrxdesc, sc->sc_nrxdesc,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ sc->sc_rxnext = 0;
rtw_rxdesc_init_all(sc->sc_dmat, sc->sc_desc_dmamap,
- sc->sc_rxdesc, sc->sc_rxctl, 1);
+ sc->sc_rxdesc, sc->sc_rxctl, sc->sc_nrxdesc, 1);
rtw_txdescs_sync_all(sc->sc_dmat, sc->sc_desc_dmamap,
&sc->sc_txdesc_blk[0]);
-#if 0 /* redundant with rtw_rxdesc_init_all */
Home |
Main Index |
Thread Index |
Old Index