> Date: Fri, 23 May 2014 10:40:49 +0200
> From: Martin Pieuchot <[email protected]>
>
> 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?
I think that's a step backwards. If an interface is unconfigured it
should not consume any resources (such as memory) that are not needed.
> 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
>
>