]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/sfxge/common/hunt_rx.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / sfxge / common / hunt_rx.c
1 /*-
2  * Copyright (c) 2012-2015 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efsys.h"
35 #include "efx.h"
36 #include "efx_impl.h"
37
38
39 #if EFSYS_OPT_HUNTINGTON
40
41
42 static  __checkReturn   int
43 efx_mcdi_init_rxq(
44         __in            efx_nic_t *enp,
45         __in            uint32_t size,
46         __in            uint32_t target_evq,
47         __in            uint32_t label,
48         __in            uint32_t instance,
49         __in            efsys_mem_t *esmp)
50 {
51         efx_mcdi_req_t req;
52         uint8_t payload[
53             MAX(MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXQ_MAXNDESCS)),
54                 MC_CMD_INIT_RXQ_OUT_LEN)];
55         int npages = EFX_RXQ_NBUFS(size);
56         int i;
57         efx_qword_t *dma_addr;
58         uint64_t addr;
59         int rc;
60
61         EFSYS_ASSERT3U(size, <=, EFX_RXQ_MAXNDESCS);
62
63         (void) memset(payload, 0, sizeof (payload));
64         req.emr_cmd = MC_CMD_INIT_RXQ;
65         req.emr_in_buf = payload;
66         req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages);
67         req.emr_out_buf = payload;
68         req.emr_out_length = MC_CMD_INIT_RXQ_OUT_LEN;
69
70         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_SIZE, size);
71         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_TARGET_EVQ, target_evq);
72         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_LABEL, label);
73         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_INSTANCE, instance);
74         MCDI_IN_POPULATE_DWORD_5(req, INIT_RXQ_IN_FLAGS,
75                                     INIT_RXQ_IN_FLAG_BUFF_MODE, 0,
76                                     INIT_RXQ_IN_FLAG_HDR_SPLIT, 0,
77                                     INIT_RXQ_IN_FLAG_TIMESTAMP, 0,
78                                     INIT_RXQ_IN_CRC_MODE, 0,
79                                     INIT_RXQ_IN_FLAG_PREFIX, 1);
80         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_OWNER_ID, 0);
81         MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
82
83         dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR);
84         addr = EFSYS_MEM_ADDR(esmp);
85
86         for (i = 0; i < npages; i++) {
87                 EFX_POPULATE_QWORD_2(*dma_addr,
88                     EFX_DWORD_1, (uint32_t)(addr >> 32),
89                     EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
90
91                 dma_addr++;
92                 addr += EFX_BUF_SIZE;
93         }
94
95         efx_mcdi_execute(enp, &req);
96
97         if (req.emr_rc != 0) {
98                 rc = req.emr_rc;
99                 goto fail1;
100         }
101
102         return (0);
103
104 fail1:
105         EFSYS_PROBE1(fail1, int, rc);
106
107         return (rc);
108 }
109
110 static  __checkReturn   int
111 efx_mcdi_fini_rxq(
112         __in            efx_nic_t *enp,
113         __in            uint32_t instance)
114 {
115         efx_mcdi_req_t req;
116         uint8_t payload[MAX(MC_CMD_FINI_RXQ_IN_LEN,
117                             MC_CMD_FINI_RXQ_OUT_LEN)];
118         int rc;
119
120         (void) memset(payload, 0, sizeof (payload));
121         req.emr_cmd = MC_CMD_FINI_RXQ;
122         req.emr_in_buf = payload;
123         req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
124         req.emr_out_buf = payload;
125         req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN;
126
127         MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance);
128
129         efx_mcdi_execute(enp, &req);
130
131         if ((req.emr_rc != 0) && (req.emr_rc != MC_CMD_ERR_EALREADY)) {
132                 rc = req.emr_rc;
133                 goto fail1;
134         }
135
136         return (0);
137
138 fail1:
139         EFSYS_PROBE1(fail1, int, rc);
140
141         return (rc);
142 }
143
144 #if EFSYS_OPT_RX_SCALE
145 static  __checkReturn   int
146 efx_mcdi_rss_context_alloc(
147         __in            efx_nic_t *enp,
148         __out           uint32_t *rss_contextp)
149 {
150         efx_mcdi_req_t req;
151         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN,
152                             MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN)];
153         uint32_t rss_context;
154         int rc;
155
156         (void) memset(payload, 0, sizeof (payload));
157         req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
158         req.emr_in_buf = payload;
159         req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
160         req.emr_out_buf = payload;
161         req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
162
163         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
164             EVB_PORT_ID_ASSIGNED);
165         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE,
166             MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE);
167         /* NUM_QUEUES is only used to validate indirection table offsets */
168         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, 64);
169
170         efx_mcdi_execute(enp, &req);
171
172         if (req.emr_rc != 0) {
173                 rc = req.emr_rc;
174                 goto fail1;
175         }
176
177         if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
178                 rc = EMSGSIZE;
179                 goto fail2;
180         }
181
182         rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
183         if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) {
184                 rc = ENOENT;
185                 goto fail3;
186         }
187
188         *rss_contextp = rss_context;
189
190         return (0);
191
192 fail3:
193         EFSYS_PROBE(fail3);
194 fail2:
195         EFSYS_PROBE(fail2);
196 fail1:
197         EFSYS_PROBE1(fail1, int, rc);
198
199         return (rc);
200 }
201 #endif /* EFSYS_OPT_RX_SCALE */
202
203 #if EFSYS_OPT_RX_SCALE
204 static  int
205 efx_mcdi_rss_context_free(
206         __in            efx_nic_t *enp,
207         __in            uint32_t rss_context)
208 {
209         efx_mcdi_req_t req;
210         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_FREE_IN_LEN,
211                             MC_CMD_RSS_CONTEXT_FREE_OUT_LEN)];
212         int rc;
213
214         if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) {
215                 rc = EINVAL;
216                 goto fail1;
217         }
218
219         (void) memset(payload, 0, sizeof (payload));
220         req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE;
221         req.emr_in_buf = payload;
222         req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN;
223         req.emr_out_buf = payload;
224         req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN;
225
226         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context);
227
228         efx_mcdi_execute(enp, &req);
229
230         if (req.emr_rc != 0) {
231                 rc = req.emr_rc;
232                 goto fail2;
233         }
234
235         return (0);
236
237 fail2:
238         EFSYS_PROBE(fail2);
239 fail1:
240         EFSYS_PROBE1(fail1, int, rc);
241
242         return (rc);
243 }
244 #endif /* EFSYS_OPT_RX_SCALE */
245
246 #if EFSYS_OPT_RX_SCALE
247 static  int
248 efx_mcdi_rss_context_set_flags(
249         __in            efx_nic_t *enp,
250         __in            uint32_t rss_context,
251         __in            efx_rx_hash_type_t type)
252 {
253         efx_mcdi_req_t req;
254         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
255                             MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)];
256         int rc;
257
258         if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) {
259                 rc = EINVAL;
260                 goto fail1;
261         }
262
263         (void) memset(payload, 0, sizeof (payload));
264         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
265         req.emr_in_buf = payload;
266         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
267         req.emr_out_buf = payload;
268         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
269
270         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
271             rss_context);
272
273         MCDI_IN_POPULATE_DWORD_4(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
274             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
275             (type & (1U << EFX_RX_HASH_IPV4)) ? 1 : 0,
276             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
277             (type & (1U << EFX_RX_HASH_TCPIPV4)) ? 1 : 0,
278             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
279             (type & (1U << EFX_RX_HASH_IPV6)) ? 1 : 0,
280             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
281             (type & (1U << EFX_RX_HASH_TCPIPV6)) ? 1 : 0);
282
283         efx_mcdi_execute(enp, &req);
284
285         if (req.emr_rc != 0) {
286                 rc = req.emr_rc;
287                 goto fail2;
288         }
289
290         return (0);
291
292 fail2:
293         EFSYS_PROBE(fail2);
294 fail1:
295         EFSYS_PROBE1(fail1, int, rc);
296
297         return (rc);
298 }
299 #endif /* EFSYS_OPT_RX_SCALE */
300
301 #if EFSYS_OPT_RX_SCALE
302 static  int
303 efx_mcdi_rss_context_set_key(
304         __in            efx_nic_t *enp,
305         __in            uint32_t rss_context,
306         __in_ecount(n)  uint8_t *key,
307         __in            size_t n)
308 {
309         efx_mcdi_req_t req;
310         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
311                             MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN)];
312         int rc;
313
314         if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) {
315                 rc = EINVAL;
316                 goto fail1;
317         }
318
319         (void) memset(payload, 0, sizeof (payload));
320         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
321         req.emr_in_buf = payload;
322         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
323         req.emr_out_buf = payload;
324         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
325
326         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
327             rss_context);
328
329         EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
330         if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
331                 rc = EINVAL;
332                 goto fail2;
333         }
334
335         memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
336             key, n);
337
338         efx_mcdi_execute(enp, &req);
339
340         if (req.emr_rc != 0) {
341                 rc = req.emr_rc;
342                 goto fail3;
343         }
344
345         return (0);
346
347 fail3:
348         EFSYS_PROBE(fail3);
349 fail2:
350         EFSYS_PROBE(fail2);
351 fail1:
352         EFSYS_PROBE1(fail1, int, rc);
353
354         return (rc);
355 }
356 #endif /* EFSYS_OPT_RX_SCALE */
357
358 #if EFSYS_OPT_RX_SCALE
359 static  int
360 efx_mcdi_rss_context_set_table(
361         __in            efx_nic_t *enp,
362         __in            uint32_t rss_context,
363         __in_ecount(n)  unsigned int *table,
364         __in            size_t n)
365 {
366         efx_mcdi_req_t req;
367         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
368                             MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN)];
369         uint8_t *req_table;
370         int i, rc;
371
372         if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) {
373                 rc = EINVAL;
374                 goto fail1;
375         }
376
377         (void) memset(payload, 0, sizeof (payload));
378         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
379         req.emr_in_buf = payload;
380         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
381         req.emr_out_buf = payload;
382         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
383
384         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
385             rss_context);
386
387         req_table =
388             MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
389
390         for (i = 0;
391             i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
392             i++) {
393                 req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0;
394         }
395
396         efx_mcdi_execute(enp, &req);
397
398         if (req.emr_rc != 0) {
399                 rc = req.emr_rc;
400                 goto fail2;
401         }
402
403         return (0);
404
405 fail2:
406         EFSYS_PROBE(fail2);
407 fail1:
408         EFSYS_PROBE1(fail1, int, rc);
409
410         return (rc);
411 }
412 #endif /* EFSYS_OPT_RX_SCALE */
413
414
415         __checkReturn   int
416 hunt_rx_init(
417         __in            efx_nic_t *enp)
418 {
419 #if EFSYS_OPT_RX_SCALE
420
421         if (efx_mcdi_rss_context_alloc(enp, &enp->en_rss_context) == 0) {
422                 /*
423                  * Allocated an exclusive RSS context, which allows both the
424                  * indirection table and key to be modified.
425                  */
426                 enp->en_rss_support = EFX_RX_SCALE_EXCLUSIVE;
427                 enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
428         } else {
429                 /*
430                  * Failed to allocate an exclusive RSS context. Continue
431                  * operation without support for RSS. The pseudo-header in
432                  * received packets will not contain a Toeplitz hash value.
433                  */
434                 enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE;
435                 enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
436         }
437
438 #endif /* EFSYS_OPT_RX_SCALE */
439
440         return (0);
441 }
442
443 #if EFSYS_OPT_RX_HDR_SPLIT
444         __checkReturn   int
445 hunt_rx_hdr_split_enable(
446         __in            efx_nic_t *enp,
447         __in            unsigned int hdr_buf_size,
448         __in            unsigned int pld_buf_size)
449 {
450         int rc;
451
452         /* FIXME */
453         _NOTE(ARGUNUSED(enp, hdr_buf_size, pld_buf_size))
454         if (B_FALSE) {
455                 rc = ENOTSUP;
456                 goto fail1;
457         }
458         /* FIXME */
459
460         return (0);
461
462 fail1:
463         EFSYS_PROBE1(fail1, int, rc);
464
465         return (rc);
466 }
467 #endif  /* EFSYS_OPT_RX_HDR_SPLIT */
468
469 #if EFSYS_OPT_RX_SCATTER
470         __checkReturn   int
471 hunt_rx_scatter_enable(
472         __in            efx_nic_t *enp,
473         __in            unsigned int buf_size)
474 {
475         _NOTE(ARGUNUSED(enp, buf_size))
476         return (0);
477 }
478 #endif  /* EFSYS_OPT_RX_SCATTER */
479
480 #if EFSYS_OPT_RX_SCALE
481         __checkReturn   int
482 hunt_rx_scale_mode_set(
483         __in            efx_nic_t *enp,
484         __in            efx_rx_hash_alg_t alg,
485         __in            efx_rx_hash_type_t type,
486         __in            boolean_t insert)
487 {
488         int rc;
489
490         EFSYS_ASSERT3U(alg, ==, EFX_RX_HASHALG_TOEPLITZ);
491         EFSYS_ASSERT3U(insert, ==, B_TRUE);
492
493         if ((alg != EFX_RX_HASHALG_TOEPLITZ) || (insert == B_FALSE)) {
494                 rc = EINVAL;
495                 goto fail1;
496         }
497
498         if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) {
499                 rc = ENOTSUP;
500                 goto fail2;
501         }
502
503         if ((rc = efx_mcdi_rss_context_set_flags(enp,
504                     enp->en_rss_context, type)) != 0)
505                 goto fail3;
506
507         return (0);
508
509 fail3:
510         EFSYS_PROBE(fail3);
511 fail2:
512         EFSYS_PROBE(fail2);
513 fail1:
514         EFSYS_PROBE1(fail1, int, rc);
515
516         return (rc);
517 }
518 #endif /* EFSYS_OPT_RX_SCALE */
519
520 #if EFSYS_OPT_RX_SCALE
521         __checkReturn   int
522 hunt_rx_scale_key_set(
523         __in            efx_nic_t *enp,
524         __in_ecount(n)  uint8_t *key,
525         __in            size_t n)
526 {
527         int rc;
528
529         if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) {
530                 rc = ENOTSUP;
531                 goto fail1;
532         }
533
534         if ((rc = efx_mcdi_rss_context_set_key(enp,
535             enp->en_rss_context, key, n)) != 0)
536                 goto fail2;
537
538         return (0);
539
540 fail2:
541         EFSYS_PROBE(fail2);
542 fail1:
543         EFSYS_PROBE1(fail1, int, rc);
544
545         return (rc);
546 }
547 #endif /* EFSYS_OPT_RX_SCALE */
548
549 #if EFSYS_OPT_RX_SCALE
550         __checkReturn   int
551 hunt_rx_scale_tbl_set(
552         __in            efx_nic_t *enp,
553         __in_ecount(n)  unsigned int *table,
554         __in            size_t n)
555 {
556         int rc;
557
558         if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) {
559                 rc = ENOTSUP;
560                 goto fail1;
561         }
562
563         if ((rc = efx_mcdi_rss_context_set_table(enp,
564             enp->en_rss_context, table, n)) != 0)
565                 goto fail2;
566
567         return (0);
568
569 fail2:
570         EFSYS_PROBE(fail2);
571 fail1:
572         EFSYS_PROBE1(fail1, int, rc);
573
574         return (rc);
575 }
576 #endif /* EFSYS_OPT_RX_SCALE */
577
578                         void
579 hunt_rx_qpost(
580         __in            efx_rxq_t *erp,
581         __in_ecount(n)  efsys_dma_addr_t *addrp,
582         __in            size_t size,
583         __in            unsigned int n,
584         __in            unsigned int completed,
585         __in            unsigned int added)
586 {
587         efx_qword_t qword;
588         unsigned int i;
589         unsigned int offset;
590         unsigned int id;
591
592         /* The client driver must not overfill the queue */
593         EFSYS_ASSERT3U(added - completed + n, <=,
594             EFX_RXQ_LIMIT(erp->er_mask + 1));
595
596         id = added & (erp->er_mask);
597         for (i = 0; i < n; i++) {
598                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
599                     unsigned int, id, efsys_dma_addr_t, addrp[i],
600                     size_t, size);
601
602                 EFX_POPULATE_QWORD_3(qword,
603                     ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
604                     ESF_DZ_RX_KER_BUF_ADDR_DW0,
605                     (uint32_t)(addrp[i] & 0xffffffff),
606                     ESF_DZ_RX_KER_BUF_ADDR_DW1,
607                     (uint32_t)(addrp[i] >> 32));
608
609                 offset = id * sizeof (efx_qword_t);
610                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
611
612                 id = (id + 1) & (erp->er_mask);
613         }
614 }
615
616                         void
617 hunt_rx_qpush(
618         __in    efx_rxq_t *erp,
619         __in    unsigned int added,
620         __inout unsigned int *pushedp)
621 {
622         efx_nic_t *enp = erp->er_enp;
623         unsigned int pushed = *pushedp;
624         uint32_t wptr;
625         efx_dword_t dword;
626
627         /* Hardware has alignment restriction for WPTR */
628         wptr = P2ALIGN(added, HUNTINGTON_RX_WPTR_ALIGN);
629         if (pushed == wptr)
630                 return;
631
632         *pushedp = wptr;
633
634         /* Push the populated descriptors out */
635         wptr &= erp->er_mask;
636
637         EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
638
639         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
640         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
641             wptr, pushed & erp->er_mask);
642         EFSYS_PIO_WRITE_BARRIER();
643         EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
644                             erp->er_index, &dword, B_FALSE);
645 }
646
647         __checkReturn   int
648 hunt_rx_qflush(
649         __in    efx_rxq_t *erp)
650 {
651         efx_nic_t *enp = erp->er_enp;
652         int rc;
653
654         if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
655                 goto fail1;
656
657         return (0);
658
659 fail1:
660         EFSYS_PROBE1(fail1, int, rc);
661
662         return (rc);
663 }
664
665                 void
666 hunt_rx_qenable(
667         __in    efx_rxq_t *erp)
668 {
669         /* FIXME */
670         _NOTE(ARGUNUSED(erp))
671         /* FIXME */
672 }
673
674         __checkReturn   int
675 hunt_rx_qcreate(
676         __in            efx_nic_t *enp,
677         __in            unsigned int index,
678         __in            unsigned int label,
679         __in            efx_rxq_type_t type,
680         __in            efsys_mem_t *esmp,
681         __in            size_t n,
682         __in            uint32_t id,
683         __in            efx_evq_t *eep,
684         __in            efx_rxq_t *erp)
685 {
686         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
687         int rc;
688
689         _NOTE(ARGUNUSED(erp))
690
691         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
692         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
693         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
694
695         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
696         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
697
698         if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
699                 rc = EINVAL;
700                 goto fail1;
701         }
702         if (index >= encp->enc_rxq_limit) {
703                 rc = EINVAL;
704                 goto fail2;
705         }
706
707         /*
708          * FIXME: Siena code handles different queue types (default, header
709          * split, scatter); we'll need to do something more here later, but
710          * all that stuff is TBD for now.
711          */
712
713         if ((rc = efx_mcdi_init_rxq(enp, n, eep->ee_index, label, index,
714             esmp)) != 0)
715                 goto fail3;
716
717         erp->er_eep = eep;
718         erp->er_label = label;
719
720         hunt_ev_rxlabel_init(eep, erp, label);
721
722         return (0);
723
724 fail3:
725         EFSYS_PROBE(fail3);
726 fail2:
727         EFSYS_PROBE(fail2);
728 fail1:
729         EFSYS_PROBE1(fail1, int, rc);
730
731         return (rc);
732 }
733
734                 void
735 hunt_rx_qdestroy(
736         __in    efx_rxq_t *erp)
737 {
738         efx_nic_t *enp = erp->er_enp;
739         efx_evq_t *eep = erp->er_eep;
740         unsigned int label = erp->er_label;
741
742         hunt_ev_rxlabel_fini(eep, label);
743
744         EFSYS_ASSERT(enp->en_rx_qcount != 0);
745         --enp->en_rx_qcount;
746
747         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
748 }
749
750                 void
751 hunt_rx_fini(
752         __in    efx_nic_t *enp)
753 {
754 #if EFSYS_OPT_RX_SCALE
755         if (enp->en_rss_support != EFX_RX_SCALE_UNAVAILABLE) {
756                 (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
757         }
758         enp->en_rss_context = 0;
759         enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE;
760 #else
761         _NOTE(ARGUNUSED(enp))
762 #endif /* EFSYS_OPT_RX_SCALE */
763 }
764
765 #endif /* EFSYS_OPT_HUNTINGTON */