LCOV - code coverage report
Current view: top level - drivers/common/sfc_efx/base - rhead_ev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 93 0.0 %
Date: 2024-02-14 00:53:57 Functions: 0 12 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 48 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *
       3                 :            :  * Copyright(c) 2019-2021 Xilinx, Inc.
       4                 :            :  * Copyright(c) 2018-2019 Solarflare Communications Inc.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "efx.h"
       8                 :            : #include "efx_impl.h"
       9                 :            : 
      10                 :            : #if EFSYS_OPT_RIVERHEAD
      11                 :            : 
      12                 :            : /*
      13                 :            :  * Non-interrupting event queue requires interrupting event queue to
      14                 :            :  * refer to for wake-up events even if wake ups are never used.
      15                 :            :  * It could be even non-allocated event queue.
      16                 :            :  */
      17                 :            : #define EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX (0)
      18                 :            : 
      19                 :            : static                  boolean_t
      20                 :            : rhead_ev_dispatch(
      21                 :            :         __in            efx_evq_t *eep,
      22                 :            :         __in            efx_qword_t *eventp,
      23                 :            :         __in            const efx_ev_callbacks_t *eecp,
      24                 :            :         __in_opt        void *arg);
      25                 :            : 
      26                 :            : static  __checkReturn   boolean_t
      27                 :            : rhead_ev_rx_packets(
      28                 :            :         __in            efx_evq_t *eep,
      29                 :            :         __in            efx_qword_t *eqp,
      30                 :            :         __in            const efx_ev_callbacks_t *eecp,
      31                 :            :         __in_opt        void *arg);
      32                 :            : 
      33                 :            : static  __checkReturn   boolean_t
      34                 :            : rhead_ev_tx_completion(
      35                 :            :         __in            efx_evq_t *eep,
      36                 :            :         __in            efx_qword_t *eqp,
      37                 :            :         __in            const efx_ev_callbacks_t *eecp,
      38                 :            :         __in_opt        void *arg);
      39                 :            : 
      40                 :            : static  __checkReturn   boolean_t
      41                 :            : rhead_ev_mcdi(
      42                 :            :         __in            efx_evq_t *eep,
      43                 :            :         __in            efx_qword_t *eqp,
      44                 :            :         __in            const efx_ev_callbacks_t *eecp,
      45                 :            :         __in_opt        void *arg);
      46                 :            : 
      47                 :            : #if EFSYS_OPT_EV_EXTENDED_WIDTH
      48                 :            : static                  boolean_t
      49                 :            : rhead_ev_ew_dispatch(
      50                 :            :         __in            efx_evq_t *eep,
      51                 :            :         __in            efx_xword_t *eventp,
      52                 :            :         __in            const efx_ev_callbacks_t *eecp,
      53                 :            :         __in_opt        void *arg);
      54                 :            : 
      55                 :            : static                  void
      56                 :            : rhead_ev_ew_qpoll(
      57                 :            :         __in            efx_evq_t *eep,
      58                 :            :         __inout         unsigned int *countp,
      59                 :            :         __in            const efx_ev_callbacks_t *eecp,
      60                 :            :         __in_opt        void *arg);
      61                 :            : 
      62                 :            : #if EFSYS_OPT_DESC_PROXY
      63                 :            : static                  boolean_t
      64                 :            : rhead_ev_ew_txq_desc(
      65                 :            :         __in            efx_evq_t *eep,
      66                 :            :         __in            efx_xword_t *eventp,
      67                 :            :         __in            const efx_ev_callbacks_t *eecp,
      68                 :            :         __in_opt        void *arg);
      69                 :            : 
      70                 :            : static                  boolean_t
      71                 :            : rhead_ev_ew_virtq_desc(
      72                 :            :         __in            efx_evq_t *eep,
      73                 :            :         __in            efx_xword_t *eventp,
      74                 :            :         __in            const efx_ev_callbacks_t *eecp,
      75                 :            :         __in_opt        void *arg);
      76                 :            : #endif /* EFSYS_OPT_DESC_PROXY */
      77                 :            : #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
      78                 :            : 
      79                 :            : 
      80                 :            :         __checkReturn   efx_rc_t
      81                 :          0 : rhead_ev_init(
      82                 :            :         __in            efx_nic_t *enp)
      83                 :            : {
      84                 :            :         _NOTE(ARGUNUSED(enp))
      85                 :            : 
      86                 :          0 :         return (0);
      87                 :            : }
      88                 :            : 
      89                 :            :                         void
      90                 :          0 : rhead_ev_fini(
      91                 :            :         __in            efx_nic_t *enp)
      92                 :            : {
      93                 :            :         _NOTE(ARGUNUSED(enp))
      94                 :          0 : }
      95                 :            : 
      96                 :            :         __checkReturn   efx_rc_t
      97                 :          0 : rhead_ev_qcreate(
      98                 :            :         __in            efx_nic_t *enp,
      99                 :            :         __in            unsigned int index,
     100                 :            :         __in            efsys_mem_t *esmp,
     101                 :            :         __in            size_t ndescs,
     102                 :            :         __in            uint32_t id,
     103                 :            :         __in            uint32_t us,
     104                 :            :         __in            uint32_t flags,
     105                 :            :         __in            uint32_t irq,
     106                 :            :         __in            efx_evq_t *eep)
     107                 :            : {
     108                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
     109                 :            :         size_t desc_size;
     110                 :            :         uint32_t target_evq = 0;
     111                 :            :         efx_rc_t rc;
     112                 :            : 
     113                 :            :         _NOTE(ARGUNUSED(id))    /* buftbl id managed by MC */
     114                 :            : 
     115                 :          0 :         desc_size = encp->enc_ev_desc_size;
     116                 :            : #if EFSYS_OPT_EV_EXTENDED_WIDTH
     117                 :            :         if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH)
     118                 :            :                 desc_size = encp->enc_ev_ew_desc_size;
     119                 :            : #endif
     120         [ #  # ]:          0 :         EFSYS_ASSERT(desc_size != 0);
     121                 :            : 
     122         [ #  # ]:          0 :         if (EFSYS_MEM_SIZE(esmp) < (ndescs * desc_size)) {
     123                 :            :                 /* Buffer too small for event queue descriptors */
     124                 :            :                 rc = EINVAL;
     125                 :          0 :                 goto fail1;
     126                 :            :         }
     127                 :            : 
     128                 :            :         /* Set up the handler table */
     129                 :          0 :         eep->ee_rx   = rhead_ev_rx_packets;
     130                 :          0 :         eep->ee_tx   = rhead_ev_tx_completion;
     131                 :          0 :         eep->ee_driver       = NULL; /* FIXME */
     132                 :          0 :         eep->ee_drv_gen      = NULL; /* FIXME */
     133                 :          0 :         eep->ee_mcdi = rhead_ev_mcdi;
     134                 :            : 
     135                 :            : #if EFSYS_OPT_DESC_PROXY
     136                 :            :         eep->ee_ew_txq_desc  = rhead_ev_ew_txq_desc;
     137                 :            :         eep->ee_ew_virtq_desc        = rhead_ev_ew_virtq_desc;
     138                 :            : #endif /* EFSYS_OPT_DESC_PROXY */
     139                 :            : 
     140                 :            :         /* Set up the event queue */
     141                 :            :         /* INIT_EVQ expects function-relative vector number */
     142         [ #  # ]:          0 :         if ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
     143                 :            :             EFX_EVQ_FLAGS_NOTIFY_INTERRUPT) {
     144                 :            :                 /* IRQ number is specified by caller */
     145         [ #  # ]:          0 :         } else if (index == EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX) {
     146                 :            :                 /* Use the first interrupt for always interrupting EvQ */
     147                 :            :                 irq = 0;
     148                 :          0 :                 flags = (flags & ~EFX_EVQ_FLAGS_NOTIFY_MASK) |
     149                 :            :                     EFX_EVQ_FLAGS_NOTIFY_INTERRUPT;
     150                 :            :         } else {
     151                 :            :                 target_evq = EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX;
     152                 :            :         }
     153                 :            : 
     154                 :            :         /*
     155                 :            :          * Interrupts may be raised for events immediately after the queue is
     156                 :            :          * created. See bug58606.
     157                 :            :          */
     158                 :          0 :         rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, target_evq, us,
     159                 :            :             flags, B_FALSE);
     160         [ #  # ]:          0 :         if (rc != 0)
     161                 :          0 :                 goto fail2;
     162                 :            : 
     163                 :            :         return (0);
     164                 :            : 
     165                 :            : fail2:
     166                 :            :         EFSYS_PROBE(fail2);
     167                 :            : fail1:
     168                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     169                 :            : 
     170                 :            :         return (rc);
     171                 :            : }
     172                 :            : 
     173                 :            :                         void
     174                 :          0 : rhead_ev_qdestroy(
     175                 :            :         __in            efx_evq_t *eep)
     176                 :            : {
     177                 :          0 :         efx_nic_t *enp = eep->ee_enp;
     178                 :            : 
     179         [ #  # ]:          0 :         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_RIVERHEAD);
     180                 :            : 
     181                 :          0 :         (void) efx_mcdi_fini_evq(enp, eep->ee_index);
     182                 :          0 : }
     183                 :            : 
     184                 :            :         __checkReturn   efx_rc_t
     185                 :          0 : rhead_ev_qprime(
     186                 :            :         __in            efx_evq_t *eep,
     187                 :            :         __in            unsigned int count)
     188                 :            : {
     189                 :          0 :         efx_nic_t *enp = eep->ee_enp;
     190                 :            :         uint32_t rptr;
     191                 :            :         efx_dword_t dword;
     192                 :            : 
     193                 :          0 :         rptr = count & eep->ee_mask;
     194                 :            : 
     195                 :          0 :         EFX_POPULATE_DWORD_2(dword, ERF_GZ_EVQ_ID, eep->ee_index,
     196                 :            :             ERF_GZ_IDX, rptr);
     197                 :            :         /* EVQ_INT_PRIME lives function control window only on Riverhead */
     198   [ #  #  #  #  :          0 :         EFX_BAR_FCW_WRITED(enp, ER_GZ_EVQ_INT_PRIME, &dword);
                   #  # ]
     199                 :            : 
     200                 :          0 :         return (0);
     201                 :            : }
     202                 :            : 
     203                 :            :                         void
     204                 :          0 : rhead_ev_qpost(
     205                 :            :         __in    efx_evq_t *eep,
     206                 :            :         __in    uint16_t data)
     207                 :            : {
     208                 :            :         _NOTE(ARGUNUSED(eep, data))
     209                 :            : 
     210                 :            :         /* Not implemented yet */
     211                 :          0 :         EFSYS_ASSERT(B_FALSE);
     212                 :            : }
     213                 :            : 
     214                 :            : static  __checkReturn   boolean_t
     215                 :          0 : rhead_ev_dispatch(
     216                 :            :         __in            efx_evq_t *eep,
     217                 :            :         __in            efx_qword_t *eventp,
     218                 :            :         __in            const efx_ev_callbacks_t *eecp,
     219                 :            :         __in_opt        void *arg)
     220                 :            : {
     221                 :            :         boolean_t should_abort;
     222                 :            :         uint32_t code;
     223                 :            : 
     224                 :          0 :         code = EFX_QWORD_FIELD(*eventp, ESF_GZ_E_TYPE);
     225   [ #  #  #  # ]:          0 :         switch (code) {
     226                 :          0 :         case ESE_GZ_EF100_EV_RX_PKTS:
     227                 :          0 :                 should_abort = eep->ee_rx(eep, eventp, eecp, arg);
     228                 :          0 :                 break;
     229                 :          0 :         case ESE_GZ_EF100_EV_TX_COMPLETION:
     230                 :          0 :                 should_abort = eep->ee_tx(eep, eventp, eecp, arg);
     231                 :          0 :                 break;
     232                 :          0 :         case ESE_GZ_EF100_EV_MCDI:
     233                 :          0 :                 should_abort = eep->ee_mcdi(eep, eventp, eecp, arg);
     234                 :          0 :                 break;
     235                 :          0 :         default:
     236                 :            :                 EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
     237                 :            :                     uint32_t, EFX_QWORD_FIELD(*eventp, EFX_DWORD_1),
     238                 :            :                     uint32_t, EFX_QWORD_FIELD(*eventp, EFX_DWORD_0));
     239                 :            : 
     240         [ #  # ]:          0 :                 EFSYS_ASSERT(eecp->eec_exception != NULL);
     241                 :          0 :                 (void) eecp->eec_exception(arg, EFX_EXCEPTION_EV_ERROR, code);
     242                 :            :                 should_abort = B_TRUE;
     243                 :          0 :                 break;
     244                 :            :         }
     245                 :            : 
     246                 :          0 :         return (should_abort);
     247                 :            : }
     248                 :            : 
     249                 :            : /*
     250                 :            :  * Poll event queue in batches. Size of the batch is equal to cache line
     251                 :            :  * size divided by event size.
     252                 :            :  *
     253                 :            :  * Event queue is written by NIC and read by CPU. If CPU starts reading
     254                 :            :  * of events on the cache line, read all remaining events in a tight
     255                 :            :  * loop while event is present.
     256                 :            :  */
     257                 :            : #define EF100_EV_BATCH  8
     258                 :            : 
     259                 :            : /*
     260                 :            :  * Check if event is present.
     261                 :            :  *
     262                 :            :  * Riverhead EvQs use a phase bit to indicate the presence of valid events,
     263                 :            :  * by flipping the phase bit on each wrap of the write index.
     264                 :            :  */
     265                 :            : #define EF100_EV_PRESENT(_qword, _phase_bit)                            \
     266                 :            :         (EFX_QWORD_FIELD((_qword), ESF_GZ_EV_EVQ_PHASE) == _phase_bit)
     267                 :            : 
     268                 :            :                         void
     269                 :          0 : rhead_ev_qpoll(
     270                 :            :         __in            efx_evq_t *eep,
     271                 :            :         __inout         unsigned int *countp,
     272                 :            :         __in            const efx_ev_callbacks_t *eecp,
     273                 :            :         __in_opt        void *arg)
     274                 :            : {
     275                 :            :         efx_qword_t ev[EF100_EV_BATCH];
     276                 :            :         unsigned int batch;
     277                 :            :         unsigned int phase_bit;
     278                 :            :         unsigned int total;
     279                 :            :         unsigned int count;
     280                 :            :         unsigned int index;
     281                 :            :         size_t offset;
     282                 :            : 
     283                 :            : #if EFSYS_OPT_EV_EXTENDED_WIDTH
     284                 :            :         if (eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) {
     285                 :            :                 rhead_ev_ew_qpoll(eep, countp, eecp, arg);
     286                 :            :                 return;
     287                 :            :         }
     288                 :            : #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
     289                 :            : 
     290         [ #  # ]:          0 :         EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
     291         [ #  # ]:          0 :         EFSYS_ASSERT(countp != NULL);
     292         [ #  # ]:          0 :         EFSYS_ASSERT(eecp != NULL);
     293                 :            : 
     294                 :          0 :         count = *countp;
     295                 :            :         do {
     296                 :            :                 /* Read up until the end of the batch period */
     297                 :          0 :                 batch = EF100_EV_BATCH - (count & (EF100_EV_BATCH - 1));
     298                 :          0 :                 phase_bit = (count & (eep->ee_mask + 1)) != 0;
     299                 :          0 :                 offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
     300         [ #  # ]:          0 :                 for (total = 0; total < batch; ++total) {
     301                 :          0 :                         EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total]));
     302                 :            : 
     303         [ #  # ]:          0 :                         if (!EF100_EV_PRESENT(ev[total], phase_bit))
     304                 :            :                                 break;
     305                 :            : 
     306                 :            :                         EFSYS_PROBE3(event, unsigned int, eep->ee_index,
     307                 :            :                             uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1),
     308                 :            :                             uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0));
     309                 :            : 
     310                 :          0 :                         offset += sizeof (efx_qword_t);
     311                 :            :                 }
     312                 :            : 
     313                 :            :                 /* Process the batch of events */
     314         [ #  # ]:          0 :                 for (index = 0; index < total; ++index) {
     315                 :            :                         boolean_t should_abort;
     316                 :            : 
     317                 :            :                         EFX_EV_QSTAT_INCR(eep, EV_ALL);
     318                 :            : 
     319                 :            :                         should_abort =
     320                 :          0 :                             rhead_ev_dispatch(eep, &(ev[index]), eecp, arg);
     321                 :            : 
     322         [ #  # ]:          0 :                         if (should_abort) {
     323                 :            :                                 /* Ignore subsequent events */
     324                 :          0 :                                 total = index + 1;
     325                 :            : 
     326                 :            :                                 /*
     327                 :            :                                  * Poison batch to ensure the outer
     328                 :            :                                  * loop is broken out of.
     329                 :            :                                  */
     330                 :            :                                 EFSYS_ASSERT(batch <= EF100_EV_BATCH);
     331                 :          0 :                                 batch += (EF100_EV_BATCH << 1);
     332                 :            :                                 EFSYS_ASSERT(total != batch);
     333                 :            :                                 break;
     334                 :            :                         }
     335                 :            :                 }
     336                 :            : 
     337                 :            :                 /*
     338                 :            :                  * There is no necessity to clear processed events since
     339                 :            :                  * phase bit which is flipping on each write index wrap
     340                 :            :                  * is used for event presence indication.
     341                 :            :                  */
     342                 :            : 
     343                 :          0 :                 count += total;
     344                 :            : 
     345         [ #  # ]:          0 :         } while (total == batch);
     346                 :            : 
     347                 :          0 :         *countp = count;
     348                 :          0 : }
     349                 :            : 
     350                 :            : #if EFSYS_OPT_EV_EXTENDED_WIDTH
     351                 :            : static                  boolean_t
     352                 :            : rhead_ev_ew_dispatch(
     353                 :            :         __in            efx_evq_t *eep,
     354                 :            :         __in            efx_xword_t *eventp,
     355                 :            :         __in            const efx_ev_callbacks_t *eecp,
     356                 :            :         __in_opt        void *arg)
     357                 :            : {
     358                 :            :         boolean_t should_abort;
     359                 :            :         uint32_t code;
     360                 :            : 
     361                 :            :         EFSYS_ASSERT((eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) != 0);
     362                 :            : 
     363                 :            :         code = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_256_EV32_TYPE);
     364                 :            :         switch (code) {
     365                 :            :         case ESE_GZ_EF100_EVEW_64BIT:
     366                 :            :                 /* NOTE: ignore phase bit in encapsulated 64bit event. */
     367                 :            :                 should_abort =
     368                 :            :                     rhead_ev_dispatch(eep, &eventp->ex_qword[0], eecp, arg);
     369                 :            :                 break;
     370                 :            : 
     371                 :            : #if EFSYS_OPT_DESC_PROXY
     372                 :            :         case ESE_GZ_EF100_EVEW_TXQ_DESC:
     373                 :            :                 should_abort = eep->ee_ew_txq_desc(eep, eventp, eecp, arg);
     374                 :            :                 break;
     375                 :            : 
     376                 :            :         case ESE_GZ_EF100_EVEW_VIRTQ_DESC:
     377                 :            :                 should_abort = eep->ee_ew_virtq_desc(eep, eventp, eecp, arg);
     378                 :            :                 break;
     379                 :            : #endif /* EFSYS_OPT_DESC_PROXY */
     380                 :            : 
     381                 :            :         default:
     382                 :            :                 /* Omit currently unused reserved bits from the probe. */
     383                 :            :                 EFSYS_PROBE7(ew_bad_event, unsigned int, eep->ee_index,
     384                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_7),
     385                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_4),
     386                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_3),
     387                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_2),
     388                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_1),
     389                 :            :                     uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_0));
     390                 :            : 
     391                 :            :                 EFSYS_ASSERT(eecp->eec_exception != NULL);
     392                 :            :                 (void) eecp->eec_exception(arg, EFX_EXCEPTION_EV_ERROR, code);
     393                 :            :                 should_abort = B_TRUE;
     394                 :            :         }
     395                 :            : 
     396                 :            :         return (should_abort);
     397                 :            : }
     398                 :            : 
     399                 :            : /*
     400                 :            :  * Poll extended width event queue. Size of the batch is equal to cache line
     401                 :            :  * size divided by event size.
     402                 :            :  */
     403                 :            : #define EF100_EV_EW_BATCH       2
     404                 :            : 
     405                 :            : /*
     406                 :            :  * Check if event is present.
     407                 :            :  *
     408                 :            :  * Riverhead EvQs use a phase bit to indicate the presence of valid events,
     409                 :            :  * by flipping the phase bit on each wrap of the write index.
     410                 :            :  */
     411                 :            : #define EF100_EV_EW_PRESENT(_xword, _phase_bit)                         \
     412                 :            :         (EFX_XWORD_FIELD((_xword), ESF_GZ_EV_256_EV32_PHASE) == (_phase_bit))
     413                 :            : 
     414                 :            : static                  void
     415                 :            : rhead_ev_ew_qpoll(
     416                 :            :         __in            efx_evq_t *eep,
     417                 :            :         __inout         unsigned int *countp,
     418                 :            :         __in            const efx_ev_callbacks_t *eecp,
     419                 :            :         __in_opt        void *arg)
     420                 :            : {
     421                 :            :         efx_xword_t ev[EF100_EV_EW_BATCH];
     422                 :            :         unsigned int batch;
     423                 :            :         unsigned int phase_bit;
     424                 :            :         unsigned int total;
     425                 :            :         unsigned int count;
     426                 :            :         unsigned int index;
     427                 :            :         size_t offset;
     428                 :            : 
     429                 :            :         EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
     430                 :            :         EFSYS_ASSERT((eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) != 0);
     431                 :            :         EFSYS_ASSERT(countp != NULL);
     432                 :            :         EFSYS_ASSERT(eecp != NULL);
     433                 :            : 
     434                 :            :         count = *countp;
     435                 :            :         do {
     436                 :            :                 /* Read up until the end of the batch period */
     437                 :            :                 batch = EF100_EV_EW_BATCH - (count & (EF100_EV_EW_BATCH - 1));
     438                 :            :                 phase_bit = (count & (eep->ee_mask + 1)) != 0;
     439                 :            :                 offset = (count & eep->ee_mask) * sizeof (efx_xword_t);
     440                 :            :                 for (total = 0; total < batch; ++total) {
     441                 :            :                         EFSYS_MEM_READX(eep->ee_esmp, offset, &(ev[total]));
     442                 :            : 
     443                 :            :                         if (!EF100_EV_EW_PRESENT(ev[total], phase_bit))
     444                 :            :                                 break;
     445                 :            : 
     446                 :            :                         /* Omit unused reserved bits from the probe. */
     447                 :            :                         EFSYS_PROBE7(ew_event, unsigned int, eep->ee_index,
     448                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_7),
     449                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_4),
     450                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_3),
     451                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_2),
     452                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_1),
     453                 :            :                             uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_0));
     454                 :            : 
     455                 :            :                         offset += sizeof (efx_xword_t);
     456                 :            :                 }
     457                 :            : 
     458                 :            :                 /* Process the batch of events */
     459                 :            :                 for (index = 0; index < total; ++index) {
     460                 :            :                         boolean_t should_abort;
     461                 :            : 
     462                 :            :                         EFX_EV_QSTAT_INCR(eep, EV_ALL);
     463                 :            : 
     464                 :            :                         should_abort =
     465                 :            :                             rhead_ev_ew_dispatch(eep, &(ev[index]), eecp, arg);
     466                 :            : 
     467                 :            :                         if (should_abort) {
     468                 :            :                                 /* Ignore subsequent events */
     469                 :            :                                 total = index + 1;
     470                 :            : 
     471                 :            :                                 /*
     472                 :            :                                  * Poison batch to ensure the outer
     473                 :            :                                  * loop is broken out of.
     474                 :            :                                  */
     475                 :            :                                 EFSYS_ASSERT(batch <= EF100_EV_EW_BATCH);
     476                 :            :                                 batch += (EF100_EV_EW_BATCH << 1);
     477                 :            :                                 EFSYS_ASSERT(total != batch);
     478                 :            :                                 break;
     479                 :            :                         }
     480                 :            :                 }
     481                 :            : 
     482                 :            :                 /*
     483                 :            :                  * There is no necessity to clear processed events since
     484                 :            :                  * phase bit which is flipping on each write index wrap
     485                 :            :                  * is used for event presence indication.
     486                 :            :                  */
     487                 :            : 
     488                 :            :                 count += total;
     489                 :            : 
     490                 :            :         } while (total == batch);
     491                 :            : 
     492                 :            :         *countp = count;
     493                 :            : }
     494                 :            : #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
     495                 :            : 
     496                 :            : 
     497                 :            :         __checkReturn   efx_rc_t
     498                 :          0 : rhead_ev_qmoderate(
     499                 :            :         __in            efx_evq_t *eep,
     500                 :            :         __in            unsigned int us)
     501                 :            : {
     502                 :            :         _NOTE(ARGUNUSED(eep, us))
     503                 :            : 
     504                 :          0 :         return (ENOTSUP);
     505                 :            : }
     506                 :            : 
     507                 :            : 
     508                 :            : #if EFSYS_OPT_QSTATS
     509                 :            :                         void
     510                 :            : rhead_ev_qstats_update(
     511                 :            :         __in                            efx_evq_t *eep,
     512                 :            :         __inout_ecount(EV_NQSTATS)      efsys_stat_t *stat)
     513                 :            : {
     514                 :            :         unsigned int id;
     515                 :            : 
     516                 :            :         for (id = 0; id < EV_NQSTATS; id++) {
     517                 :            :                 efsys_stat_t *essp = &stat[id];
     518                 :            : 
     519                 :            :                 EFSYS_STAT_INCR(essp, eep->ee_stat[id]);
     520                 :            :                 eep->ee_stat[id] = 0;
     521                 :            :         }
     522                 :            : }
     523                 :            : #endif /* EFSYS_OPT_QSTATS */
     524                 :            : 
     525                 :            : static  __checkReturn   boolean_t
     526                 :          0 : rhead_ev_rx_packets(
     527                 :            :         __in            efx_evq_t *eep,
     528                 :            :         __in            efx_qword_t *eqp,
     529                 :            :         __in            const efx_ev_callbacks_t *eecp,
     530                 :            :         __in_opt        void *arg)
     531                 :            : {
     532                 :          0 :         efx_nic_t *enp = eep->ee_enp;
     533                 :            :         uint32_t label;
     534                 :            :         uint32_t num_packets;
     535                 :            :         boolean_t should_abort;
     536                 :            : 
     537                 :            :         EFX_EV_QSTAT_INCR(eep, EV_RX);
     538                 :            : 
     539                 :            :         /* Discard events after RXQ/TXQ errors, or hardware not available */
     540         [ #  # ]:          0 :         if (enp->en_reset_flags &
     541                 :            :             (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
     542                 :            :                 return (B_FALSE);
     543                 :            : 
     544                 :          0 :         label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_Q_LABEL);
     545                 :            : 
     546                 :            :         /*
     547                 :            :          * On EF100 the EV_RX event reports the number of received
     548                 :            :          * packets (unlike EF10 which reports a descriptor index).
     549                 :            :          * The client driver is responsible for maintaining the Rx
     550                 :            :          * descriptor index, and computing how many descriptors are
     551                 :            :          * occupied by each received packet (based on the Rx buffer size
     552                 :            :          * and the packet length from the Rx prefix).
     553                 :            :          */
     554                 :          0 :         num_packets = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_NUM_PKT);
     555                 :            : 
     556                 :            :         /*
     557                 :            :          * The receive event may indicate more than one packet, and so
     558                 :            :          * does not contain the packet length. Read the packet length
     559                 :            :          * from the prefix when handling each packet.
     560                 :            :          */
     561         [ #  # ]:          0 :         EFSYS_ASSERT(eecp->eec_rx_packets != NULL);
     562                 :          0 :         should_abort = eecp->eec_rx_packets(arg, label, num_packets,
     563                 :            :             EFX_PKT_PREFIX_LEN);
     564                 :            : 
     565                 :          0 :         return (should_abort);
     566                 :            : }
     567                 :            : 
     568                 :            : static  __checkReturn   boolean_t
     569                 :          0 : rhead_ev_tx_completion(
     570                 :            :         __in            efx_evq_t *eep,
     571                 :            :         __in            efx_qword_t *eqp,
     572                 :            :         __in            const efx_ev_callbacks_t *eecp,
     573                 :            :         __in_opt        void *arg)
     574                 :            : {
     575                 :          0 :         efx_nic_t *enp = eep->ee_enp;
     576                 :            :         uint32_t num_descs;
     577                 :            :         uint32_t label;
     578                 :            :         boolean_t should_abort;
     579                 :            : 
     580                 :            :         EFX_EV_QSTAT_INCR(eep, EV_TX);
     581                 :            : 
     582                 :            :         /* Discard events after RXQ/TXQ errors, or hardware not available */
     583         [ #  # ]:          0 :         if (enp->en_reset_flags &
     584                 :            :             (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
     585                 :            :                 return (B_FALSE);
     586                 :            : 
     587                 :          0 :         label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_Q_LABEL);
     588                 :            : 
     589                 :            :         /*
     590                 :            :          * On EF100 the EV_TX event reports the number of completed Tx
     591                 :            :          * descriptors (on EF10, the event reports the low bits of the
     592                 :            :          * index of the last completed descriptor).
     593                 :            :          * The client driver completion callback will compute the
     594                 :            :          * descriptor index, so that is not needed here.
     595                 :            :          */
     596                 :          0 :         num_descs = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_NUM_DESC);
     597                 :            : 
     598                 :            :         EFSYS_PROBE2(tx_ndescs, uint32_t, label, unsigned int, num_descs);
     599                 :            : 
     600         [ #  # ]:          0 :         EFSYS_ASSERT(eecp->eec_tx_ndescs != NULL);
     601                 :          0 :         should_abort = eecp->eec_tx_ndescs(arg, label, num_descs);
     602                 :            : 
     603                 :          0 :         return (should_abort);
     604                 :            : }
     605                 :            : 
     606                 :            : static  __checkReturn   boolean_t
     607                 :          0 : rhead_ev_mcdi(
     608                 :            :         __in            efx_evq_t *eep,
     609                 :            :         __in            efx_qword_t *eqp,
     610                 :            :         __in            const efx_ev_callbacks_t *eecp,
     611                 :            :         __in_opt        void *arg)
     612                 :            : {
     613                 :            :         boolean_t ret;
     614                 :            : 
     615                 :            :         /*
     616                 :            :          * Event format was changed post Riverhead R1 and now
     617                 :            :          * MCDI event layout on EF100 is exactly the same as on EF10
     618                 :            :          * except added QDMA phase bit which is unused on EF10.
     619                 :            :          */
     620                 :          0 :         ret = ef10_ev_mcdi(eep, eqp, eecp, arg);
     621                 :            : 
     622                 :          0 :         return (ret);
     623                 :            : }
     624                 :            : 
     625                 :            : #if EFSYS_OPT_DESC_PROXY
     626                 :            : static                  boolean_t
     627                 :            : rhead_ev_ew_txq_desc(
     628                 :            :         __in            efx_evq_t *eep,
     629                 :            :         __in            efx_xword_t *eventp,
     630                 :            :         __in            const efx_ev_callbacks_t *eecp,
     631                 :            :         __in_opt        void *arg)
     632                 :            : {
     633                 :            :         efx_oword_t txq_desc;
     634                 :            :         uint16_t vi_id;
     635                 :            :         boolean_t should_abort;
     636                 :            : 
     637                 :            :         _NOTE(ARGUNUSED(eep))
     638                 :            : 
     639                 :            :         vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_TXQ_DP_VI_ID);
     640                 :            : 
     641                 :            :         /*
     642                 :            :          * NOTE: This is the raw descriptor data, and has not been converted
     643                 :            :          * to host endian. The handler callback must use the EFX_OWORD macros
     644                 :            :          * to extract the descriptor fields as host endian values.
     645                 :            :          */
     646                 :            :         txq_desc = eventp->ex_oword[0];
     647                 :            : 
     648                 :            :         EFSYS_ASSERT(eecp->eec_desc_proxy_txq_desc != NULL);
     649                 :            :         should_abort = eecp->eec_desc_proxy_txq_desc(arg, vi_id, txq_desc);
     650                 :            : 
     651                 :            :         return (should_abort);
     652                 :            : }
     653                 :            : #endif /* EFSYS_OPT_DESC_PROXY */
     654                 :            : 
     655                 :            : 
     656                 :            : #if EFSYS_OPT_DESC_PROXY
     657                 :            : static                  boolean_t
     658                 :            : rhead_ev_ew_virtq_desc(
     659                 :            :         __in            efx_evq_t *eep,
     660                 :            :         __in            efx_xword_t *eventp,
     661                 :            :         __in            const efx_ev_callbacks_t *eecp,
     662                 :            :         __in_opt        void *arg)
     663                 :            : {
     664                 :            :         efx_oword_t virtq_desc;
     665                 :            :         uint16_t vi_id;
     666                 :            :         uint16_t avail;
     667                 :            :         boolean_t should_abort;
     668                 :            : 
     669                 :            :         _NOTE(ARGUNUSED(eep))
     670                 :            : 
     671                 :            :         vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_VI_ID);
     672                 :            :         avail = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_AVAIL_ENTRY);
     673                 :            : 
     674                 :            :         /*
     675                 :            :          * NOTE: This is the raw descriptor data, and has not been converted
     676                 :            :          * to host endian. The handler callback must use the EFX_OWORD macros
     677                 :            :          * to extract the descriptor fields as host endian values.
     678                 :            :          */
     679                 :            :         virtq_desc = eventp->ex_oword[0];
     680                 :            : 
     681                 :            :         EFSYS_ASSERT(eecp->eec_desc_proxy_virtq_desc != NULL);
     682                 :            :         should_abort =
     683                 :            :             eecp->eec_desc_proxy_virtq_desc(arg, vi_id, avail, virtq_desc);
     684                 :            : 
     685                 :            :         return (should_abort);
     686                 :            : }
     687                 :            : #endif /* EFSYS_OPT_DESC_PROXY */
     688                 :            : 
     689                 :            : #endif  /* EFSYS_OPT_RIVERHEAD */

Generated by: LCOV version 1.14