Diff below splits the functions that allocate memory for the various
ring to do it only once, in bge_attach(), instead of doing it every
time bge_init() is called, possibly in the watchdog function.

Tested with a "Broadcom BCM5714" rev 0xa3, BCM5715 A3 (0x9003).

Comments?  Ok?

Index: if_bge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.354
diff -u -p -r1.354 if_bge.c
--- if_bge.c    22 Apr 2014 11:54:46 -0000      1.354
+++ if_bge.c    21 May 2014 14:52:03 -0000
@@ -166,18 +166,24 @@ int bge_read_eeprom(struct bge_softc *, 
 void bge_iff(struct bge_softc *);
 
 int bge_newbuf_jumbo(struct bge_softc *, int);
+int bge_alloc_rx_ring_jumbo(struct bge_softc *);
 int bge_init_rx_ring_jumbo(struct bge_softc *);
 void bge_fill_rx_ring_jumbo(struct bge_softc *);
 void bge_free_rx_ring_jumbo(struct bge_softc *);
+void bge_drain_rx_ring_jumbo(struct bge_softc *);
 
 int bge_newbuf(struct bge_softc *, int);
+int bge_alloc_rx_ring_std(struct bge_softc *);
 int bge_init_rx_ring_std(struct bge_softc *);
 void bge_rxtick(void *);
 void bge_fill_rx_ring_std(struct bge_softc *);
 void bge_free_rx_ring_std(struct bge_softc *);
+void bge_drain_rx_ring_std(struct bge_softc *);
 
+int bge_alloc_tx_ring(struct bge_softc *);
 void bge_free_tx_ring(struct bge_softc *);
 int bge_init_tx_ring(struct bge_softc *);
+void bge_drain_tx_ring(struct bge_softc *);
 
 void bge_chipinit(struct bge_softc *);
 int bge_blockinit(struct bge_softc *);
@@ -1238,13 +1244,10 @@ bge_newbuf_jumbo(struct bge_softc *sc, i
  * the NIC.
  */
 int
-bge_init_rx_ring_std(struct bge_softc *sc)
+bge_alloc_rx_ring_std(struct bge_softc *sc)
 {
        int i;
 
-       if (ISSET(sc->bge_flags, BGE_RXRING_VALID))
-               return (0);
-
        for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
                if (bus_dmamap_create(sc->bge_dmatag, MCLBYTES, 1, MCLBYTES, 0,
                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
@@ -1257,12 +1260,6 @@ bge_init_rx_ring_std(struct bge_softc *s
                    sizeof(struct bge_rx_bd));
        }
 
-       sc->bge_std = BGE_STD_RX_RING_CNT - 1;
-       sc->bge_std_cnt = 0;
-       bge_fill_rx_ring_std(sc);
-
-       SET(sc->bge_flags, BGE_RXRING_VALID);
-
        return (0);
 
 uncreate:
@@ -1273,6 +1270,21 @@ uncreate:
        return (1);
 }
 
+int
+bge_init_rx_ring_std(struct bge_softc *sc)
+{
+       if (ISSET(sc->bge_flags, BGE_RXRING_VALID))
+               return (0);
+
+       sc->bge_std = BGE_STD_RX_RING_CNT - 1;
+       sc->bge_std_cnt = 0;
+       bge_fill_rx_ring_std(sc);
+
+       SET(sc->bge_flags, BGE_RXRING_VALID);
+
+       return (0);
+}
+
 void
 bge_rxtick(void *arg)
 {
@@ -1321,6 +1333,21 @@ void
 bge_free_rx_ring_std(struct bge_softc *sc)
 {
        bus_dmamap_t dmap;
+       int i;
+
+       for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
+               dmap = sc->bge_cdata.bge_rx_std_map[i];
+               bus_dmamap_destroy(sc->bge_dmatag, dmap);
+               sc->bge_cdata.bge_rx_std_map[i] = NULL;
+               bzero(&sc->bge_rdata->bge_rx_std_ring[i],
+                   sizeof(struct bge_rx_bd));
+       }
+}
+
+void
+bge_drain_rx_ring_std(struct bge_softc *sc)
+{
+       bus_dmamap_t dmap;
        struct mbuf *m;
        int i;
 
@@ -1337,24 +1364,16 @@ bge_free_rx_ring_std(struct bge_softc *s
                        m_freem(m);
                        sc->bge_cdata.bge_rx_std_chain[i] = NULL;
                }
-               bus_dmamap_destroy(sc->bge_dmatag, dmap);
-               sc->bge_cdata.bge_rx_std_map[i] = NULL;
-               bzero(&sc->bge_rdata->bge_rx_std_ring[i],
-                   sizeof(struct bge_rx_bd));
        }
 
        CLR(sc->bge_flags, BGE_RXRING_VALID);
 }
 
 int
-bge_init_rx_ring_jumbo(struct bge_softc *sc)
+bge_alloc_rx_ring_jumbo(struct bge_softc *sc)
 {
-       volatile struct bge_rcb *rcb;
        int i;
 
-       if (ISSET(sc->bge_flags, BGE_JUMBO_RXRING_VALID))
-               return (0);
-
        for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
                if (bus_dmamap_create(sc->bge_dmatag, BGE_JLEN, 4, BGE_JLEN, 0,
                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
@@ -1367,6 +1386,24 @@ bge_init_rx_ring_jumbo(struct bge_softc 
                    sizeof(struct bge_ext_rx_bd));
        }
 
+       return (0);
+
+uncreate:
+       while (--i) {
+               bus_dmamap_destroy(sc->bge_dmatag,
+                   sc->bge_cdata.bge_rx_jumbo_map[i]);
+       }
+       return (1);
+}
+
+int
+bge_init_rx_ring_jumbo(struct bge_softc *sc)
+{
+       volatile struct bge_rcb *rcb;
+
+       if (ISSET(sc->bge_flags, BGE_JUMBO_RXRING_VALID))
+               return (0);
+
        sc->bge_jumbo = BGE_JUMBO_RX_RING_CNT - 1;
        sc->bge_jumbo_cnt = 0;
        bge_fill_rx_ring_jumbo(sc);
@@ -1379,13 +1416,6 @@ bge_init_rx_ring_jumbo(struct bge_softc 
        CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
 
        return (0);
-
-uncreate:
-       while (--i) {
-               bus_dmamap_destroy(sc->bge_dmatag,
-                   sc->bge_cdata.bge_rx_jumbo_map[i]);
-       }
-       return (1);
 }
 
 void
@@ -1420,6 +1450,21 @@ void
 bge_free_rx_ring_jumbo(struct bge_softc *sc)
 {
        bus_dmamap_t dmap;
+       int i;
+
+       for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
+               dmap = sc->bge_cdata.bge_rx_jumbo_map[i];
+               bus_dmamap_destroy(sc->bge_dmatag, dmap);
+               sc->bge_cdata.bge_rx_jumbo_map[i] = NULL;
+               bzero(&sc->bge_rdata->bge_rx_jumbo_ring[i],
+                   sizeof(struct bge_ext_rx_bd));
+       }
+}
+
+void
+bge_drain_rx_ring_jumbo(struct bge_softc *sc)
+{
+       bus_dmamap_t dmap;
        struct mbuf *m;
        int i;
 
@@ -1436,20 +1481,15 @@ bge_free_rx_ring_jumbo(struct bge_softc 
                        m_freem(m);
                        sc->bge_cdata.bge_rx_jumbo_chain[i] = NULL;
                }
-               bus_dmamap_destroy(sc->bge_dmatag, dmap);
-               sc->bge_cdata.bge_rx_jumbo_map[i] = NULL;
-               bzero(&sc->bge_rdata->bge_rx_jumbo_ring[i],
-                   sizeof(struct bge_ext_rx_bd));
        }
 
        CLR(sc->bge_flags, BGE_JUMBO_RXRING_VALID);
 }
 
 void
-bge_free_tx_ring(struct bge_softc *sc)
+bge_drain_tx_ring(struct bge_softc *sc)
 {
        int i;
-       struct txdmamap_pool_entry *dma;
 
        if (!(sc->bge_flags & BGE_TXRING_VALID))
                return;
@@ -1466,39 +1506,28 @@ bge_free_tx_ring(struct bge_softc *sc)
                    sizeof(struct bge_tx_bd));
        }
 
+       sc->bge_flags &= ~BGE_TXRING_VALID;
+}
+
+void
+bge_free_tx_ring(struct bge_softc *sc)
+{
+       struct txdmamap_pool_entry *dma;
+
        while ((dma = SLIST_FIRST(&sc->txdma_list))) {
                SLIST_REMOVE_HEAD(&sc->txdma_list, link);
                bus_dmamap_destroy(sc->bge_dmatag, dma->dmamap);
                free(dma, M_DEVBUF);
        }
-
-       sc->bge_flags &= ~BGE_TXRING_VALID;
 }
 
 int
-bge_init_tx_ring(struct bge_softc *sc)
+bge_alloc_tx_ring(struct bge_softc *sc)
 {
        int i;
        bus_dmamap_t dmamap;
        struct txdmamap_pool_entry *dma;
 
-       if (sc->bge_flags & BGE_TXRING_VALID)
-               return (0);
-
-       sc->bge_txcnt = 0;
-       sc->bge_tx_saved_considx = 0;
-
-       /* Initialize transmit producer index for host-memory send ring. */
-       sc->bge_tx_prodidx = 0;
-       bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
-       if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX)
-               bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
-
-       /* NIC-memory send ring not used; initialize to zero. */
-       bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
-       if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX)
-               bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
-
        SLIST_INIT(&sc->txdma_list);
        for (i = 0; i < BGE_TX_RING_CNT; i++) {
                if (bus_dmamap_create(sc->bge_dmatag, BGE_JLEN,
@@ -1506,7 +1535,7 @@ bge_init_tx_ring(struct bge_softc *sc)
                    &dmamap))
                        return (ENOBUFS);
                if (dmamap == NULL)
-                       panic("dmamap NULL in bge_init_tx_ring");
+                       panic("dmamap NULL in %s", __func__);
                dma = malloc(sizeof(*dma), M_DEVBUF, M_NOWAIT);
                if (dma == NULL) {
                        printf("%s: can't alloc txdmamap_pool_entry\n",
@@ -1518,6 +1547,29 @@ bge_init_tx_ring(struct bge_softc *sc)
                SLIST_INSERT_HEAD(&sc->txdma_list, dma, link);
        }
 
+       return (0);
+}
+
+int
+bge_init_tx_ring(struct bge_softc *sc)
+{
+       if (sc->bge_flags & BGE_TXRING_VALID)
+               return (0);
+
+       sc->bge_txcnt = 0;
+       sc->bge_tx_saved_considx = 0;
+
+       /* Initialize transmit producer index for host-memory send ring. */
+       sc->bge_tx_prodidx = 0;
+       bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+       if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX)
+               bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+
+       /* NIC-memory send ring not used; initialize to zero. */
+       bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+       if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX)
+               bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+
        sc->bge_flags |= BGE_TXRING_VALID;
 
        return (0);
@@ -3077,6 +3129,15 @@ bge_attach(struct device *parent, struct
                goto fail_6;
        }
 
+       if (bge_alloc_rx_ring_std(sc))
+               goto fail_6;
+
+       if (BGE_IS_JUMBO_CAPABLE(sc) && bge_alloc_rx_ring_jumbo(sc))
+               goto fail_7;
+
+       if (bge_alloc_tx_ring(sc))
+               goto fail_8;
+
        /*
         * A Broadcom chip was detected. Inform the world.
         */
@@ -3127,6 +3188,15 @@ bge_attach(struct device *parent, struct
        timeout_set(&sc->bge_rxtimeout, bge_rxtick, sc);
        return;
 
+fail_8:
+       bge_free_tx_ring(sc);
+
+       if (BGE_IS_JUMBO_CAPABLE(sc))
+               bge_free_rx_ring_jumbo(sc);
+
+fail_7:
+       bge_free_rx_ring_std(sc);
+
 fail_6:
        bus_dmamap_unload(sc->bge_dmatag, sc->bge_ring_map);
 
@@ -4586,15 +4656,15 @@ bge_stop(struct bge_softc *sc)
         */
        BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
 
-       /* Free the RX lists. */
-       bge_free_rx_ring_std(sc);
+       /* Drain the RX lists. */
+       bge_drain_rx_ring_std(sc);
 
-       /* Free jumbo RX list. */
+       /* Drain jumbo RX list. */
        if (BGE_IS_JUMBO_CAPABLE(sc))
-               bge_free_rx_ring_jumbo(sc);
+               bge_drain_rx_ring_jumbo(sc);
 
-       /* Free TX buffers. */
-       bge_free_tx_ring(sc);
+       /* Drain TX buffers. */
+       bge_drain_tx_ring(sc);
 
        /*
         * Isolate/power down the PHY, but leave the media selection

Reply via email to