This is a port of the em(4) IPL_MPSAFE changes made by kettenis@ to ix(4).
Seems to work for me but don't expect any miracles.

Please test
-- 
:wq Claudio

Index: if_ix.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.124
diff -u -p -r1.124 if_ix.c
--- if_ix.c     2 Sep 2015 16:08:49 -0000       1.124
+++ if_ix.c     8 Sep 2015 16:36:21 -0000
@@ -210,6 +210,8 @@ ixgbe_attach(struct device *parent, stru
        sc->osdep.os_sc = sc;
        sc->osdep.os_pa = *pa;
 
+       mtx_init(&sc->rx_mtx, IPL_NET);
+
        /* Set up the timer callout */
        timeout_set(&sc->timer, ixgbe_local_timer, sc);
        timeout_set(&sc->rx_refill, ixgbe_rxrefill, sc);
@@ -866,10 +868,29 @@ ixgbe_intr(void *arg)
 
        reg_eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR);
        if (reg_eicr == 0) {
+               KERNEL_LOCK(); /* XXX SHOULD NOT BE NEEDED */
                ixgbe_enable_intr(sc);
+               KERNEL_UNLOCK();
                return (0);
        }
 
+       if (ifp->if_flags & IFF_RUNNING) {
+               ixgbe_rxeof(que);
+               ixgbe_txeof(txr);
+               refill = 1;
+       }
+
+       KERNEL_LOCK();
+
+       if (refill) {
+               if (ixgbe_rxfill(que->rxr)) {
+                       /* Advance the Rx Queue "Tail Pointer" */
+                       IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me),
+                           que->rxr->last_desc_filled);
+               } else
+                       timeout_add(&sc->rx_refill, 1);
+       }
+
        /* Link status change */
        if (reg_eicr & IXGBE_EICR_LSC)
                ixgbe_update_link_status(sc);
@@ -903,27 +924,14 @@ ixgbe_intr(void *arg)
                IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
        }
 
-       if (ifp->if_flags & IFF_RUNNING) {
-               ixgbe_rxeof(que);
-               ixgbe_txeof(txr);
-               refill = 1;
-       }
-
-       if (refill) {
-               if (ixgbe_rxfill(que->rxr)) {
-                       /* Advance the Rx Queue "Tail Pointer" */
-                       IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me),
-                           que->rxr->last_desc_filled);
-               } else
-                       timeout_add(&sc->rx_refill, 1);
-       }
-
        if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
                ixgbe_start(ifp);
 
        for (i = 0; i < sc->num_queues; i++, que++)
                ixgbe_enable_queue(sc, que->msix);
 
+       KERNEL_UNLOCK();
+
        return (1);
 }
 
@@ -1449,7 +1457,7 @@ ixgbe_allocate_legacy(struct ix_softc *s
 #endif
 
        intrstr = pci_intr_string(pc, ih);
-       sc->tag = pci_intr_establish(pc, ih, IPL_NET,
+       sc->tag = pci_intr_establish(pc, ih, IPL_NET | IPL_MPSAFE,
            ixgbe_intr, sc, sc->dev.dv_xname);
        if (sc->tag == NULL) {
                printf(": couldn't establish interrupt");
@@ -2338,14 +2346,18 @@ ixgbe_txeof(struct tx_ring *txr)
                return FALSE;
        }
 
+       KERNEL_LOCK();
+
        processed = 0;
        first = txr->next_to_clean;
        tx_buffer = &txr->tx_buffers[first];
        /* For cleanup we just use legacy struct */
        tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];
        last = tx_buffer->eop_index;
-       if (last == -1)
+       if (last == -1) {
+               KERNEL_UNLOCK();
                return FALSE;
+       }
        eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];
 
        /*
@@ -2422,6 +2434,7 @@ ixgbe_txeof(struct tx_ring *txr)
                if (txr->tx_avail == sc->num_tx_desc) {
                        ifp->if_timer = 0;
                        txr->watchdog_timer = 0;
+                       KERNEL_UNLOCK();
                        return FALSE;
                }
                /* Some were cleaned, so reset timer */
@@ -2431,6 +2444,8 @@ ixgbe_txeof(struct tx_ring *txr)
                }
        }
 
+       KERNEL_UNLOCK();
+
        return TRUE;
 }
 
@@ -2580,6 +2595,8 @@ ixgbe_rxfill(struct rx_ring *rxr)
        u_int            slots;
        int              i;
 
+       mtx_enter(&sc->rx_mtx);
+
        i = rxr->last_desc_filled;
        for (slots = if_rxr_get(&rxr->rx_ring, sc->num_rx_desc);
            slots > 0; slots--) {
@@ -2595,6 +2612,8 @@ ixgbe_rxfill(struct rx_ring *rxr)
 
        if_rxr_put(&rxr->rx_ring, slots);
 
+       mtx_leave(&sc->rx_mtx);
+
        return (post);
 }
 
@@ -2762,8 +2781,10 @@ ixgbe_free_receive_structures(struct ix_
        struct rx_ring *rxr = sc->rx_rings;
        int             i;
 
+       mtx_enter(&sc->rx_mtx);
        for (i = 0; i < sc->num_queues; i++, rxr++)
                ixgbe_free_receive_buffers(rxr);
+       mtx_leave(&sc->rx_mtx);
 }
 
 /*********************************************************************
@@ -2814,6 +2835,7 @@ ixgbe_rxeof(struct ix_queue *que)
        struct rx_ring          *rxr = que->rxr;
        struct ifnet            *ifp = &sc->arpcom.ac_if;
        struct mbuf_list         ml = MBUF_LIST_INITIALIZER();
+       struct mbuf_list         free_ml = MBUF_LIST_INITIALIZER();
        struct mbuf             *mp, *sendmp;
        uint8_t                  eop = 0;
        uint16_t                 len, vtag;
@@ -2826,6 +2848,7 @@ ixgbe_rxeof(struct ix_queue *que)
        if (!ISSET(ifp->if_flags, IFF_RUNNING))
                return FALSE;
 
+       mtx_enter(&sc->rx_mtx);
        i = rxr->next_to_check;
        while (if_rxr_inuse(&rxr->rx_ring) > 0) {
                bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
@@ -2860,11 +2883,11 @@ ixgbe_rxeof(struct ix_queue *que)
                        sc->dropped_pkts++;
 
                        if (rxbuf->fmp) {
-                               m_freem(rxbuf->fmp);
+                               ml_enqueue(&free_ml, rxbuf->fmp);
                                rxbuf->fmp = NULL;
                        }
 
-                       m_freem(mp);
+                       ml_enqueue(&free_ml, mp);
                        rxbuf->buf = NULL;
                        goto next_desc;
                }
@@ -2942,6 +2965,10 @@ next_desc:
                        i = 0;
        }
        rxr->next_to_check = i;
+       mtx_leave(&sc->rx_mtx);
+
+       while ((mp = ml_dequeue(&free_ml)))
+               m_freem(mp);
 
        if_input(ifp, &ml);
 
Index: if_ix.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.h,v
retrieving revision 1.27
diff -u -p -r1.27 if_ix.h
--- if_ix.h     12 Nov 2014 16:06:47 -0000      1.27
+++ if_ix.h     31 Aug 2015 20:09:32 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.h,v 1.27 2014/11/12 16:06:47 mikeb Exp $        */
+/*     $OpenBSD: if_ix.h,v 1.26 2014/11/10 15:58:32 mikeb Exp $        */
 
 /******************************************************************************
 
@@ -277,6 +277,7 @@ struct ix_softc {
         * Receive rings:
         *      Allocated at run time, an array of rings.
         */
+       struct mutex            rx_mtx;
        struct rx_ring          *rx_rings;
        uint64_t                que_mask;
        int                     num_rx_desc;

Reply via email to