summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-01-17 20:46:52 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-01-17 20:46:52 +0000
commit163f2ee6109ffb7d99c0b8d96efd9db690952ba4 (patch)
treeb550b90e37adc3ec9a6d158a19e4b8631ab101f4 /sys
parent6f7d4532d62449bc3298e3f3e64f058a5870560c (diff)
Fix RX queue stalling by regulary reading the device statistics (with a
firmware command). Doh! We can now reliable communicate in 11g. Took me about 3 weeks to find out (just had to say that).
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/if_upgt.c63
-rw-r--r--sys/dev/usb/if_upgtvar.h9
2 files changed, 70 insertions, 2 deletions
diff --git a/sys/dev/usb/if_upgt.c b/sys/dev/usb/if_upgt.c
index 978e7986d30..3bac935452d 100644
--- a/sys/dev/usb/if_upgt.c
+++ b/sys/dev/usb/if_upgt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_upgt.c,v 1.17 2008/01/17 07:23:45 mglocker Exp $ */
+/* $OpenBSD: if_upgt.c,v 1.18 2008/01/17 20:46:51 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -118,6 +118,7 @@ void upgt_rx_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
void upgt_rx(struct upgt_softc *, uint8_t *, int);
int upgt_set_macfilter(struct upgt_softc *, uint8_t state);
int upgt_set_channel(struct upgt_softc *, unsigned);
+int upgt_get_stats(struct upgt_softc *);
int upgt_alloc_tx(struct upgt_softc *);
int upgt_alloc_rx(struct upgt_softc *);
@@ -1528,6 +1529,13 @@ upgt_tx_task(void *arg)
sc->sc_dev.dv_xname, len);
}
+ /*
+ * If we don't regulary read the device statistics, the RX queue
+ * will stall. It's strange, but it works, so we keep reading
+ * the statistics here. *shrug*
+ */
+ upgt_get_stats(sc);
+
splx(s);
}
@@ -1633,6 +1641,13 @@ upgt_rx_cb(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
sc->sc_dev.dv_xname);
upgt_rx(sc, data_rx->buf + 4, letoh16(header->header1.len));
+ } else
+ if (h1_type == UPGT_H1_TYPE_CTRL &&
+ h2_type == UPGT_H2_TYPE_STATS) {
+ DPRINTF(2, "%s: received statistic data\n",
+ sc->sc_dev.dv_xname);
+
+ /* TODO: what could we do with the statistic data? */
} else {
/* ignore unknown frame types */
DPRINTF(1, "%s: received unknown frame type 0x%02x\n",
@@ -1858,6 +1873,52 @@ upgt_set_channel(struct upgt_softc *sc, unsigned channel)
}
int
+upgt_get_stats(struct upgt_softc *sc)
+{
+ struct upgt_data *data_cmd = &sc->cmd_data;
+ struct upgt_lmac_mem *mem;
+ struct upgt_lmac_stats *stats;
+ int len;
+
+ DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
+
+ /*
+ * Transmit the URB containing the CMD data.
+ */
+ bzero(data_cmd->buf, MCLBYTES);
+
+ mem = (struct upgt_lmac_mem *)data_cmd->buf;
+ mem->addr = htole32(sc->sc_memaddr_frame_start +
+ UPGT_MEMSIZE_FRAME_HEAD);
+
+ stats = (struct upgt_lmac_stats *)(mem + 1);
+
+ stats->header1.flags = 0;
+ stats->header1.type = UPGT_H1_TYPE_CTRL;
+ stats->header1.len = htole16(
+ sizeof(struct upgt_lmac_stats) -
+ sizeof(struct upgt_lmac_header));
+
+ stats->header2.reqid = htole32(sc->sc_memaddr_frame_start);
+ stats->header2.type = htole16(UPGT_H2_TYPE_STATS);
+ stats->header2.flags = 0;
+
+ len = sizeof(*mem) + sizeof(*stats);
+
+ mem->chksum = htole32(upgt_chksum((uint32_t *)stats,
+ len - sizeof(*mem)));
+
+ if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
+ printf("%s: could not transmit statistics CMD data URB!\n",
+ sc->sc_dev.dv_xname);
+ return (EIO);
+ }
+
+ return (0);
+
+}
+
+int
upgt_alloc_tx(struct upgt_softc *sc)
{
int i;
diff --git a/sys/dev/usb/if_upgtvar.h b/sys/dev/usb/if_upgtvar.h
index cb141a65c2a..d99b64b60c5 100644
--- a/sys/dev/usb/if_upgtvar.h
+++ b/sys/dev/usb/if_upgtvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_upgtvar.h,v 1.7 2008/01/17 07:23:45 mglocker Exp $ */
+/* $OpenBSD: if_upgtvar.h,v 1.8 2008/01/17 20:46:51 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -217,6 +217,7 @@ struct upgt_lmac_h1 {
#define UPGT_H2_TYPE_MACFILTER 0x0000
#define UPGT_H2_TYPE_CHANNEL 0x0001
#define UPGT_H2_TYPE_TX_DONE 0x0008
+#define UPGT_H2_TYPE_STATS 0x000a
#define UPGT_H2_TYPE_EEPROM 0x000c
#define UPGT_H2_FLAGS_TX_ACK_NO 0x0101
#define UPGT_H2_FLAGS_TX_ACK_YES 0x0707
@@ -303,6 +304,12 @@ struct upgt_lmac_channel {
uint32_t pad2;
} __packed;
+struct upgt_lmac_stats {
+ struct upgt_lmac_h1 header1;
+ struct upgt_lmac_h2 header2;
+ uint8_t data[76];
+} __packed;
+
struct upgt_lmac_rx_desc {
struct upgt_lmac_h1 header1;
/* 16 bytes */