Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci workqueue and callout fixes



details:   https://anonhg.NetBSD.org/src/rev/5672a851cd7e
branches:  trunk
changeset: 446313:5672a851cd7e
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Nov 30 11:37:11 2018 +0000

description:
workqueue and callout fixes

diffstat:

 sys/dev/pci/if_ena.c |  41 ++++++++++++++++++++++++++---------------
 1 files changed, 26 insertions(+), 15 deletions(-)

diffs (122 lines):

diff -r 5713ecc31064 -r 5672a851cd7e sys/dev/pci/if_ena.c
--- a/sys/dev/pci/if_ena.c      Fri Nov 30 10:18:37 2018 +0000
+++ b/sys/dev/pci/if_ena.c      Fri Nov 30 11:37:11 2018 +0000
@@ -31,7 +31,7 @@
 #if 0
 __FBSDID("$FreeBSD: head/sys/dev/ena/ena.c 333456 2018-05-10 09:37:54Z mw $");
 #endif
-__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.9 2018/11/28 21:31:32 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.10 2018/11/30 11:37:11 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -641,9 +641,9 @@
        }
 
        /* Allocate workqueues */
-       int rc = workqueue_create(&tx_ring->enqueue_tq, "ena_tx_enque",
-           ena_deferred_mq_start, tx_ring, 0, IPL_NET, 0);
-       if (unlikely(rc == 0)) {
+       int rc = workqueue_create(&tx_ring->enqueue_tq, "ena_tx_enq",
+           ena_deferred_mq_start, tx_ring, 0, IPL_NET, WQ_PERCPU | WQ_MPSAFE);
+       if (unlikely(rc != 0)) {
                ena_trace(ENA_ALERT,
                    "Unable to create workqueue for enqueue task\n");
                i = tx_ring->ring_size;
@@ -848,8 +848,8 @@
 #endif
 
        /* Allocate workqueues */
-       int rc = workqueue_create(&rx_ring->cmpl_tq, "ena RX completion",
-           ena_deferred_rx_cleanup, rx_ring, 0, IPL_NET, 0);
+       int rc = workqueue_create(&rx_ring->cmpl_tq, "ena_rx_comp",
+           ena_deferred_rx_cleanup, rx_ring, 0, IPL_NET, WQ_PERCPU | WQ_MPSAFE);
        if (unlikely(rc != 0)) {
                ena_trace(ENA_ALERT,
                    "Unable to create workqueue for RX completion task\n");
@@ -1422,7 +1422,8 @@
                ena_com_update_dev_comp_head(io_cq);
        }
 
-       workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task, NULL);
+       if (atomic_cas_uint(&tx_ring->task_pending, 0, 1) == 0)
+               workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task, NULL);
 
        return (work_done);
 }
@@ -1638,6 +1639,8 @@
        struct ena_ring *rx_ring = arg;
        int budget = CLEAN_BUDGET;
 
+       atomic_swap_uint(&rx_ring->task_pending, 0);
+
        ENA_RING_MTX_LOCK(rx_ring);
        /*
         * If deferred task was executed, perform cleanup of all awaiting
@@ -2913,6 +2916,8 @@
        struct ena_ring *tx_ring = (struct ena_ring *)arg;
        struct ifnet *ifp = tx_ring->adapter->ifp;
 
+       atomic_swap_uint(&tx_ring->task_pending, 0);
+
        while (!drbr_empty(ifp, tx_ring->br) &&
            (if_getdrvflags(ifp) & IFF_RUNNING) != 0) {
                ENA_RING_MTX_LOCK(tx_ring);
@@ -2962,8 +2967,9 @@
        is_drbr_empty = drbr_empty(ifp, tx_ring->br);
        ret = drbr_enqueue(ifp, tx_ring->br, m);
        if (unlikely(ret != 0)) {
-               workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task,
-                   curcpu());
+               if (atomic_cas_uint(&tx_ring->task_pending, 0, 1) == 0)
+                       workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task,
+                           curcpu());
                return (ret);
        }
 
@@ -2971,8 +2977,9 @@
                ena_start_xmit(tx_ring);
                ENA_RING_MTX_UNLOCK(tx_ring);
        } else {
-               workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task,
-                   curcpu());
+               if (atomic_cas_uint(&tx_ring->task_pending, 0, 1) == 0)
+                       workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task,
+                           curcpu());
        }
 
        return (0);
@@ -3494,8 +3501,9 @@
                                device_printf(adapter->pdev,
                                    "trigger refill for ring %d\n", i);
 
-                               workqueue_enqueue(rx_ring->cmpl_tq,
-                                   &rx_ring->cmpl_task, curcpu());
+                               if (atomic_cas_uint(&rx_ring->task_pending, 0, 1) == 0)
+                                       workqueue_enqueue(rx_ring->cmpl_tq,
+                                           &rx_ring->cmpl_task, curcpu());
                                rx_ring->empty_rx_queue = 0;
                        }
                } else {
@@ -3765,9 +3773,11 @@
                goto err_ifp_free;
        }
 
+       callout_init(&adapter->timer_service, CALLOUT_MPSAFE);
+
        /* Initialize reset task queue */
-       rc = workqueue_create(&adapter->reset_tq, "ena_reset_enqueue",
-           ena_reset_task, adapter, 0, IPL_NET, 0);
+       rc = workqueue_create(&adapter->reset_tq, "ena_reset_enq",
+           ena_reset_task, adapter, 0, IPL_NET, WQ_PERCPU | WQ_MPSAFE);
        if (unlikely(rc != 0)) {
                ena_trace(ENA_ALERT,
                    "Unable to create workqueue for reset task\n");
@@ -3831,6 +3841,7 @@
 
        /* Free reset task and callout */
        callout_halt(&adapter->timer_service, &adapter->global_mtx);
+       callout_destroy(&adapter->timer_service);
        workqueue_wait(adapter->reset_tq, &adapter->reset_task);
        workqueue_destroy(adapter->reset_tq);
        adapter->reset_tq = NULL;



Home | Main Index | Thread Index | Old Index