This is mostly a backout of if_bnx.c r1.77, which introduced lists of tx
descriptors, allocated on demand, in order to avoid allocating space per ring
slot.  These days I think we can afford a few kb of memory overhead if it
makes the packets go faster.

Aside from that, there are the usual mpsafe network driver changes.
intr_barrier in bnx_stop, don't try to receive packets if the rxring is empty,
kernel lock around operations other than rx and tx completion in the interrupt
handler, adjust the tx counter using atomics, and rework bnx_start to check for
ring space before dequeuing and drop the packet if bnx_encap fails.

I've tested this on amd64 with the onboard bnx in a dell 2950:
bnx0 at pci4 dev 0 function 0 "Broadcom BCM5708" rev 0x12: apic 8 int 16

and I should be able to try it on BCM5709 soon too.

ok?


Index: if_bnx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v
retrieving revision 1.117
diff -u -p -r1.117 if_bnx.c
--- if_bnx.c    25 Nov 2015 03:09:59 -0000      1.117
+++ if_bnx.c    2 Dec 2015 10:38:20 -0000
@@ -365,7 +365,7 @@ void        bnx_free_rx_chain(struct bnx_softc 
 void   bnx_free_tx_chain(struct bnx_softc *);
 void   bnx_rxrefill(void *);
 
-int    bnx_tx_encap(struct bnx_softc *, struct mbuf *);
+int    bnx_tx_encap(struct bnx_softc *, struct mbuf *, int *);
 void   bnx_start(struct ifnet *);
 int    bnx_ioctl(struct ifnet *, u_long, caddr_t);
 void   bnx_watchdog(struct ifnet *);
@@ -388,10 +388,6 @@ void       bnx_iff(struct bnx_softc *);
 void   bnx_stats_update(struct bnx_softc *);
 void   bnx_tick(void *);
 
-struct rwlock bnx_tx_pool_lk = RWLOCK_INITIALIZER("bnxplinit");
-struct pool *bnx_tx_pool = NULL;
-void   bnx_alloc_pkts(void *);
-
 /****************************************************************************/
 /* OpenBSD device dispatch table.                                           */
 /****************************************************************************/
@@ -745,8 +741,8 @@ bnx_attach(struct device *parent, struct
                sc->bnx_flags |= BNX_PCI_32BIT_FLAG;
 
        /* Hookup IRQ last. */
-       sc->bnx_intrhand = pci_intr_establish(pc, sc->bnx_ih, IPL_NET,
-           bnx_intr, sc, sc->bnx_dev.dv_xname);
+       sc->bnx_intrhand = pci_intr_establish(pc, sc->bnx_ih,
+           IPL_NET | IPL_MPSAFE, bnx_intr, sc, sc->bnx_dev.dv_xname);
        if (sc->bnx_intrhand == NULL) {
                printf(": couldn't establish interrupt");
                if (intrstr != NULL)
@@ -2365,8 +2361,11 @@ bnx_dma_free(struct bnx_softc *sc)
                }
        }
 
-       /* Destroy the TX dmamaps. */
-       /* This isn't necessary since we dont allocate them up front */
+       /* Unload and destroy the TX mbuf maps. */
+       for (i = 0; i < TOTAL_TX_BD; i++) {
+               bus_dmamap_unload(sc->bnx_dmatag, sc->tx_mbuf_map[i]);
+               bus_dmamap_destroy(sc->bnx_dmatag, sc->tx_mbuf_map[i]);
+       }
 
        /* Free, unmap and destroy all RX buffer descriptor chain pages. */
        for (i = 0; i < RX_PAGES; i++ ) {
@@ -2414,6 +2413,19 @@ bnx_dma_alloc(struct bnx_softc *sc)
        DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
 
        /*
+        * Create DMA maps for the TX buffer mbufs.
+        */
+       for (i = 0; i < TOTAL_TX_BD; i++) {
+               if (bus_dmamap_create(sc->bnx_dmatag,
+                   MCLBYTES * BNX_MAX_SEGMENTS, USABLE_TX_BD,
+                   MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->tx_mbuf_map[i])) {
+                       printf(": Could not create Tx mbuf %d DMA map!\n", 1);
+                       rc = ENOMEM;
+                       goto bnx_dma_alloc_exit;
+               }
+       }
+
+       /*
         * Allocate DMA memory for the status block, map the memory into DMA
         * space, and fetch the physical address of the block.
         */
@@ -2589,15 +2601,6 @@ bnx_dma_alloc(struct bnx_softc *sc)
        }
 
        /*
-        * Create lists to hold TX mbufs.
-        */
-       TAILQ_INIT(&sc->tx_free_pkts);
-       TAILQ_INIT(&sc->tx_used_pkts);
-       sc->tx_pkt_count = 0;
-       mtx_init(&sc->tx_pkt_mtx, IPL_NET);
-       task_set(&sc->tx_alloc_task, bnx_alloc_pkts, sc);
-
-       /*
         * Allocate DMA memory for the Rx buffer descriptor chain,
         * and fetch the physical address of the block.
         */
@@ -3266,6 +3269,9 @@ bnx_stop(struct bnx_softc *sc)
 
        bnx_disable_intr(sc);
 
+       intr_barrier(sc->bnx_intrhand);
+       KASSERT((ifp->if_flags & IFF_RUNNING) == 0);
+
        /* Tell firmware that the driver is going away. */
        bnx_reset(sc, BNX_DRV_MSG_CODE_SUSPEND_NO_WOL);
 
@@ -3727,47 +3733,6 @@ bnx_get_buf(struct bnx_softc *sc, u_int1
        return (map->dm_nsegs);
 }
 
-void
-bnx_alloc_pkts(void *xsc)
-{
-       struct bnx_softc *sc = xsc;
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       struct bnx_pkt *pkt;
-       int i;
-       int s;
-
-       for (i = 0; i < 4; i++) { /* magic! */
-               pkt = pool_get(bnx_tx_pool, PR_WAITOK);
-               if (pkt == NULL)
-                       break;
-
-               if (bus_dmamap_create(sc->bnx_dmatag,
-                   MCLBYTES * BNX_MAX_SEGMENTS, USABLE_TX_BD,
-                   MCLBYTES, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
-                   &pkt->pkt_dmamap) != 0)
-                       goto put;
-
-               if (!ISSET(ifp->if_flags, IFF_UP))
-                       goto stopping;
-
-               mtx_enter(&sc->tx_pkt_mtx);
-               TAILQ_INSERT_TAIL(&sc->tx_free_pkts, pkt, pkt_entry);
-               sc->tx_pkt_count++;
-               mtx_leave(&sc->tx_pkt_mtx);
-       }
-
-       s = splnet();
-       if (!IFQ_IS_EMPTY(&ifp->if_snd))
-               bnx_start(ifp);
-       splx(s);
-
-       return;
-
-stopping:
-       bus_dmamap_destroy(sc->bnx_dmatag, pkt->pkt_dmamap);
-put:
-       pool_put(bnx_tx_pool, pkt);
-}
 
 /****************************************************************************/
 /* Initialize the TX context memory.                                        */
@@ -3825,9 +3790,6 @@ bnx_init_tx_chain(struct bnx_softc *sc)
 
        DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
 
-       /* Force an allocation of some dmamaps for tx up front */
-       bnx_alloc_pkts(sc);
-
        /* Set the initial TX producer/consumer indices. */
        sc->tx_prod = 0;
        sc->tx_cons = 0;
@@ -3884,39 +3846,26 @@ bnx_init_tx_chain(struct bnx_softc *sc)
 void
 bnx_free_tx_chain(struct bnx_softc *sc)
 {
-       struct bnx_pkt          *pkt;
        int                     i;
 
        DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
 
        /* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
-       mtx_enter(&sc->tx_pkt_mtx);
-       while ((pkt = TAILQ_FIRST(&sc->tx_used_pkts)) != NULL) {
-               TAILQ_REMOVE(&sc->tx_used_pkts, pkt, pkt_entry);
-               mtx_leave(&sc->tx_pkt_mtx);
-
-               bus_dmamap_sync(sc->bnx_dmatag, pkt->pkt_dmamap, 0,
-                   pkt->pkt_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
-               bus_dmamap_unload(sc->bnx_dmatag, pkt->pkt_dmamap);
-
-               m_freem(pkt->pkt_mbuf);
-
-               mtx_enter(&sc->tx_pkt_mtx);
-               TAILQ_INSERT_TAIL(&sc->tx_free_pkts, pkt, pkt_entry);
-       }
-
-       /* Destroy all the dmamaps we allocated for TX */
-       while ((pkt = TAILQ_FIRST(&sc->tx_free_pkts)) != NULL) {
-               TAILQ_REMOVE(&sc->tx_free_pkts, pkt, pkt_entry);
-               sc->tx_pkt_count--;
-               mtx_leave(&sc->tx_pkt_mtx);
-
-               bus_dmamap_destroy(sc->bnx_dmatag, pkt->pkt_dmamap);
-               pool_put(bnx_tx_pool, pkt);
-
-               mtx_enter(&sc->tx_pkt_mtx);
+       for (i = 0; i < TOTAL_TX_BD; i++) {
+               if (sc->tx_mbuf_ptr[i] != NULL) {
+                       if (sc->tx_mbuf_map[i] != NULL) {
+                               bus_dmamap_sync(sc->bnx_dmatag,
+                                   sc->tx_mbuf_map[i], 0,
+                                   sc->tx_mbuf_map[i]->dm_mapsize,
+                                   BUS_DMASYNC_POSTWRITE);
+                               bus_dmamap_unload(sc->bnx_dmatag,
+                                   sc->tx_mbuf_map[i]);
+                       }
+                       m_freem(sc->tx_mbuf_ptr[i]);
+                       sc->tx_mbuf_ptr[i] = NULL;
+                       DBRUNIF(1, sc->tx_mbuf_alloc--);
+               }
        }
-       mtx_leave(&sc->tx_pkt_mtx);
 
        /* Clear each TX chain page. */
        for (i = 0; i < TX_PAGES; i++)
@@ -4284,6 +4233,9 @@ bnx_rx_intr(struct bnx_softc *sc)
 
        DBRUNIF(1, sc->rx_interrupts++);
 
+       if (if_rxr_inuse(&sc->rx_ring) == 0)
+               return;
+
        /* Prepare the RX chain pages to be accessed by the host CPU. */
        for (i = 0; i < RX_PAGES; i++)
                bus_dmamap_sync(sc->bnx_dmatag,
@@ -4543,9 +4495,9 @@ bnx_tx_intr(struct bnx_softc *sc)
 {
        struct status_block     *sblk = sc->status_block;
        struct ifnet            *ifp = &sc->arpcom.ac_if;
-       struct bnx_pkt          *pkt;
        bus_dmamap_t            map;
        u_int16_t               hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
+       int                     freed, used;
 
        DBRUNIF(1, sc->tx_interrupts++);
 
@@ -4563,6 +4515,7 @@ bnx_tx_intr(struct bnx_softc *sc)
            BUS_SPACE_BARRIER_READ);
 
        /* Cycle through any completed TX chain page entries. */
+       freed = 0;
        while (sw_tx_cons != hw_tx_cons) {
 #ifdef BNX_DEBUG
                struct tx_bd *txbd = NULL;
@@ -4589,56 +4542,47 @@ bnx_tx_intr(struct bnx_softc *sc)
                DBRUN(BNX_INFO_SEND, printf("%s: ", __FUNCTION__);
                    bnx_dump_txbd(sc, sw_tx_chain_cons, txbd));
 
-               mtx_enter(&sc->tx_pkt_mtx);
-               pkt = TAILQ_FIRST(&sc->tx_used_pkts);
-               if (pkt != NULL && pkt->pkt_end_desc == sw_tx_chain_cons) {
-                       TAILQ_REMOVE(&sc->tx_used_pkts, pkt, pkt_entry);
-                       mtx_leave(&sc->tx_pkt_mtx);
-                       /*
-                        * Free the associated mbuf. Remember
-                        * that only the last tx_bd of a packet
-                        * has an mbuf pointer and DMA map.
-                        */
-                       map = pkt->pkt_dmamap;
+               map = sc->tx_mbuf_map[sw_tx_chain_cons];
+               if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) {
+                       /* Validate that this is the last tx_bd. */
+                       DBRUNIF((!(txbd->tx_bd_flags & TX_BD_FLAGS_END)),
+                           printf("%s: tx_bd END flag not set but "
+                           "txmbuf == NULL!\n");
+                           bnx_breakpoint(sc));
+
+                       DBRUN(BNX_INFO_SEND,
+                           printf("%s: Unloading map/freeing mbuf "
+                           "from tx_bd[0x%04X]\n",
+                           __FUNCTION__, sw_tx_chain_cons));
+
+                       /* Unmap the mbuf. */
                        bus_dmamap_sync(sc->bnx_dmatag, map, 0,
                            map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                        bus_dmamap_unload(sc->bnx_dmatag, map);
 
-                       m_freem(pkt->pkt_mbuf);
+                       /* Free the mbuf. */
+                       m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]);
+                       sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
 
                        ifp->if_opackets++;
-
-                       mtx_enter(&sc->tx_pkt_mtx);
-                       TAILQ_INSERT_TAIL(&sc->tx_free_pkts, pkt, pkt_entry);
                }
-               mtx_leave(&sc->tx_pkt_mtx);
-
-               sc->used_tx_bd--;
+               
+               freed++;
                sw_tx_cons = NEXT_TX_BD(sw_tx_cons);
-
-               /* Refresh hw_cons to see if there's new work. */
-               hw_tx_cons = sc->hw_tx_cons =
-                   sblk->status_tx_quick_consumer_index0;
-               if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) ==
-                   USABLE_TX_BD_PER_PAGE)
-                       hw_tx_cons++;
-
-               /* Prevent speculative reads from getting ahead of
-                * the status block.
-                */
-               bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0, 
-                   BUS_SPACE_BARRIER_READ);
        }
 
+       used = atomic_sub_int_nv(&sc->used_tx_bd, freed);
+
        /* Clear the TX timeout timer. */
-       ifp->if_timer = 0;
+       if (used == 0)
+               ifp->if_timer = 0;
 
        /* Clear the tx hardware queue full flag. */
-       if (sc->used_tx_bd < sc->max_tx_bd) {
+       if (used < sc->max_tx_bd) {
                DBRUNIF(ifq_is_oactive(&ifp->if_snd),
-                       printf("%s: Open TX chain! %d/%d (used/total)\n",
-                              sc->bnx_dev.dv_xname, sc->used_tx_bd,
-                              sc->max_tx_bd));
+                   printf("%s: Open TX chain! %d/%d (used/total)\n",
+                       sc->bnx_dev.dv_xname, used,
+                       sc->max_tx_bd));
                ifq_clr_oactive(&ifp->if_snd);
        }
 
@@ -4691,26 +4635,10 @@ bnx_init(void *xsc)
        struct bnx_softc        *sc = (struct bnx_softc *)xsc;
        struct ifnet            *ifp = &sc->arpcom.ac_if;
        u_int32_t               ether_mtu;
-       int                     txpl = 1;
        int                     s;
 
        DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
 
-       if (rw_enter(&bnx_tx_pool_lk, RW_WRITE | RW_INTR) != 0)
-               return;
-       if (bnx_tx_pool == NULL) {
-               bnx_tx_pool = malloc(sizeof(*bnx_tx_pool), M_DEVBUF, M_WAITOK);
-               if (bnx_tx_pool != NULL) {
-                       pool_init(bnx_tx_pool, sizeof(struct bnx_pkt),
-                           0, 0, 0, "bnxpkts", NULL);
-               } else
-                       txpl = 0;
-       }
-       rw_exit(&bnx_tx_pool_lk);
-
-       if (!txpl)
-               return;
-
        s = splnet();
 
        bnx_stop(sc);
@@ -4819,32 +4747,17 @@ bnx_mgmt_init_exit:
 /*   0 for success, positive value for failure.                             */
 /****************************************************************************/
 int
-bnx_tx_encap(struct bnx_softc *sc, struct mbuf *m)
+bnx_tx_encap(struct bnx_softc *sc, struct mbuf *m, int *used)
 {
-       struct bnx_pkt          *pkt;
        bus_dmamap_t            map;
        struct tx_bd            *txbd = NULL;
        u_int16_t               vlan_tag = 0, flags = 0;
-       u_int16_t               chain_prod, prod;
+       u_int16_t               chain_prod, chain_head, prod;
 #ifdef BNX_DEBUG
        u_int16_t               debug_prod;
 #endif
        u_int32_t               addr, prod_bseq;
-       int                     i, error, add;
-
-       mtx_enter(&sc->tx_pkt_mtx);
-       pkt = TAILQ_FIRST(&sc->tx_free_pkts);
-       if (pkt == NULL) {
-               add = (sc->tx_pkt_count <= TOTAL_TX_BD);
-               mtx_leave(&sc->tx_pkt_mtx);
-
-               if (add)
-                       task_add(systq, &sc->tx_alloc_task);
-
-               return (ENOMEM);
-       }
-       TAILQ_REMOVE(&sc->tx_free_pkts, pkt, pkt_entry);
-       mtx_leave(&sc->tx_pkt_mtx);
+       int                     i, error;
 
        /* Transfer any checksum offload flags to the bd. */
        if (m->m_pkthdr.csum_flags) {
@@ -4865,8 +4778,8 @@ bnx_tx_encap(struct bnx_softc *sc, struc
 
        /* Map the mbuf into DMAable memory. */
        prod = sc->tx_prod;
-       chain_prod = TX_CHAIN_IDX(prod);
-       map = pkt->pkt_dmamap;
+       chain_head = chain_prod = TX_CHAIN_IDX(prod);
+       map = sc->tx_mbuf_map[chain_head];
 
        /* Map the mbuf into our DMA address space. */
        error = bus_dmamap_load_mbuf(sc->bnx_dmatag, map, m,
@@ -4884,13 +4797,9 @@ bnx_tx_encap(struct bnx_softc *sc, struc
                /* FALLTHROUGH */
        default:
                sc->tx_dma_map_failures++;
-               goto maperr;
+               return (ENOBUFS);
        }
 
-       /* Make sure there's room in the chain */
-       if (map->dm_nsegs > (sc->max_tx_bd - sc->used_tx_bd))
-               goto nospace;
-
        /* prod points to an empty tx_bd at this point. */
        prod_bseq = sc->tx_prod_bseq;
 #ifdef BNX_DEBUG
@@ -4936,19 +4845,12 @@ bnx_tx_encap(struct bnx_softc *sc, struc
                "prod_bseq = 0x%08X\n",
                __FUNCTION__, prod, chain_prod, prod_bseq);
 
-       pkt->pkt_mbuf = m;
-       pkt->pkt_end_desc = chain_prod;
-       
-       mtx_enter(&sc->tx_pkt_mtx);
-       TAILQ_INSERT_TAIL(&sc->tx_used_pkts, pkt, pkt_entry);
-       mtx_leave(&sc->tx_pkt_mtx);
+       sc->tx_mbuf_ptr[chain_prod] = m;
+       sc->tx_mbuf_map[chain_head] = sc->tx_mbuf_map[chain_prod];
+       sc->tx_mbuf_map[chain_prod] = map;
 
-       sc->used_tx_bd += map->dm_nsegs;
+       *used += map->dm_nsegs;
 
-       /* Update some debug statistics counters */
-       DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
-           sc->tx_hi_watermark = sc->used_tx_bd);
-       DBRUNIF(sc->used_tx_bd == sc->max_tx_bd, sc->tx_full_count++);
        DBRUNIF(1, sc->tx_mbuf_alloc++);
 
        DBRUN(BNX_VERBOSE_SEND, bnx_dump_tx_mbuf_chain(sc, chain_prod, 
@@ -4962,15 +4864,6 @@ bnx_tx_encap(struct bnx_softc *sc, struc
        sc->tx_prod_bseq = prod_bseq;
 
        return (0);
-
-nospace:
-       bus_dmamap_unload(sc->bnx_dmatag, map);
-maperr:
-       mtx_enter(&sc->tx_pkt_mtx);
-       TAILQ_INSERT_TAIL(&sc->tx_free_pkts, pkt, pkt_entry);
-       mtx_leave(&sc->tx_pkt_mtx);
-
-       return (ENOMEM);
 }
 
 /****************************************************************************/
@@ -4984,7 +4877,7 @@ bnx_start(struct ifnet *ifp)
 {
        struct bnx_softc        *sc = ifp->if_softc;
        struct mbuf             *m_head = NULL;
-       int                     count = 0;
+       int                     used;
        u_int16_t               tx_prod, tx_chain_prod;
 
        /* If there's no link or the transmit queue is empty then just exit. */
@@ -5005,37 +4898,32 @@ bnx_start(struct ifnet *ifp)
        /*
         * Keep adding entries while there is space in the ring.
         */
-       while (sc->used_tx_bd < sc->max_tx_bd) {
-               /* Check for any frames to send. */
-               m_head = ifq_deq_begin(&ifp->if_snd);
-               if (m_head == NULL)
-                       break;
-
-               /*
-                * Pack the data into the transmit ring. If we
-                * don't have room, set the OACTIVE flag to wait
-                * for the NIC to drain the chain.
-                */
-               if (bnx_tx_encap(sc, m_head)) {
-                       ifq_deq_rollback(&ifp->if_snd, m_head);
-                       ifq_set_oactive(&ifp->if_snd);
+       used = 0;
+       while (1) {
+               if (sc->used_tx_bd + used + BNX_MAX_SEGMENTS >= sc->max_tx_bd) {
                        DBPRINT(sc, BNX_INFO_SEND, "TX chain is closed for "
                            "business! Total tx_bd used = %d\n",
-                           sc->used_tx_bd);
+                           sc->used_tx_bd + used);
+                       ifq_set_oactive(&ifp->if_snd);
                        break;
                }
 
-               ifq_deq_commit(&ifp->if_snd, m_head);
-               count++;
+               IFQ_DEQUEUE(&ifp->if_snd, m_head);
+               if (m_head == NULL)
+                       break;
+
+               if (bnx_tx_encap(sc, m_head, &used)) {
+                       m_freem(m_head);
+                       continue;
+               }
 
 #if NBPFILTER > 0
-               /* Send a copy of the frame to any BPF listeners. */
                if (ifp->if_bpf)
                        bpf_mtap_ether(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
 #endif
        }
 
-       if (count == 0) {
+       if (used == 0) {
                /* no packets were dequeued */
                DBPRINT(sc, BNX_VERBOSE_SEND,
                    "%s(): No packets were dequeued\n", __FUNCTION__);
@@ -5043,8 +4931,14 @@ bnx_start(struct ifnet *ifp)
        }
 
        /* Update the driver's counters. */
-       tx_chain_prod = TX_CHAIN_IDX(sc->tx_prod);
+       used = atomic_add_int_nv(&sc->used_tx_bd, used);
 
+       /* Update some debug statistics counters */
+       DBRUNIF((used > sc->tx_hi_watermark),
+           sc->tx_hi_watermark = used);
+       DBRUNIF(used == sc->max_tx_bd, sc->tx_full_count++);
+
+       tx_chain_prod = TX_CHAIN_IDX(sc->tx_prod);
        DBPRINT(sc, BNX_INFO_SEND, "%s(): End: tx_prod = 0x%04X, tx_chain_prod "
            "= 0x%04X, tx_prod_bseq = 0x%08X\n", __FUNCTION__, tx_prod,
            tx_chain_prod, sc->tx_prod_bseq);
@@ -5221,13 +5115,17 @@ bnx_intr(void *xsc)
                /* Was it a link change interrupt? */
                if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
                    (sc->status_block->status_attn_bits_ack &
-                   STATUS_ATTN_BITS_LINK_STATE))
+                   STATUS_ATTN_BITS_LINK_STATE)) {
+                       KERNEL_LOCK();
                        bnx_phy_intr(sc);
+                       KERNEL_UNLOCK();
+               }
 
                /* If any other attention is asserted then the chip is toast. */
                if (((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
                    (sc->status_block->status_attn_bits_ack & 
                    ~STATUS_ATTN_BITS_LINK_STATE))) {
+                       KERNEL_LOCK();
                        DBRUN(1, sc->unexpected_attentions++);
 
                        BNX_PRINTF(sc, "Fatal attention detected: 0x%08X\n",
@@ -5238,6 +5136,7 @@ bnx_intr(void *xsc)
                                bnx_breakpoint(sc));
 
                        bnx_init(sc);
+                       KERNEL_UNLOCK();
                        goto out;
                }
 
@@ -5258,8 +5157,12 @@ bnx_intr(void *xsc)
                sc->last_status_idx = status_idx;
 
                /* Start moving packets again */
-               if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
+               if (ifp->if_flags & IFF_RUNNING &&
+                   !IFQ_IS_EMPTY(&ifp->if_snd)) {
+                       KERNEL_LOCK();
                        bnx_start(ifp);
+                       KERNEL_UNLOCK();
+               }
        }
 
 out:
Index: if_bnxreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bnxreg.h,v
retrieving revision 1.48
diff -u -p -r1.48 if_bnxreg.h
--- if_bnxreg.h 24 Nov 2015 17:11:39 -0000      1.48
+++ if_bnxreg.h 2 Dec 2015 10:38:20 -0000
@@ -50,6 +50,7 @@
 #include <sys/pool.h>
 #include <sys/rwlock.h>
 #include <sys/task.h>
+#include <sys/atomic.h>
 
 #include <net/if.h>
 #include <net/if_media.h>
@@ -4915,11 +4916,8 @@ struct bnx_softc {
        int                     tx_mbuf_rseg;
 
        /* S/W maintained mbuf TX chain structure. */
-       struct mutex            tx_pkt_mtx;
-       u_int                   tx_pkt_count;
-       struct bnx_pkt_list     tx_free_pkts;
-       struct bnx_pkt_list     tx_used_pkts;
-       struct task             tx_alloc_task;
+       bus_dmamap_t            tx_mbuf_map[TOTAL_TX_BD];
+       struct mbuf             *tx_mbuf_ptr[TOTAL_TX_BD];
 
        /* S/W maintained mbuf RX chain structure. */
        bus_dmamap_t            rx_mbuf_map[TOTAL_RX_BD];
@@ -4928,7 +4926,7 @@ struct bnx_softc {
        /* Track the number of rx_bd and tx_bd's in use. */
        struct if_rxring        rx_ring;
        u_int16_t               max_rx_bd;
-       u_int16_t               used_tx_bd;
+       int                     used_tx_bd;
        u_int16_t               max_tx_bd;
 
        /* Provides access to hardware statistics through sysctl. */

Reply via email to