net/sfc: periodic management EVQ polling using alarm
authorAndrew Rybchenko <arybchenko@solarflare.com>
Tue, 29 Nov 2016 16:19:12 +0000 (16:19 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:26 +0000 (19:39 +0100)
Timers cannot be used to implement periodic polling, since it implies
requirement on application to process timers in the main loop.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@solarflare.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
drivers/net/sfc/sfc_ev.c

index a6a1ee2..179c4f8 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <rte_debug.h>
 #include <rte_cycles.h>
+#include <rte_alarm.h>
 
 #include "efx.h"
 
@@ -45,6 +46,9 @@
 /* Event queue init approx timeout */
 #define SFC_EVQ_INIT_TIMEOUT_US                (2 * US_PER_S)
 
+/* Management event queue polling period in microseconds */
+#define SFC_MGMT_EV_QPOLL_PERIOD_US    (US_PER_S)
+
 
 static boolean_t
 sfc_ev_initialized(void *arg)
@@ -328,6 +332,34 @@ sfc_ev_qstop(struct sfc_adapter *sa, unsigned int sw_index)
        efx_ev_qdestroy(evq->common);
 }
 
+static void
+sfc_ev_mgmt_periodic_qpoll(void *arg)
+{
+       struct sfc_adapter *sa = arg;
+       int rc;
+
+       sfc_ev_mgmt_qpoll(sa);
+
+       rc = rte_eal_alarm_set(SFC_MGMT_EV_QPOLL_PERIOD_US,
+                              sfc_ev_mgmt_periodic_qpoll, sa);
+       if (rc != 0)
+               sfc_panic(sa,
+                         "cannot rearm management EVQ polling alarm (rc=%d)",
+                         rc);
+}
+
+static void
+sfc_ev_mgmt_periodic_qpoll_start(struct sfc_adapter *sa)
+{
+       sfc_ev_mgmt_periodic_qpoll(sa);
+}
+
+static void
+sfc_ev_mgmt_periodic_qpoll_stop(struct sfc_adapter *sa)
+{
+       rte_eal_alarm_cancel(sfc_ev_mgmt_periodic_qpoll, sa);
+}
+
 int
 sfc_ev_start(struct sfc_adapter *sa)
 {
@@ -348,6 +380,14 @@ sfc_ev_start(struct sfc_adapter *sa)
 
        rte_spinlock_unlock(&sa->mgmt_evq_lock);
 
+       /*
+        * Start management EVQ polling. If interrupts are disabled
+        * (not used), it is required to process link status change
+        * and other device level events to avoid unrecoverable
+        * error because the event queue overflow.
+        */
+       sfc_ev_mgmt_periodic_qpoll_start(sa);
+
        /*
         * Rx/Tx event queues are started/stopped when corresponding
         * Rx/Tx queue is started/stopped.
@@ -371,6 +411,8 @@ sfc_ev_stop(struct sfc_adapter *sa)
 
        sfc_log_init(sa, "entry");
 
+       sfc_ev_mgmt_periodic_qpoll_stop(sa);
+
        /* Make sure that all event queues are stopped */
        sw_index = sa->evq_count;
        while (sw_index-- > 0) {