common/sfc_efx/base: handle Tx complete on Riverhead
[dpdk.git] / drivers / common / sfc_efx / base / rhead_ev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 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  __checkReturn   boolean_t
20 rhead_ev_rx_packets(
21         __in            efx_evq_t *eep,
22         __in            efx_qword_t *eqp,
23         __in            const efx_ev_callbacks_t *eecp,
24         __in_opt        void *arg);
25
26 static  __checkReturn   boolean_t
27 rhead_ev_tx_completion(
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
34 static  __checkReturn   boolean_t
35 rhead_ev_mcdi(
36         __in            efx_evq_t *eep,
37         __in            efx_qword_t *eqp,
38         __in            const efx_ev_callbacks_t *eecp,
39         __in_opt        void *arg);
40
41
42         __checkReturn   efx_rc_t
43 rhead_ev_init(
44         __in            efx_nic_t *enp)
45 {
46         _NOTE(ARGUNUSED(enp))
47
48         return (0);
49 }
50
51                         void
52 rhead_ev_fini(
53         __in            efx_nic_t *enp)
54 {
55         _NOTE(ARGUNUSED(enp))
56 }
57
58         __checkReturn   efx_rc_t
59 rhead_ev_qcreate(
60         __in            efx_nic_t *enp,
61         __in            unsigned int index,
62         __in            efsys_mem_t *esmp,
63         __in            size_t ndescs,
64         __in            uint32_t id,
65         __in            uint32_t us,
66         __in            uint32_t flags,
67         __in            efx_evq_t *eep)
68 {
69         uint32_t irq;
70         efx_rc_t rc;
71
72         _NOTE(ARGUNUSED(id))    /* buftbl id managed by MC */
73
74         /* Set up the handler table */
75         eep->ee_rx      = rhead_ev_rx_packets;
76         eep->ee_tx      = rhead_ev_tx_completion;
77         eep->ee_driver  = NULL; /* FIXME */
78         eep->ee_drv_gen = NULL; /* FIXME */
79         eep->ee_mcdi    = rhead_ev_mcdi;
80
81         /* Set up the event queue */
82         /* INIT_EVQ expects function-relative vector number */
83         if ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
84             EFX_EVQ_FLAGS_NOTIFY_INTERRUPT) {
85                 irq = index;
86         } else if (index == EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX) {
87                 irq = index;
88                 flags = (flags & ~EFX_EVQ_FLAGS_NOTIFY_MASK) |
89                     EFX_EVQ_FLAGS_NOTIFY_INTERRUPT;
90         } else {
91                 irq = EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX;
92         }
93
94         /*
95          * Interrupts may be raised for events immediately after the queue is
96          * created. See bug58606.
97          */
98         rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, us, flags,
99             B_FALSE);
100         if (rc != 0)
101                 goto fail1;
102
103         return (0);
104
105 fail1:
106         EFSYS_PROBE1(fail1, efx_rc_t, rc);
107
108         return (rc);
109 }
110
111                         void
112 rhead_ev_qdestroy(
113         __in            efx_evq_t *eep)
114 {
115         efx_nic_t *enp = eep->ee_enp;
116
117         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_RIVERHEAD);
118
119         (void) efx_mcdi_fini_evq(enp, eep->ee_index);
120 }
121
122         __checkReturn   efx_rc_t
123 rhead_ev_qprime(
124         __in            efx_evq_t *eep,
125         __in            unsigned int count)
126 {
127         efx_nic_t *enp = eep->ee_enp;
128         uint32_t rptr;
129         efx_dword_t dword;
130
131         rptr = count & eep->ee_mask;
132
133         EFX_POPULATE_DWORD_2(dword, ERF_GZ_EVQ_ID, eep->ee_index,
134             ERF_GZ_IDX, rptr);
135         /* EVQ_INT_PRIME lives function control window only on Riverhead */
136         EFX_BAR_WRITED(enp, ER_GZ_EVQ_INT_PRIME, &dword, B_FALSE);
137
138         return (0);
139 }
140
141                         void
142 rhead_ev_qpost(
143         __in    efx_evq_t *eep,
144         __in    uint16_t data)
145 {
146         _NOTE(ARGUNUSED(eep, data))
147
148         /* Not implemented yet */
149         EFSYS_ASSERT(B_FALSE);
150 }
151
152 /*
153  * Poll event queue in batches. Size of the batch is equal to cache line
154  * size divided by event size.
155  *
156  * Event queue is written by NIC and read by CPU. If CPU starts reading
157  * of events on the cache line, read all remaining events in a tight
158  * loop while event is present.
159  */
160 #define EF100_EV_BATCH  8
161
162 /*
163  * Check if event is present.
164  *
165  * Riverhead EvQs use a phase bit to indicate the presence of valid events,
166  * by flipping the phase bit on each wrap of the write index.
167  */
168 #define EF100_EV_PRESENT(_qword, _phase_bit)                            \
169         (EFX_QWORD_FIELD((_qword), ESF_GZ_EV_EVQ_PHASE) == _phase_bit)
170
171                         void
172 rhead_ev_qpoll(
173         __in            efx_evq_t *eep,
174         __inout         unsigned int *countp,
175         __in            const efx_ev_callbacks_t *eecp,
176         __in_opt        void *arg)
177 {
178         efx_qword_t ev[EF100_EV_BATCH];
179         unsigned int batch;
180         unsigned int phase_bit;
181         unsigned int total;
182         unsigned int count;
183         unsigned int index;
184         size_t offset;
185
186         EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
187         EFSYS_ASSERT(countp != NULL);
188         EFSYS_ASSERT(eecp != NULL);
189
190         count = *countp;
191         do {
192                 /* Read up until the end of the batch period */
193                 batch = EF100_EV_BATCH - (count & (EF100_EV_BATCH - 1));
194                 phase_bit = (count & (eep->ee_mask + 1)) != 0;
195                 offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
196                 for (total = 0; total < batch; ++total) {
197                         EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total]));
198
199                         if (!EF100_EV_PRESENT(ev[total], phase_bit))
200                                 break;
201
202                         EFSYS_PROBE3(event, unsigned int, eep->ee_index,
203                             uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1),
204                             uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0));
205
206                         offset += sizeof (efx_qword_t);
207                 }
208
209                 /* Process the batch of events */
210                 for (index = 0; index < total; ++index) {
211                         boolean_t should_abort;
212                         uint32_t code;
213
214                         EFX_EV_QSTAT_INCR(eep, EV_ALL);
215
216                         code = EFX_QWORD_FIELD(ev[index], ESF_GZ_E_TYPE);
217                         switch (code) {
218                         case ESE_GZ_EF100_EV_RX_PKTS:
219                                 should_abort = eep->ee_rx(eep,
220                                     &(ev[index]), eecp, arg);
221                                 break;
222                         case ESE_GZ_EF100_EV_TX_COMPLETION:
223                                 should_abort = eep->ee_tx(eep,
224                                     &(ev[index]), eecp, arg);
225                                 break;
226                         case ESE_GZ_EF100_EV_MCDI:
227                                 should_abort = eep->ee_mcdi(eep,
228                                     &(ev[index]), eecp, arg);
229                                 break;
230                         default:
231                                 EFSYS_PROBE3(bad_event,
232                                     unsigned int, eep->ee_index,
233                                     uint32_t,
234                                     EFX_QWORD_FIELD(ev[index], EFX_DWORD_1),
235                                     uint32_t,
236                                     EFX_QWORD_FIELD(ev[index], EFX_DWORD_0));
237
238                                 EFSYS_ASSERT(eecp->eec_exception != NULL);
239                                 (void) eecp->eec_exception(arg,
240                                         EFX_EXCEPTION_EV_ERROR, code);
241                                 should_abort = B_TRUE;
242                         }
243                         if (should_abort) {
244                                 /* Ignore subsequent events */
245                                 total = index + 1;
246
247                                 /*
248                                  * Poison batch to ensure the outer
249                                  * loop is broken out of.
250                                  */
251                                 EFSYS_ASSERT(batch <= EF100_EV_BATCH);
252                                 batch += (EF100_EV_BATCH << 1);
253                                 EFSYS_ASSERT(total != batch);
254                                 break;
255                         }
256                 }
257
258                 /*
259                  * There is no necessity to clear processed events since
260                  * phase bit which is flipping on each write index wrap
261                  * is used for event presence indication.
262                  */
263
264                 count += total;
265
266         } while (total == batch);
267
268         *countp = count;
269 }
270
271         __checkReturn   efx_rc_t
272 rhead_ev_qmoderate(
273         __in            efx_evq_t *eep,
274         __in            unsigned int us)
275 {
276         _NOTE(ARGUNUSED(eep, us))
277
278         return (ENOTSUP);
279 }
280
281
282 #if EFSYS_OPT_QSTATS
283                         void
284 rhead_ev_qstats_update(
285         __in                            efx_evq_t *eep,
286         __inout_ecount(EV_NQSTATS)      efsys_stat_t *stat)
287 {
288         unsigned int id;
289
290         for (id = 0; id < EV_NQSTATS; id++) {
291                 efsys_stat_t *essp = &stat[id];
292
293                 EFSYS_STAT_INCR(essp, eep->ee_stat[id]);
294                 eep->ee_stat[id] = 0;
295         }
296 }
297 #endif /* EFSYS_OPT_QSTATS */
298
299 static  __checkReturn   boolean_t
300 rhead_ev_rx_packets(
301         __in            efx_evq_t *eep,
302         __in            efx_qword_t *eqp,
303         __in            const efx_ev_callbacks_t *eecp,
304         __in_opt        void *arg)
305 {
306         efx_nic_t *enp = eep->ee_enp;
307         uint32_t label;
308         uint32_t num_packets;
309         boolean_t should_abort;
310
311         EFX_EV_QSTAT_INCR(eep, EV_RX);
312
313         /* Discard events after RXQ/TXQ errors, or hardware not available */
314         if (enp->en_reset_flags &
315             (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
316                 return (B_FALSE);
317
318         label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_Q_LABEL);
319
320         /*
321          * On EF100 the EV_RX event reports the number of received
322          * packets (unlike EF10 which reports a descriptor index).
323          * The client driver is responsible for maintaining the Rx
324          * descriptor index, and computing how many descriptors are
325          * occupied by each received packet (based on the Rx buffer size
326          * and the packet length from the Rx prefix).
327          */
328         num_packets = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_NUM_PKT);
329
330         /*
331          * The receive event may indicate more than one packet, and so
332          * does not contain the packet length. Read the packet length
333          * from the prefix when handling each packet.
334          */
335         EFSYS_ASSERT(eecp->eec_rx_packets != NULL);
336         should_abort = eecp->eec_rx_packets(arg, label, num_packets,
337             EFX_PKT_PREFIX_LEN);
338
339         return (should_abort);
340 }
341
342 static  __checkReturn   boolean_t
343 rhead_ev_tx_completion(
344         __in            efx_evq_t *eep,
345         __in            efx_qword_t *eqp,
346         __in            const efx_ev_callbacks_t *eecp,
347         __in_opt        void *arg)
348 {
349         efx_nic_t *enp = eep->ee_enp;
350         uint32_t num_descs;
351         uint32_t label;
352         boolean_t should_abort;
353
354         EFX_EV_QSTAT_INCR(eep, EV_TX);
355
356         /* Discard events after RXQ/TXQ errors, or hardware not available */
357         if (enp->en_reset_flags &
358             (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
359                 return (B_FALSE);
360
361         label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_Q_LABEL);
362
363         /*
364          * On EF100 the EV_TX event reports the number of completed Tx
365          * descriptors (on EF10, the event reports the low bits of the
366          * index of the last completed descriptor).
367          * The client driver completion callback will compute the
368          * descriptor index, so that is not needed here.
369          */
370         num_descs = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_NUM_DESC);
371
372         EFSYS_PROBE2(tx_ndescs, uint32_t, label, unsigned int, num_descs);
373
374         EFSYS_ASSERT(eecp->eec_tx_ndescs != NULL);
375         should_abort = eecp->eec_tx_ndescs(arg, label, num_descs);
376
377         return (should_abort);
378 }
379
380 static  __checkReturn   boolean_t
381 rhead_ev_mcdi(
382         __in            efx_evq_t *eep,
383         __in            efx_qword_t *eqp,
384         __in            const efx_ev_callbacks_t *eecp,
385         __in_opt        void *arg)
386 {
387         boolean_t ret;
388
389         /*
390          * Event format was changed post Riverhead R1 and now
391          * MCDI event layout on EF100 is exactly the same as on EF10
392          * except added QDMA phase bit which is unused on EF10.
393          */
394         ret = ef10_ev_mcdi(eep, eqp, eecp, arg);
395
396         return (ret);
397 }
398
399 #endif  /* EFSYS_OPT_RIVERHEAD */