-/* $OpenBSD: if_bwfm_sdio.c,v 1.22 2018/07/16 13:46:17 patrick Exp $ */
+/* $OpenBSD: if_bwfm_sdio.c,v 1.23 2018/07/17 19:44:38 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
* Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
uint8_t sc_tx_seq;
uint8_t sc_tx_max_seq;
- struct mbuf_queue sc_txdata_queue;
+ struct mbuf_list sc_tx_queue;
+ int sc_tx_count;
struct task sc_task;
};
struct mbuf * bwfm_sdio_newbuf(void);
int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *);
-void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *);
-void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *);
+void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *);
+void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *, struct mbuf *);
+void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *, struct mbuf *);
void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *);
void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *, uint16_t *, int,
uint16_t *);
int bwfm_sdio_txcheck(struct bwfm_softc *);
int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *);
-int bwfm_sdio_txctl(struct bwfm_softc *);
+int bwfm_sdio_txctl(struct bwfm_softc *, void *);
#ifdef BWFM_DEBUG
void bwfm_sdio_debug_console(struct bwfm_sdio_softc *);
printf("\n");
task_set(&sc->sc_task, bwfm_sdio_task, sc);
- mq_init(&sc->sc_txdata_queue, 16, IPL_SOFTNET);
+ ml_init(&sc->sc_tx_queue);
sc->sc_bounce_size = 64 * 1024;
sc->sc_bounce_buf = dma_alloc(sc->sc_bounce_size, PR_WAITOK);
sc->sc_tx_seq = 0xff;
bwfm_sdio_rx_frames(sc);
}
- if (!TAILQ_EMPTY(&sc->sc_sc.sc_bcdc_txctlq)) {
- bwfm_sdio_tx_ctrlframe(sc);
- }
-
- if (!mq_empty(&sc->sc_txdata_queue)) {
- bwfm_sdio_tx_dataframe(sc);
+ if (!ml_empty(&sc->sc_tx_queue)) {
+ bwfm_sdio_tx_frames(sc);
}
#ifdef BWFM_DEBUG
}
void
-bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc)
+bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc)
{
- struct bwfm_sdio_hwhdr *hwhdr;
- struct bwfm_sdio_swhdr *swhdr;
- struct bwfm_proto_bcdc_ctl *ctl, *tmp;
- size_t len, roundto;
+ struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
+ struct mbuf *m;
+ int i;
if (!bwfm_sdio_tx_ok(sc))
return;
- TAILQ_FOREACH_SAFE(ctl, &sc->sc_sc.sc_bcdc_txctlq, next, tmp) {
- TAILQ_REMOVE(&sc->sc_sc.sc_bcdc_txctlq, ctl, next);
-
- len = sizeof(*hwhdr) + sizeof(*swhdr) + ctl->len;
+ i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32);
+ while (i--) {
+ m = ml_dequeue(&sc->sc_tx_queue);
+ if (m == NULL)
+ break;
- /* Zero-pad to either block-size or 4-byte alignment. */
- if (len > 512 && (len % 512) != 0)
- roundto = 512;
+ if (m->m_type == MT_CONTROL)
+ bwfm_sdio_tx_ctrlframe(sc, m);
else
- roundto = 4;
+ bwfm_sdio_tx_dataframe(sc, m);
- KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
+ m_freem(m);
+ }
+
+ if (sc->sc_tx_count < 64)
+ ifq_restart(&ifp->if_snd);
+}
- hwhdr = (void *)sc->sc_bounce_buf;
- hwhdr->frmlen = htole16(len);
- hwhdr->cksum = htole16(~len);
+void
+bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
+{
+ struct bwfm_sdio_hwhdr *hwhdr;
+ struct bwfm_sdio_swhdr *swhdr;
+ size_t len, roundto;
- swhdr = (void *)&hwhdr[1];
- swhdr->seqnr = sc->sc_tx_seq++;
- swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL;
- swhdr->nextlen = 0;
- swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
- swhdr->maxseqnr = 0;
+ len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len;
- memcpy(&swhdr[1], ctl->buf, ctl->len);
+ /* Zero-pad to either block-size or 4-byte alignment. */
+ if (len > 512 && (len % 512) != 0)
+ roundto = 512;
+ else
+ roundto = 4;
- if (roundup(len, roundto) != len)
- memset(sc->sc_bounce_buf + len, 0,
- roundup(len, roundto) - len);
+ KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
- bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
- roundup(len, roundto), 1);
+ hwhdr = (void *)sc->sc_bounce_buf;
+ hwhdr->frmlen = htole16(len);
+ hwhdr->cksum = htole16(~len);
- TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
- }
+ swhdr = (void *)&hwhdr[1];
+ swhdr->seqnr = sc->sc_tx_seq++;
+ swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL;
+ swhdr->nextlen = 0;
+ swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
+ swhdr->maxseqnr = 0;
+
+ m_copydata(m, 0, m->m_len, (caddr_t)&swhdr[1]);
+
+ if (roundup(len, roundto) != len)
+ memset(sc->sc_bounce_buf + len, 0,
+ roundup(len, roundto) - len);
+
+ bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
+ roundup(len, roundto), 1);
}
void
-bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc)
+bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
{
- struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if;
struct bwfm_sdio_hwhdr *hwhdr;
struct bwfm_sdio_swhdr *swhdr;
struct bwfm_proto_bcdc_hdr *bcdc;
size_t len, roundto;
- struct mbuf *m;
- int i;
- if (!bwfm_sdio_tx_ok(sc))
- return;
-
- i = min((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq), 32);
- while (i--) {
- m = mq_dequeue(&sc->sc_txdata_queue);
- if (m == NULL)
- break;
+ len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc)
+ + m->m_pkthdr.len;
- len = sizeof(*hwhdr) + sizeof(*swhdr) + sizeof(*bcdc)
- + m->m_pkthdr.len;
-
- /* Zero-pad to either block-size or 4-byte alignment. */
- if (len > 512 && (len % 512) != 0)
- roundto = 512;
- else
- roundto = 4;
-
- KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
+ /* Zero-pad to either block-size or 4-byte alignment. */
+ if (len > 512 && (len % 512) != 0)
+ roundto = 512;
+ else
+ roundto = 4;
- hwhdr = (void *)sc->sc_bounce_buf;
- hwhdr->frmlen = htole16(len);
- hwhdr->cksum = htole16(~len);
+ KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
- swhdr = (void *)&hwhdr[1];
- swhdr->seqnr = sc->sc_tx_seq++;
- swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA;
- swhdr->nextlen = 0;
- swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
- swhdr->maxseqnr = 0;
+ hwhdr = (void *)sc->sc_bounce_buf;
+ hwhdr->frmlen = htole16(len);
+ hwhdr->cksum = htole16(~len);
- bcdc = (void *)&swhdr[1];
- bcdc->data_offset = 0;
- bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m);
- bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER);
- bcdc->flags2 = 0;
+ swhdr = (void *)&hwhdr[1];
+ swhdr->seqnr = sc->sc_tx_seq++;
+ swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_DATA;
+ swhdr->nextlen = 0;
+ swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
+ swhdr->maxseqnr = 0;
- m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]);
+ bcdc = (void *)&swhdr[1];
+ bcdc->data_offset = 0;
+ bcdc->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m);
+ bcdc->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER);
+ bcdc->flags2 = 0;
- if (roundup(len, roundto) != len)
- memset(sc->sc_bounce_buf + len, 0,
- roundup(len, roundto) - len);
+ m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcdc[1]);
- bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
- roundup(len, roundto), 1);
+ if (roundup(len, roundto) != len)
+ memset(sc->sc_bounce_buf + len, 0,
+ roundup(len, roundto) - len);
- m_freem(m);
- }
+ bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
+ roundup(len, roundto), 1);
- if (!mq_full(&sc->sc_txdata_queue))
- ifq_restart(&ifp->if_snd);
+ sc->sc_tx_count--;
}
void
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
- if (mq_full(&sc->sc_txdata_queue))
+ if (sc->sc_tx_count >= 64)
return ENOBUFS;
return 0;
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
- if (mq_full(&sc->sc_txdata_queue))
+ if (sc->sc_tx_count >= 64)
return ENOBUFS;
- mq_enqueue(&sc->sc_txdata_queue, m);
+ sc->sc_tx_count++;
+ ml_enqueue(&sc->sc_tx_queue, m);
task_add(systq, &sc->sc_task);
return 0;
}
int
-bwfm_sdio_txctl(struct bwfm_softc *bwfm)
+bwfm_sdio_txctl(struct bwfm_softc *bwfm, void *arg)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
+ struct bwfm_proto_bcdc_ctl *ctl = arg;
+ struct mbuf *m;
+
+ MGET(m, M_DONTWAIT, MT_CONTROL);
+ if (m == NULL || M_TRAILINGSPACE(m) < ctl->len) {
+ free(ctl->buf, M_TEMP, ctl->len);
+ free(ctl, M_TEMP, sizeof(*ctl));
+ return 1;
+ }
+ memcpy(mtod(m, char *), ctl->buf, ctl->len);
+ m->m_len = ctl->len;
+
+ TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
+ ml_enqueue(&sc->sc_tx_queue, m);
task_add(systq, &sc->sc_task);
return 0;
}
-/* $OpenBSD: if_bwfm_usb.c,v 1.15 2018/05/23 14:15:06 patrick Exp $ */
+/* $OpenBSD: if_bwfm_usb.c,v 1.16 2018/07/17 19:44:38 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
* Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
int bwfm_usb_preinit(struct bwfm_softc *);
int bwfm_usb_txcheck(struct bwfm_softc *);
int bwfm_usb_txdata(struct bwfm_softc *, struct mbuf *);
-int bwfm_usb_txctl(struct bwfm_softc *);
+int bwfm_usb_txctl(struct bwfm_softc *, void *);
void bwfm_usb_txctl_cb(struct usbd_xfer *, void *, usbd_status);
struct mbuf * bwfm_usb_newbuf(void);
}
int
-bwfm_usb_txctl(struct bwfm_softc *bwfm)
+bwfm_usb_txctl(struct bwfm_softc *bwfm, void *arg)
{
struct bwfm_usb_softc *sc = (void *)bwfm;
- struct bwfm_proto_bcdc_ctl *ctl, *tmp;
+ struct bwfm_proto_bcdc_ctl *ctl = arg;
usb_device_request_t req;
struct usbd_xfer *xfer;
usbd_status error;
DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
- TAILQ_FOREACH_SAFE(ctl, &sc->sc_sc.sc_bcdc_txctlq, next, tmp) {
- TAILQ_REMOVE(&sc->sc_sc.sc_bcdc_txctlq, ctl, next);
-
- /* Send out control packet. */
- req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- req.bRequest = 0;
- USETW(req.wValue, 0);
- USETW(req.wIndex, sc->sc_ifaceno);
- USETW(req.wLength, ctl->len);
-
- error = usbd_do_request(sc->sc_udev, &req, ctl->buf);
- if (error != 0) {
- printf("%s: could not write ctl packet: %s\n",
- DEVNAME(sc), usbd_errstr(error));
- free(ctl->buf, M_TEMP, ctl->len);
- free(ctl, M_TEMP, sizeof(*ctl));
- return 1;
- }
+ /* Send out control packet. */
+ req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+ req.bRequest = 0;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, sc->sc_ifaceno);
+ USETW(req.wLength, ctl->len);
- /* Setup asynchronous receive. */
- if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
- free(ctl->buf, M_TEMP, ctl->len);
- free(ctl, M_TEMP, sizeof(*ctl));
- return 1;
- }
- if ((buf = usbd_alloc_buffer(xfer, ctl->len)) == NULL) {
- free(ctl->buf, M_TEMP, ctl->len);
- free(ctl, M_TEMP, sizeof(*ctl));
- usbd_free_xfer(xfer);
- return 1;
- }
+ error = usbd_do_request(sc->sc_udev, &req, ctl->buf);
+ if (error != 0) {
+ printf("%s: could not write ctl packet: %s\n",
+ DEVNAME(sc), usbd_errstr(error));
+ free(ctl->buf, M_TEMP, ctl->len);
+ free(ctl, M_TEMP, sizeof(*ctl));
+ return 1;
+ }
- memset(buf, 0, ctl->len);
- req.bmRequestType = UT_READ_CLASS_INTERFACE;
- req.bRequest = 1;
- USETW(req.wValue, 0);
- USETW(req.wIndex, sc->sc_ifaceno);
- USETW(req.wLength, ctl->len);
+ /* Setup asynchronous receive. */
+ if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
+ free(ctl->buf, M_TEMP, ctl->len);
+ free(ctl, M_TEMP, sizeof(*ctl));
+ return 1;
+ }
+ if ((buf = usbd_alloc_buffer(xfer, ctl->len)) == NULL) {
+ free(ctl->buf, M_TEMP, ctl->len);
+ free(ctl, M_TEMP, sizeof(*ctl));
+ usbd_free_xfer(xfer);
+ return 1;
+ }
- error = usbd_request_async(xfer, &req, sc, bwfm_usb_txctl_cb);
- if (error != 0) {
- printf("%s: could not read ctl packet: %s\n",
- DEVNAME(sc), usbd_errstr(error));
- free(ctl->buf, M_TEMP, ctl->len);
- free(ctl, M_TEMP, sizeof(*ctl));
- usbd_free_xfer(xfer);
- return 1;
- }
+ memset(buf, 0, ctl->len);
+ req.bmRequestType = UT_READ_CLASS_INTERFACE;
+ req.bRequest = 1;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, sc->sc_ifaceno);
+ USETW(req.wLength, ctl->len);
- TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
+ error = usbd_request_async(xfer, &req, sc, bwfm_usb_txctl_cb);
+ if (error != 0) {
+ printf("%s: could not read ctl packet: %s\n",
+ DEVNAME(sc), usbd_errstr(error));
+ free(ctl->buf, M_TEMP, ctl->len);
+ free(ctl, M_TEMP, sizeof(*ctl));
+ usbd_free_xfer(xfer);
+ return 1;
}
+ TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next);
+
return 0;
}