Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144500576
D11705.1775033982.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D11705.1775033982.diff
View Options
Index: head/sys/dev/rtwn/if_rtwnreg.h
===================================================================
--- head/sys/dev/rtwn/if_rtwnreg.h
+++ head/sys/dev/rtwn/if_rtwnreg.h
@@ -18,6 +18,9 @@
* $FreeBSD$
*/
+#ifndef IF_RTWNREG_H
+#define IF_RTWNREG_H
+
#define R92C_MIN_TX_PWR 0x00
#define R92C_MAX_TX_PWR 0x3f
@@ -165,3 +168,5 @@
return (chan);
}
+
+#endif /* IF_RTWNREG_H */
Index: head/sys/dev/rtwn/usb/rtwn_usb_attach.c
===================================================================
--- head/sys/dev/rtwn/usb/rtwn_usb_attach.c
+++ head/sys/dev/rtwn/usb/rtwn_usb_attach.c
@@ -77,12 +77,14 @@
struct ieee80211vap *);
static void rtwn_usb_reset_tx_list(struct rtwn_usb_softc *,
rtwn_datahead *, struct ieee80211vap *);
+static void rtwn_usb_reset_rx_list(struct rtwn_usb_softc *);
static void rtwn_usb_start_xfers(struct rtwn_softc *);
static void rtwn_usb_abort_xfers(struct rtwn_softc *);
static int rtwn_usb_fw_write_block(struct rtwn_softc *,
const uint8_t *, uint16_t, int);
static void rtwn_usb_drop_incorrect_tx(struct rtwn_softc *);
static void rtwn_usb_attach_methods(struct rtwn_softc *);
+static void rtwn_usb_sysctlattach(struct rtwn_softc *);
#define RTWN_CONFIG_INDEX 0
@@ -133,9 +135,8 @@
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
int error, i;
- /* XXX recheck */
error = rtwn_usb_alloc_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT,
- sc->rx_dma_size + 1024);
+ uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT);
if (error != 0)
return (error);
@@ -199,6 +200,9 @@
rtwn_usb_free_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT);
+ uc->uc_rx_stat_len = 0;
+ uc->uc_rx_off = 0;
+
STAILQ_INIT(&uc->uc_rx_active);
STAILQ_INIT(&uc->uc_rx_inactive);
}
@@ -224,8 +228,10 @@
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_active, vap);
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_pending, vap);
- if (vap == NULL)
+ if (vap == NULL) {
+ rtwn_usb_reset_rx_list(uc);
sc->qfullmsk = 0;
+ }
}
static void
@@ -259,6 +265,23 @@
}
static void
+rtwn_usb_reset_rx_list(struct rtwn_usb_softc *uc)
+{
+ int i;
+
+ for (i = 0; i < RTWN_USB_RX_LIST_COUNT; i++) {
+ struct rtwn_data *dp = &uc->uc_rx[i];
+
+ if (dp->m != NULL) {
+ m_freem(dp->m);
+ dp->m = NULL;
+ }
+ }
+ uc->uc_rx_stat_len = 0;
+ uc->uc_rx_off = 0;
+}
+
+static void
rtwn_usb_start_xfers(struct rtwn_softc *sc)
{
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
@@ -327,6 +350,31 @@
sc->bcn_check_interval = 100;
}
+static void
+rtwn_usb_sysctlattach(struct rtwn_softc *sc)
+{
+ struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
+ char str[64];
+ int ret;
+
+ ret = snprintf(str, sizeof(str),
+ "Rx buffer size, 512-byte units [%d...%d]",
+ RTWN_USB_RXBUFSZ_MIN, RTWN_USB_RXBUFSZ_MAX);
+ KASSERT(ret > 0, ("ret (%d) <= 0!\n", ret));
+ (void) ret;
+
+ uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_DEF;
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "rx_buf_size", CTLFLAG_RDTUN, &uc->uc_rx_buf_size,
+ uc->uc_rx_buf_size, str);
+ if (uc->uc_rx_buf_size < RTWN_USB_RXBUFSZ_MIN)
+ uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MIN;
+ if (uc->uc_rx_buf_size > RTWN_USB_RXBUFSZ_MAX)
+ uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MAX;
+}
+
static int
rtwn_usb_attach(device_t self)
{
@@ -343,6 +391,7 @@
/* Need to be initialized early. */
rtwn_sysctlattach(sc);
+ rtwn_usb_sysctlattach(sc);
mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF);
rtwn_usb_attach_methods(sc);
Index: head/sys/dev/rtwn/usb/rtwn_usb_ep.c
===================================================================
--- head/sys/dev/rtwn/usb/rtwn_usb_ep.c
+++ head/sys/dev/rtwn/usb/rtwn_usb_ep.c
@@ -225,7 +225,8 @@
break;
}
- rtwn_config[RTWN_BULK_RX].bufsize = sc->rx_dma_size + 1024;
+ rtwn_config[RTWN_BULK_RX].bufsize =
+ uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT;
error = usbd_transfer_setup(uc->uc_udev, &iface_index,
uc->uc_xfer, rtwn_config, RTWN_N_TRANSFER, uc, &sc->sc_mtx);
free(rtwn_config, M_TEMP);
Index: head/sys/dev/rtwn/usb/rtwn_usb_rx.c
===================================================================
--- head/sys/dev/rtwn/usb/rtwn_usb_rx.c
+++ head/sys/dev/rtwn/usb/rtwn_usb_rx.c
@@ -63,31 +63,24 @@
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/usb/rtwn_usb_rx.h>
+static struct mbuf * rtwn_rxeof(struct rtwn_softc *, struct rtwn_data *,
+ uint8_t *, int);
-static struct mbuf *
-rtwn_rx_copy_to_mbuf(struct rtwn_softc *sc, struct rtwn_rx_stat_common *stat,
- int totlen)
+static int
+rtwn_rx_check_pre_alloc(struct rtwn_softc *sc,
+ struct rtwn_rx_stat_common *stat)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct mbuf *m;
uint32_t rxdw0;
int pktlen;
RTWN_ASSERT_LOCKED(sc);
- /* Dump Rx descriptor. */
- RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
- "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X\n",
- __func__, le32toh(stat->rxdw0), le32toh(stat->rxdw1),
- le32toh(stat->rxdw2), le32toh(stat->rxdw3), le32toh(stat->rxdw4),
- le32toh(stat->tsf_low));
-
/*
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
if (!(sc->sc_flags & RTWN_RUNNING))
- return (NULL);
+ return (-1);
rxdw0 = le32toh(stat->rxdw0);
if (__predict_false(rxdw0 & (RTWN_RXDW0_CRCERR | RTWN_RXDW0_ICVERR))) {
@@ -98,7 +91,7 @@
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: RX flags error (%s)\n", __func__,
rxdw0 & RTWN_RXDW0_CRCERR ? "CRC" : "ICV");
- goto fail;
+ return (-1);
}
pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
@@ -108,9 +101,31 @@
*/
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: frame is too short: %d\n", __func__, pktlen);
- goto fail;
+ return (-1);
}
+ return (0);
+}
+
+static struct mbuf *
+rtwn_rx_copy_to_mbuf(struct rtwn_softc *sc, struct rtwn_rx_stat_common *stat,
+ int totlen)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct mbuf *m;
+
+ RTWN_ASSERT_LOCKED(sc);
+
+ /* Dump Rx descriptor. */
+ RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
+ "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X\n",
+ __func__, le32toh(stat->rxdw0), le32toh(stat->rxdw1),
+ le32toh(stat->rxdw2), le32toh(stat->rxdw3), le32toh(stat->rxdw4),
+ le32toh(stat->tsf_low));
+
+ if (rtwn_rx_check_pre_alloc(sc, stat) != 0)
+ goto fail;
+
m = m_get2(totlen, M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m == NULL)) {
device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
@@ -134,14 +149,108 @@
}
static struct mbuf *
-rtwn_rxeof(struct rtwn_softc *sc, uint8_t *buf, int len)
+rtwn_rxeof_fragmented(struct rtwn_usb_softc *uc, struct rtwn_data *data,
+ uint8_t *buf, int len)
{
+ struct rtwn_softc *sc = &uc->uc_sc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct rtwn_rx_stat_common *stat = &uc->uc_rx_stat;
+ uint32_t rxdw0;
+ int totlen, pktlen, infosz, min_len;
+ int orig_len = len;
+ int alloc_mbuf = 0;
+
+ /* Check if Rx descriptor is not truncated. */
+ if (uc->uc_rx_stat_len < sizeof(*stat)) {
+ min_len = min(sizeof(*stat) - uc->uc_rx_stat_len, len);
+ memcpy((uint8_t *)stat + uc->uc_rx_stat_len, buf, min_len);
+
+ uc->uc_rx_stat_len += min_len;
+ buf += min_len;
+ len -= min_len;
+
+ if (uc->uc_rx_stat_len < sizeof(*stat))
+ goto end;
+
+ KASSERT(data->m == NULL, ("%s: data->m != NULL!\n", __func__));
+ alloc_mbuf = 1;
+
+ /* Dump Rx descriptor. */
+ RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
+ "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, "
+ "tsfl %08X\n", __func__, le32toh(stat->rxdw0),
+ le32toh(stat->rxdw1), le32toh(stat->rxdw2),
+ le32toh(stat->rxdw3), le32toh(stat->rxdw4),
+ le32toh(stat->tsf_low));
+ }
+
+ rxdw0 = le32toh(stat->rxdw0);
+ pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
+ infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8;
+ totlen = sizeof(*stat) + infosz + pktlen;
+ if (alloc_mbuf) {
+ if (rtwn_rx_check_pre_alloc(sc, stat) == 0) {
+ data->m = m_getm(NULL, totlen, M_NOWAIT, MT_DATA);
+ if (data->m != NULL) {
+ m_copyback(data->m, 0, uc->uc_rx_stat_len,
+ (caddr_t)stat);
+
+ if (rtwn_check_frame(sc, data->m) != 0) {
+ m_freem(data->m);
+ data->m = NULL;
+ counter_u64_add(ic->ic_ierrors, 1);
+ }
+ } else
+ counter_u64_add(ic->ic_ierrors, 1);
+ } else
+ counter_u64_add(ic->ic_ierrors, 1);
+
+ uc->uc_rx_off = sizeof(*stat);
+ }
+
+ /* If mbuf allocation fails just discard the data. */
+ min_len = min(totlen - uc->uc_rx_off, len);
+ if (data->m != NULL)
+ m_copyback(data->m, uc->uc_rx_off, min_len, buf);
+
+ uc->uc_rx_off += min_len;
+ if (uc->uc_rx_off == totlen) {
+ /* Align next frame. */
+ min_len = rtwn_usb_align_rx(uc,
+ orig_len - len + min_len, orig_len);
+ min_len -= (orig_len - len);
+ KASSERT(len >= min_len, ("%s: len (%d) < min_len (%d)!\n",
+ __func__, len, min_len));
+
+ /* Clear mbuf stats. */
+ uc->uc_rx_stat_len = 0;
+ uc->uc_rx_off = 0;
+ }
+ len -= min_len;
+ buf += min_len;
+end:
+ if (uc->uc_rx_stat_len == 0)
+ return (rtwn_rxeof(sc, data, buf, len));
+ else
+ return (NULL);
+}
+
+static struct mbuf *
+rtwn_rxeof(struct rtwn_softc *sc, struct rtwn_data *data, uint8_t *buf,
+ int len)
+{
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
struct rtwn_rx_stat_common *stat;
struct mbuf *m, *m0 = NULL;
uint32_t rxdw0;
int totlen, pktlen, infosz;
+ /* Prepend defragmented frame (if any). */
+ if (data->m != NULL) {
+ m0 = m = data->m;
+ data->m = NULL;
+ }
+
/* Process packets. */
while (len >= sizeof(*stat)) {
stat = (struct rtwn_rx_stat_common *)buf;
@@ -156,8 +265,8 @@
/* Make sure everything fits in xfer. */
totlen = sizeof(*stat) + infosz + pktlen;
if (totlen > len) {
- device_printf(sc->sc_dev,
- "%s: totlen (%d) > len (%d)!\n",
+ RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
+ "%s: frame is fragmented (totlen %d len %d)\n",
__func__, totlen, len);
break;
}
@@ -165,9 +274,9 @@
if (m0 == NULL)
m0 = m = rtwn_rx_copy_to_mbuf(sc, stat, totlen);
else {
- m->m_next = rtwn_rx_copy_to_mbuf(sc, stat, totlen);
- if (m->m_next != NULL)
- m = m->m_next;
+ m->m_nextpkt = rtwn_rx_copy_to_mbuf(sc, stat, totlen);
+ if (m->m_nextpkt != NULL)
+ m = m->m_nextpkt;
}
/* Align next frame. */
@@ -176,6 +285,9 @@
len -= totlen;
}
+ if (len > 0)
+ (void)rtwn_rxeof_fragmented(uc, data, buf, len);
+
return (m0);
}
@@ -190,15 +302,19 @@
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
- if (__predict_false(len < sizeof(struct rtwn_rx_stat_common))) {
+ if (__predict_false(len < sizeof(struct rtwn_rx_stat_common) &&
+ uc->uc_rx_stat_len == 0)) {
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
buf = data->buf;
+ if (uc->uc_rx_stat_len > 0)
+ return (rtwn_rxeof_fragmented(uc, data, data->buf, len));
+
switch (rtwn_classify_intr(sc, buf, len)) {
case RTWN_RX_DATA:
- return (rtwn_rxeof(sc, buf, len));
+ return (rtwn_rxeof(sc, data, buf, len));
case RTWN_RX_TX_REPORT:
if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
/* shouldn't happen */
@@ -284,8 +400,8 @@
* callback and safe to unlock.
*/
while (m != NULL) {
- next = m->m_next;
- m->m_next = NULL;
+ next = m->m_nextpkt;
+ m->m_nextpkt = NULL;
ni = rtwn_rx_frame(sc, m);
@@ -309,6 +425,8 @@
STAILQ_INSERT_TAIL(&uc->uc_rx_inactive, data, next);
}
if (error != USB_ERR_CANCELLED) {
+ /* XXX restart device if frame was fragmented? */
+
usbd_xfer_set_stall(xfer);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
Index: head/sys/dev/rtwn/usb/rtwn_usb_var.h
===================================================================
--- head/sys/dev/rtwn/usb/rtwn_usb_var.h
+++ head/sys/dev/rtwn/usb/rtwn_usb_var.h
@@ -21,6 +21,12 @@
#ifndef RTWN_USBVAR_H
#define RTWN_USBVAR_H
+#include <dev/rtwn/if_rtwnreg.h> /* for struct rtwn_rx_stat_common */
+
+#define RTWN_USB_RXBUFSZ_UNIT (512)
+#define RTWN_USB_RXBUFSZ_MIN ( 4)
+#define RTWN_USB_RXBUFSZ_DEF (24)
+#define RTWN_USB_RXBUFSZ_MAX (64)
#define RTWN_USB_TXBUFSZ (16 * 1024)
#define RTWN_IFACE_INDEX 0
@@ -58,6 +64,12 @@
struct rtwn_data uc_rx[RTWN_USB_RX_LIST_COUNT];
rtwn_datahead uc_rx_active;
rtwn_datahead uc_rx_inactive;
+ int uc_rx_buf_size;
+
+ struct rtwn_rx_stat_common uc_rx_stat;
+ int uc_rx_stat_len;
+ int uc_rx_off;
+
struct rtwn_data uc_tx[RTWN_USB_TX_LIST_COUNT];
rtwn_datahead uc_tx_active;
rtwn_datahead uc_tx_inactive;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 1, 8:59 AM (4 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28238096
Default Alt Text
D11705.1775033982.diff (12 KB)
Attached To
Mode
D11705: rtwn_usb: add support for fragmented Rx
Attached
Detach File
Event Timeline
Log In to Comment