diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2007-09-11 19:53:59 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2007-09-11 19:53:59 +0000 |
commit | c2d0515f866b7f9188a2222b22025cd81b8f715f (patch) | |
tree | a281f286e7597160b2ffd6829854cb141cb7b677 | |
parent | 74d17e9294521ce905bfcfe3391da47d35d12b01 (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.c | 99 | ||||
-rw-r--r-- | sys/dev/usb/if_uathvar.h | 19 |
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; |