summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2007-09-11 19:53:59 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2007-09-11 19:53:59 +0000
commitc2d0515f866b7f9188a2222b22025cd81b8f715f (patch)
treea281f286e7597160b2ffd6829854cb141cb7b677
parent74d17e9294521ce905bfcfe3391da47d35d12b01 (diff)
undo rev 1.10 "implement a zero-copy RX data path".
working with a fixed number of Rx buffers doesn't work well. fixes problems with blocked incoming traffic.
-rw-r--r--sys/dev/usb/if_uath.c99
-rw-r--r--sys/dev/usb/if_uathvar.h19
2 files changed, 53 insertions, 65 deletions
diff --git a/sys/dev/usb/if_uath.c b/sys/dev/usb/if_uath.c
index af15c327ed0..0cb59f2047b 100644
--- a/sys/dev/usb/if_uath.c
+++ b/sys/dev/usb/if_uath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_uath.c,v 1.29 2007/09/07 19:05:05 damien Exp $ */
+/* $OpenBSD: if_uath.c,v 1.30 2007/09/11 19:53:58 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -137,7 +137,6 @@ int uath_alloc_tx_data_list(struct uath_softc *);
void uath_free_tx_data_list(struct uath_softc *);
int uath_alloc_rx_data_list(struct uath_softc *);
void uath_free_rx_data_list(struct uath_softc *);
-void uath_free_rx_data(caddr_t, u_int, void *);
int uath_alloc_tx_cmd_list(struct uath_softc *);
void uath_free_tx_cmd_list(struct uath_softc *);
int uath_alloc_rx_cmd_list(struct uath_softc *);
@@ -454,15 +453,6 @@ uath_detach(struct device *self, int flags)
timeout_del(&sc->scan_to);
timeout_del(&sc->stat_to);
- ieee80211_ifdetach(ifp); /* free all nodes */
- if_detach(ifp);
-
- sc->sc_dying = 1;
- DPRINTF(("reclaiming %d references\n", sc->sc_refcnt));
- while (sc->sc_refcnt > 0)
- (void)tsleep(UATH_COND_NOREF(sc), 0, "uathdet", 0);
- DPRINTF(("all references reclaimed\n"));
-
/* abort and free xfers */
uath_free_tx_data_list(sc);
uath_free_rx_data_list(sc);
@@ -472,6 +462,9 @@ uath_detach(struct device *self, int flags)
/* close Tx/Rx pipes */
uath_close_pipes(sc);
+ ieee80211_ifdetach(ifp); /* free all nodes */
+ if_detach(ifp);
+
splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
@@ -595,8 +588,7 @@ uath_alloc_rx_data_list(struct uath_softc *sc)
{
int i, error;
- SLIST_INIT(&sc->rx_freelist);
- for (i = 0; i < UATH_RX_DATA_POOL_COUNT; i++) {
+ for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
struct uath_rx_data *data = &sc->rx_data[i];
data->sc = sc; /* backpointer for callbacks */
@@ -608,14 +600,29 @@ uath_alloc_rx_data_list(struct uath_softc *sc)
error = ENOMEM;
goto fail;
}
- data->buf = usbd_alloc_buffer(data->xfer, sc->rxbufsz);
- if (data->buf == NULL) {
+ if (usbd_alloc_buffer(data->xfer, sc->rxbufsz) == NULL) {
printf("%s: could not allocate xfer buffer\n",
sc->sc_dev.dv_xname);
error = ENOMEM;
goto fail;
}
- SLIST_INSERT_HEAD(&sc->rx_freelist, data, next);
+
+ MGETHDR(data->m, M_DONTWAIT, MT_DATA);
+ if (data->m == NULL) {
+ printf("%s: could not allocate rx mbuf\n",
+ sc->sc_dev.dv_xname);
+ error = ENOMEM;
+ goto fail;
+ }
+ MCLGET(data->m, M_DONTWAIT);
+ if (!(data->m->m_flags & M_EXT)) {
+ printf("%s: could not allocate rx mbuf cluster\n",
+ sc->sc_dev.dv_xname);
+ error = ENOMEM;
+ goto fail;
+ }
+
+ data->buf = mtod(data->m, uint8_t *);
}
return 0;
@@ -631,23 +638,15 @@ uath_free_rx_data_list(struct uath_softc *sc)
/* make sure no transfers are pending */
usbd_abort_pipe(sc->data_rx_pipe);
- for (i = 0; i < UATH_RX_DATA_POOL_COUNT; i++)
- if (sc->rx_data[i].xfer != NULL)
- usbd_free_xfer(sc->rx_data[i].xfer);
-}
-
-void
-uath_free_rx_data(caddr_t buf, u_int size, void *arg)
-{
- struct uath_rx_data *data = arg;
- struct uath_softc *sc = data->sc;
+ for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
+ struct uath_rx_data *data = &sc->rx_data[i];
- /* put the buffer back in the free list */
- SLIST_INSERT_HEAD(&sc->rx_freelist, data, next);
+ if (data->xfer != NULL)
+ usbd_free_xfer(data->xfer);
- /* release reference to softc */
- if (--sc->sc_refcnt == 0 && sc->sc_dying)
- wakeup(UATH_COND_NOREF(sc));
+ if (data->m != NULL)
+ m_freem(data->m);
+ }
}
int
@@ -1185,9 +1184,8 @@ uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
struct ifnet *ifp = &ic->ic_if;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
- struct uath_rx_data *ndata;
struct uath_rx_desc *desc;
- struct mbuf *m;
+ struct mbuf *mnew, *m;
uint32_t hdr;
int s, len;
@@ -1223,24 +1221,24 @@ uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
/* there's probably a "bad CRC" flag somewhere in the descriptor.. */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
+ MGETHDR(mnew, M_DONTWAIT, MT_DATA);
+ if (mnew == NULL) {
+ printf("%s: could not allocate rx mbuf\n",
+ sc->sc_dev.dv_xname);
ifp->if_ierrors++;
goto skip;
}
-
- /* grab a new Rx buffer */
- ndata = SLIST_FIRST(&sc->rx_freelist);
- if (ndata == NULL) {
- printf("%s: could not allocate Rx buffer\n",
+ MCLGET(mnew, M_DONTWAIT);
+ if (!(mnew->m_flags & M_EXT)) {
+ printf("%s: could not allocate rx mbuf cluster\n",
sc->sc_dev.dv_xname);
- m_freem(m);
+ m_freem(mnew);
ifp->if_ierrors++;
goto skip;
}
- SLIST_REMOVE_HEAD(&sc->rx_freelist, next);
- MEXTADD(m, data->buf, sc->rxbufsz, 0, uath_free_rx_data, data);
+ m = data->m;
+ data->m = mnew;
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
@@ -1248,7 +1246,7 @@ uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
m->m_pkthdr.len = m->m_len = betoh32(desc->len) -
sizeof (struct uath_rx_desc) - IEEE80211_CRC_LEN;
- data = ndata;
+ data->buf = mtod(data->m, uint8_t *);
wh = mtod(m, struct ieee80211_frame *);
if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
@@ -1288,7 +1286,6 @@ uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
#endif
s = splnet();
- sc->sc_refcnt++;
ni = ieee80211_find_rxnode(ic, wh);
ieee80211_input(ifp, m, ni, (int)betoh32(desc->rssi), 0);
@@ -1297,9 +1294,8 @@ uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
splx(s);
skip: /* setup a new transfer */
- usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
- sc->rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
- uath_data_rxeof);
+ usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, sc->rxbufsz,
+ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, uath_data_rxeof);
(void)usbd_transfer(data->xfer);
}
@@ -1897,18 +1893,17 @@ uath_init(struct ifnet *ifp)
* Queue Rx data xfers.
*/
for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
- struct uath_rx_data *data = SLIST_FIRST(&sc->rx_freelist);
+ struct uath_rx_data *data = &sc->rx_data[i];
usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
- sc->rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
- USBD_NO_TIMEOUT, uath_data_rxeof);
+ sc->rxbufsz, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
+ uath_data_rxeof);
error = usbd_transfer(data->xfer);
if (error != USBD_IN_PROGRESS && error != 0) {
printf("%s: could not queue Rx transfer\n",
sc->sc_dev.dv_xname);
goto fail;
}
- SLIST_REMOVE_HEAD(&sc->rx_freelist, next);
}
error = uath_cmd_read(sc, UATH_CMD_07, 0, NULL, &val,
diff --git a/sys/dev/usb/if_uathvar.h b/sys/dev/usb/if_uathvar.h
index 0d6a1271e9d..5ae648c724c 100644
--- a/sys/dev/usb/if_uathvar.h
+++ b/sys/dev/usb/if_uathvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_uathvar.h,v 1.5 2007/06/06 19:25:49 mk Exp $ */
+/* $OpenBSD: if_uathvar.h,v 1.6 2007/09/11 19:53:58 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -24,8 +24,6 @@
#define UATH_RX_DATA_LIST_COUNT 1 /* 128 */
#define UATH_RX_CMD_LIST_COUNT 1 /* 30 */
-#define UATH_RX_DATA_POOL_COUNT (UATH_RX_DATA_LIST_COUNT + 24)
-
#define UATH_DATA_TIMEOUT 10000
#define UATH_CMD_TIMEOUT 1000
@@ -61,10 +59,10 @@ struct uath_tx_data {
};
struct uath_rx_data {
- struct uath_softc *sc;
- usbd_xfer_handle xfer;
- uint8_t *buf;
- SLIST_ENTRY(uath_rx_data) next;
+ struct uath_softc *sc;
+ usbd_xfer_handle xfer;
+ uint8_t *buf;
+ struct mbuf *m;
};
struct uath_tx_cmd {
@@ -92,7 +90,6 @@ struct uath_wme_settings {
/* condvars */
#define UATH_COND_INIT(sc) ((caddr_t)sc + 1)
-#define UATH_COND_NOREF(sc) ((caddr_t)sc + 2)
/* flags for sending firmware commands */
#define UATH_CMD_FLAG_ASYNC (1 << 0)
@@ -106,16 +103,12 @@ struct uath_softc {
enum ieee80211_state, int);
struct uath_tx_data tx_data[UATH_TX_DATA_LIST_COUNT];
- struct uath_rx_data rx_data[UATH_RX_DATA_POOL_COUNT];
+ struct uath_rx_data rx_data[UATH_RX_DATA_LIST_COUNT];
struct uath_tx_cmd tx_cmd[UATH_TX_CMD_LIST_COUNT];
struct uath_rx_cmd rx_cmd[UATH_RX_CMD_LIST_COUNT];
- SLIST_HEAD(, uath_rx_data) rx_freelist;
-
int sc_flags;
- int sc_dying;
- int sc_refcnt;
int data_idx;
int cmd_idx;