EFSYS_OPT_EV_PREFECT allows to enable event prefetching
when event queue is polled.

>From Solarflare Communications Inc.

Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
---
 drivers/net/sfc/efx/base/efx.h       |  9 +++++++++
 drivers/net/sfc/efx/base/efx_check.h |  7 +++++++
 drivers/net/sfc/efx/base/efx_ev.c    | 38 ++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/drivers/net/sfc/efx/base/efx.h b/drivers/net/sfc/efx/base/efx.h
index c06c9b6..24b7c8d 100644
--- a/drivers/net/sfc/efx/base/efx.h
+++ b/drivers/net/sfc/efx/base/efx.h
@@ -1317,6 +1317,15 @@ efx_ev_qpending(
        __in            efx_evq_t *eep,
        __in            unsigned int count);

+#if EFSYS_OPT_EV_PREFETCH
+
+extern                 void
+efx_ev_qprefetch(
+       __in            efx_evq_t *eep,
+       __in            unsigned int count);
+
+#endif /* EFSYS_OPT_EV_PREFETCH */
+
 extern                 void
 efx_ev_qpoll(
        __in            efx_evq_t *eep,
diff --git a/drivers/net/sfc/efx/base/efx_check.h 
b/drivers/net/sfc/efx/base/efx_check.h
index 5956052..df46410 100644
--- a/drivers/net/sfc/efx/base/efx_check.h
+++ b/drivers/net/sfc/efx/base/efx_check.h
@@ -66,6 +66,13 @@
 # endif
 #endif /* EFSYS_OPT_DIAG */

+#if EFSYS_OPT_EV_PREFETCH
+/* Support optimized EVQ data access */
+# if !(EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
+#  error "EV_PREFETCH requires SIENA or HUNTINGTON or MEDFORD"
+# endif
+#endif /* EFSYS_OPT_EV_PREFETCH */
+
 #ifdef EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE
 # error "FALCON_NIC_CFG_OVERRIDE is obsolete and is not supported."
 #endif
diff --git a/drivers/net/sfc/efx/base/efx_ev.c 
b/drivers/net/sfc/efx/base/efx_ev.c
index 74d146e..c172a06 100644
--- a/drivers/net/sfc/efx/base/efx_ev.c
+++ b/drivers/net/sfc/efx/base/efx_ev.c
@@ -351,6 +351,23 @@ efx_ev_qpending(
        return (EFX_EV_PRESENT(qword));
 }

+#if EFSYS_OPT_EV_PREFETCH
+
+                       void
+efx_ev_qprefetch(
+       __in            efx_evq_t *eep,
+       __in            unsigned int count)
+{
+       unsigned int offset;
+
+       EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+       offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
+       EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+}
+
+#endif /* EFSYS_OPT_EV_PREFETCH */
+
 #define        EFX_EV_BATCH    8

                        void
@@ -403,11 +420,32 @@ efx_ev_qpoll(
                        offset += sizeof (efx_qword_t);
                }

+#if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1)
+               /*
+                * Prefetch the next batch when we get within PREFETCH_PERIOD
+                * of a completed batch. If the batch is smaller, then prefetch
+                * immediately.
+                */
+               if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD)
+                       EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+#endif /* EFSYS_OPT_EV_PREFETCH */
+
                /* Process the batch of events */
                for (index = 0; index < total; ++index) {
                        boolean_t should_abort;
                        uint32_t code;

+#if EFSYS_OPT_EV_PREFETCH
+                       /* Prefetch if we've now reached the batch period */
+                       if (total == batch &&
+                           index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) {
+                               offset = (count + batch) & eep->ee_mask;
+                               offset *= sizeof (efx_qword_t);
+
+                               EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+                       }
+#endif /* EFSYS_OPT_EV_PREFETCH */
+
                        EFX_EV_QSTAT_INCR(eep, EV_ALL);

                        code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE);
-- 
2.5.5

Reply via email to