net/sfc/base: round number of queue buffers up
[dpdk.git] / drivers / net / sfc / base / efx_ev.c
index e0f6ba2..b986239 100644 (file)
@@ -1,31 +1,7 @@
-/*
- * Copyright (c) 2007-2016 Solarflare Communications Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
+/* SPDX-License-Identifier: BSD-3-Clause
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of the FreeBSD Project.
+ * Copyright (c) 2007-2018 Solarflare Communications Inc.
+ * All rights reserved.
  */
 
 #include "efx.h"
@@ -115,7 +91,7 @@ static const efx_ev_ops_t    __efx_ev_siena_ops = {
 };
 #endif /* EFSYS_OPT_SIENA */
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
 static const efx_ev_ops_t      __efx_ev_ef10_ops = {
        ef10_ev_init,                           /* eevo_init */
        ef10_ev_fini,                           /* eevo_fini */
@@ -128,7 +104,7 @@ static const efx_ev_ops_t   __efx_ev_ef10_ops = {
        ef10_ev_qstats_update,                  /* eevo_qstats_update */
 #endif
 };
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
+#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
 
 
        __checkReturn   efx_rc_t
@@ -165,6 +141,12 @@ efx_ev_init(
                break;
 #endif /* EFSYS_OPT_MEDFORD */
 
+#if EFSYS_OPT_MEDFORD2
+       case EFX_FAMILY_MEDFORD2:
+               eevop = &__efx_ev_ef10_ops;
+               break;
+#endif /* EFSYS_OPT_MEDFORD2 */
+
        default:
                EFSYS_ASSERT(0);
                rc = ENOTSUP;
@@ -191,6 +173,24 @@ fail1:
        return (rc);
 }
 
+       __checkReturn   size_t
+efx_evq_size(
+       __in    const efx_nic_t *enp,
+       __in    unsigned int ndescs)
+{
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+
+       return (ndescs * encp->enc_ev_desc_size);
+}
+
+       __checkReturn   unsigned int
+efx_evq_nbufs(
+       __in    const efx_nic_t *enp,
+       __in    unsigned int ndescs)
+{
+       return (EFX_DIV_ROUND_UP(efx_evq_size(enp, ndescs), EFX_BUF_SIZE));
+}
+
                void
 efx_ev_fini(
        __in    efx_nic_t *enp)
@@ -223,14 +223,15 @@ efx_ev_qcreate(
        __deref_out     efx_evq_t **eepp)
 {
        const efx_ev_ops_t *eevop = enp->en_eevop;
-       efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
        efx_evq_t *eep;
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
        efx_rc_t rc;
 
        EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
        EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV);
 
-       EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, encp->enc_evq_limit);
+       EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <,
+           enp->en_nic_cfg.enc_evq_limit);
 
        switch (flags & EFX_EVQ_FLAGS_NOTIFY_MASK) {
        case EFX_EVQ_FLAGS_NOTIFY_INTERRUPT:
@@ -246,11 +247,21 @@ efx_ev_qcreate(
                goto fail2;
        }
 
+       EFSYS_ASSERT(ISP2(encp->enc_evq_max_nevs));
+       EFSYS_ASSERT(ISP2(encp->enc_evq_min_nevs));
+
+       if (!ISP2(ndescs) ||
+           ndescs < encp->enc_evq_min_nevs ||
+           ndescs > encp->enc_evq_max_nevs) {
+               rc = EINVAL;
+               goto fail3;
+       }
+
        /* Allocate an EVQ object */
        EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep);
        if (eep == NULL) {
                rc = ENOMEM;
-               goto fail3;
+               goto fail4;
        }
 
        eep->ee_magic = EFX_EVQ_MAGIC;
@@ -273,16 +284,18 @@ efx_ev_qcreate(
 
        if ((rc = eevop->eevo_qcreate(enp, index, esmp, ndescs, id, us, flags,
            eep)) != 0)
-               goto fail4;
+               goto fail5;
 
        return (0);
 
-fail4:
-       EFSYS_PROBE(fail4);
+fail5:
+       EFSYS_PROBE(fail5);
 
        *eepp = NULL;
        enp->en_ev_qcount--;
        EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
+fail4:
+       EFSYS_PROBE(fail4);
 fail3:
        EFSYS_PROBE(fail3);
 fail2:
@@ -498,6 +511,14 @@ efx_ev_qpoll(
                        if (should_abort) {
                                /* Ignore subsequent events */
                                total = index + 1;
+
+                               /*
+                                * Poison batch to ensure the outer
+                                * loop is broken out of.
+                                */
+                               EFSYS_ASSERT(batch <= EFX_EV_BATCH);
+                               batch += (EFX_EV_BATCH << 1);
+                               EFSYS_ASSERT(total != batch);
                                break;
                        }
                }
@@ -1295,32 +1316,25 @@ siena_ev_qcreate(
 
        _NOTE(ARGUNUSED(esmp))
 
-       EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MAXNEVS));
-       EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MINNEVS));
-
-       if (!ISP2(ndescs) ||
-           (ndescs < EFX_EVQ_MINNEVS) || (ndescs > EFX_EVQ_MAXNEVS)) {
-               rc = EINVAL;
-               goto fail1;
-       }
        if (index >= encp->enc_evq_limit) {
                rc = EINVAL;
-               goto fail2;
+               goto fail1;
        }
 #if EFSYS_OPT_RX_SCALE
        if (enp->en_intr.ei_type == EFX_INTR_LINE &&
            index >= EFX_MAXRSS_LEGACY) {
                rc = EINVAL;
-               goto fail3;
+               goto fail2;
        }
 #endif
-       for (size = 0; (1 << size) <= (EFX_EVQ_MAXNEVS / EFX_EVQ_MINNEVS);
+       for (size = 0;
+           (1U << size) <= encp->enc_evq_max_nevs / encp->enc_evq_min_nevs;
            size++)
-               if ((1 << size) == (int)(ndescs / EFX_EVQ_MINNEVS))
+               if ((1U << size) == (uint32_t)ndescs / encp->enc_evq_min_nevs)
                        break;
        if (id + (1 << size) >= encp->enc_buftbl_limit) {
                rc = EINVAL;
-               goto fail4;
+               goto fail3;
        }
 
        /* Set up the handler table */
@@ -1352,14 +1366,12 @@ siena_ev_qcreate(
 
        return (0);
 
-fail4:
-       EFSYS_PROBE(fail4);
-#if EFSYS_OPT_RX_SCALE
 fail3:
        EFSYS_PROBE(fail3);
-#endif
+#if EFSYS_OPT_RX_SCALE
 fail2:
        EFSYS_PROBE(fail2);
+#endif
 fail1:
        EFSYS_PROBE1(fail1, efx_rc_t, rc);