The PCI bwfm(4) chips have no TX rings in the traditional sense, as on
authorpatrick <patrick@openbsd.org>
Thu, 11 Jan 2018 16:09:19 +0000 (16:09 +0000)
committerpatrick <patrick@openbsd.org>
Thu, 11 Jan 2018 16:09:19 +0000 (16:09 +0000)
the actual rings we only share messages.  Sending a TX packet means
putting a message on the ring which contains a pktid (which for us maps
to an mbuf) and the physical address of the mbuf.  On jcs@'s macbook he
seems to run out of TX pktids pretty quickly during a speedtest.  This
would mean that there are 2048 TX packets in flight that we either want
to send out or that have not been "acked" by the firmware yet.  Either
way, recover from that situation when we hit that arbitrary limit by
restarting the queue after we free'd a packet from the TX pktid list.

Tested by jcs@

sys/dev/pci/if_bwfm_pci.c

index 0a8430b..a195ba9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bwfm_pci.c,v 1.15 2018/01/10 17:54:26 jcs Exp $    */
+/*     $OpenBSD: if_bwfm_pci.c,v 1.16 2018/01/11 16:09:19 patrick Exp $        */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -166,8 +166,9 @@ struct bwfm_pci_softc {
        struct if_rxring         sc_event_ring;
        struct if_rxring         sc_rxbuf_ring;
 
-       struct bwfm_pci_pkts     sc_tx_pkts;
        struct bwfm_pci_pkts     sc_rx_pkts;
+       struct bwfm_pci_pkts     sc_tx_pkts;
+       int                      sc_tx_pkts_full;
 };
 
 struct bwfm_pci_dmamem {
@@ -1275,6 +1276,10 @@ bwfm_pci_msg_rx(struct bwfm_pci_softc *sc, void *buf)
                if (m == NULL)
                        break;
                m_freem(m);
+               if (sc->sc_tx_pkts_full) {
+                       sc->sc_tx_pkts_full = 0;
+                       ifq_restart(&ifp->if_snd);
+               }
                break;
        case MSGBUF_TYPE_RX_CMPLT:
                rx = (struct msgbuf_rx_complete *)buf;
@@ -1670,6 +1675,7 @@ bwfm_pci_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
 
        ret = bwfm_pci_pktid_new(sc, &sc->sc_tx_pkts, m, &pktid, &paddr);
        if (ret) {
+               sc->sc_tx_pkts_full = 1;
                bwfm_pci_ring_write_cancel(sc, ring, 1);
                return ret;
        }