]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bnxt/bnxt_txrx.c
MFV r310115,310184:
[FreeBSD/FreeBSD.git] / sys / dev / bnxt / bnxt_txrx.c
1 /*-
2  * Broadcom NetXtreme-C/E network driver.
3  *
4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/endian.h>
35 #include <net/if.h>
36 #include <net/if_var.h>
37 #include <net/ethernet.h>
38 #include <net/iflib.h>
39
40 #include "opt_inet.h"
41 #include "opt_inet6.h"
42 #include "opt_rss.h"
43
44 #include "bnxt.h"
45
46 /*
47  * Function prototypes
48  */
49
50 static int bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi);
51 static void bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx);
52 static int bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t cidx,
53     bool clear);
54
55 static void bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid,
56     uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs, uint16_t count,
57     uint16_t buf_size);
58 static void bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid,
59     uint32_t pidx);
60 static int bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx,
61     int budget);
62 static int bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri);
63
64 static int bnxt_intr(void *sc);
65
66 struct if_txrx bnxt_txrx  = {
67         bnxt_isc_txd_encap,
68         bnxt_isc_txd_flush,
69         bnxt_isc_txd_credits_update,
70         bnxt_isc_rxd_available,
71         bnxt_isc_rxd_pkt_get,
72         bnxt_isc_rxd_refill,
73         bnxt_isc_rxd_flush,
74         bnxt_intr
75 };
76
77 /*
78  * Device Dependent Packet Transmit and Receive Functions
79  */
80
81 static const uint16_t bnxt_tx_lhint[] = {
82         TX_BD_SHORT_FLAGS_LHINT_LT512,
83         TX_BD_SHORT_FLAGS_LHINT_LT1K,
84         TX_BD_SHORT_FLAGS_LHINT_LT2K,
85         TX_BD_SHORT_FLAGS_LHINT_LT2K,
86         TX_BD_SHORT_FLAGS_LHINT_GTE2K,
87 };
88
89 static int
90 bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
91 {
92         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
93         struct bnxt_ring *txr = &softc->tx_rings[pi->ipi_qsidx];
94         struct tx_bd_long *tbd;
95         struct tx_bd_long_hi *tbdh;
96         bool need_hi = false;
97         uint16_t flags_type;
98         uint16_t lflags;
99         uint32_t cfa_meta;
100         int seg = 0;
101
102         /* If we have offloads enabled, we need to use two BDs. */
103         if ((pi->ipi_csum_flags & (CSUM_OFFLOAD | CSUM_TSO | CSUM_IP)) ||
104             pi->ipi_mflags & M_VLANTAG)
105                 need_hi = true;
106
107         /* TODO: Devices before Cu+B1 need to not mix long and short BDs */
108         need_hi = true;
109
110         pi->ipi_new_pidx = pi->ipi_pidx;
111         tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx];
112         pi->ipi_ndescs = 0;
113         /* No need to byte-swap the opaque value */
114         tbd->opaque = ((pi->ipi_nsegs + need_hi) << 24) | pi->ipi_new_pidx;
115         tbd->len = htole16(pi->ipi_segs[seg].ds_len);
116         tbd->addr = htole64(pi->ipi_segs[seg++].ds_addr);
117         flags_type = ((pi->ipi_nsegs + need_hi) <<
118             TX_BD_SHORT_FLAGS_BD_CNT_SFT) & TX_BD_SHORT_FLAGS_BD_CNT_MASK;
119         if (pi->ipi_len >= 2048)
120                 flags_type |= TX_BD_SHORT_FLAGS_LHINT_GTE2K;
121         else
122                 flags_type |= bnxt_tx_lhint[pi->ipi_len >> 9];
123
124         if (need_hi) {
125                 flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG;
126
127                 pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
128                 tbdh = &((struct tx_bd_long_hi *)txr->vaddr)[pi->ipi_new_pidx];
129                 tbdh->mss = htole16(pi->ipi_tso_segsz);
130                 tbdh->hdr_size = htole16((pi->ipi_ehdrlen + pi->ipi_ip_hlen +
131                     pi->ipi_tcp_hlen) >> 1);
132                 tbdh->cfa_action = 0;
133                 lflags = 0;
134                 cfa_meta = 0;
135                 if (pi->ipi_mflags & M_VLANTAG) {
136                         /* TODO: Do we need to byte-swap the vtag here? */
137                         cfa_meta = TX_BD_LONG_CFA_META_KEY_VLAN_TAG |
138                             pi->ipi_vtag;
139                         cfa_meta |= TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100;
140                 }
141                 tbdh->cfa_meta = htole32(cfa_meta);
142                 if (pi->ipi_csum_flags & CSUM_TSO) {
143                         lflags |= TX_BD_LONG_LFLAGS_LSO |
144                             TX_BD_LONG_LFLAGS_T_IPID;
145                 }
146                 else if(pi->ipi_csum_flags & CSUM_OFFLOAD) {
147                         lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM |
148                             TX_BD_LONG_LFLAGS_IP_CHKSUM;
149                 }
150                 else if(pi->ipi_csum_flags & CSUM_IP) {
151                         lflags |= TX_BD_LONG_LFLAGS_IP_CHKSUM;
152                 }
153                 tbdh->lflags = htole16(lflags);
154         }
155         else {
156                 flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT;
157         }
158
159         for (; seg < pi->ipi_nsegs; seg++) {
160                 tbd->flags_type = htole16(flags_type);
161                 pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
162                 tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx];
163                 tbd->len = htole16(pi->ipi_segs[seg].ds_len);
164                 tbd->addr = htole64(pi->ipi_segs[seg].ds_addr);
165                 flags_type = TX_BD_SHORT_TYPE_TX_BD_SHORT;
166         }
167         flags_type |= TX_BD_SHORT_FLAGS_PACKET_END;
168         tbd->flags_type = htole16(flags_type);
169         pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
170
171         return 0;
172 }
173
174 static void
175 bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx)
176 {
177         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
178         struct bnxt_ring *tx_ring = &softc->tx_rings[txqid];
179
180         /* pidx is what we last set ipi_new_pidx to */
181         BNXT_TX_DB(tx_ring, pidx);
182         /* TODO: Cumulus+ doesn't need the double doorbell */
183         BNXT_TX_DB(tx_ring, pidx);
184         return;
185 }
186
187 static int
188 bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t idx, bool clear)
189 {
190         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
191         struct bnxt_cp_ring *cpr = &softc->tx_cp_rings[txqid];
192         struct tx_cmpl *cmpl = (struct tx_cmpl *)cpr->ring.vaddr;
193         int avail = 0;
194         uint32_t cons = cpr->cons;
195         bool v_bit = cpr->v_bit;
196         bool last_v_bit;
197         uint32_t last_cons;
198         uint16_t type;
199         uint16_t err;
200
201         for (;;) {
202                 last_cons = cons;
203                 last_v_bit = v_bit;
204                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
205                 CMPL_PREFETCH_NEXT(cpr, cons);
206
207                 if (!CMP_VALID(&cmpl[cons], v_bit))
208                         goto done;
209
210                 type = cmpl[cons].flags_type & TX_CMPL_TYPE_MASK;
211                 switch (type) {
212                 case TX_CMPL_TYPE_TX_L2:
213                         err = (le16toh(cmpl[cons].errors_v) &
214                             TX_CMPL_ERRORS_BUFFER_ERROR_MASK) >>
215                             TX_CMPL_ERRORS_BUFFER_ERROR_SFT;
216                         if (err)
217                                 device_printf(softc->dev,
218                                     "TX completion error %u\n", err);
219                         /* No need to byte-swap the opaque value */
220                         avail += cmpl[cons].opaque >> 24;
221                         /*
222                          * If we're not clearing, iflib only cares if there's
223                          * at least one buffer.  Don't scan the whole ring in
224                          * this case.
225                          */
226                         if (!clear)
227                                 goto done;
228                         break;
229                 default:
230                         if (type & 1) {
231                                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
232                                 if (!CMP_VALID(&cmpl[cons], v_bit))
233                                         goto done;
234                         }
235                         device_printf(softc->dev,
236                             "Unhandled TX completion type %u\n", type);
237                         break;
238                 }
239         }
240 done:
241
242         if (clear && avail) {
243                 cpr->cons = last_cons;
244                 cpr->v_bit = last_v_bit;
245                 BNXT_CP_IDX_DISABLE_DB(&cpr->ring, cpr->cons);
246         }
247
248         return avail;
249 }
250
251 static void
252 bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid,
253                                 uint32_t pidx, uint64_t *paddrs,
254                                 caddr_t *vaddrs, uint16_t count, uint16_t len)
255 {
256         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
257         struct bnxt_ring *rx_ring;
258         struct rx_prod_pkt_bd *rxbd;
259         uint16_t type;
260         uint16_t i;
261
262         if (flid == 0) {
263                 rx_ring = &softc->rx_rings[rxqid];
264                 type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT;
265         }
266         else {
267                 rx_ring = &softc->ag_rings[rxqid];
268                 type = RX_PROD_AGG_BD_TYPE_RX_PROD_AGG;
269         }
270         rxbd = (void *)rx_ring->vaddr;
271
272         for (i=0; i<count; i++) {
273                 rxbd[pidx].flags_type = htole16(type);
274                 rxbd[pidx].len = htole16(len);
275                 /* No need to byte-swap the opaque value */
276                 rxbd[pidx].opaque = ((rxqid & 0xff) << 24) | (flid << 16)
277                     | pidx;
278                 rxbd[pidx].addr = htole64(paddrs[i]);
279                 if (++pidx == rx_ring->ring_size)
280                         pidx = 0;
281         }
282         return;
283 }
284
285 static void
286 bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid,
287     uint32_t pidx)
288 {
289         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
290         struct bnxt_ring *rx_ring;
291
292         if (flid == 0)
293                 rx_ring = &softc->rx_rings[rxqid];
294         else
295                 rx_ring = &softc->ag_rings[rxqid];
296
297         /*
298          * We *must* update the completion ring before updating the RX ring
299          * or we will overrun the completion ring and the device will wedge for
300          * RX.
301          */
302         if (softc->rx_cp_rings[rxqid].cons != UINT32_MAX)
303                 BNXT_CP_IDX_DISABLE_DB(&softc->rx_cp_rings[rxqid].ring,
304                     softc->rx_cp_rings[rxqid].cons);
305         /* We're given the last filled RX buffer here, not the next empty one */
306         BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx));
307         /* TODO: Cumulus+ doesn't need the double doorbell */
308         BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx));
309         return;
310 }
311
312 static int
313 bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx, int budget)
314 {
315         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
316         struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[rxqid];
317         struct rx_pkt_cmpl *rcp;
318         struct rx_tpa_start_cmpl *rtpa;
319         struct rx_tpa_end_cmpl *rtpae;
320         struct cmpl_base *cmp = (struct cmpl_base *)cpr->ring.vaddr;
321         int avail = 0;
322         uint32_t cons = cpr->cons;
323         bool v_bit = cpr->v_bit;
324         uint8_t ags;
325         int i;
326         uint16_t type;
327         uint8_t agg_id;
328
329         for (;;) {
330                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
331                 CMPL_PREFETCH_NEXT(cpr, cons);
332
333                 if (!CMP_VALID(&cmp[cons], v_bit))
334                         goto cmpl_invalid;
335
336                 type = le16toh(cmp[cons].type) & CMPL_BASE_TYPE_MASK;
337                 switch (type) {
338                 case CMPL_BASE_TYPE_RX_L2:
339                         rcp = (void *)&cmp[cons];
340                         ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >>
341                             RX_PKT_CMPL_AGG_BUFS_SFT;
342                         NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
343                         CMPL_PREFETCH_NEXT(cpr, cons);
344
345                         if (!CMP_VALID(&cmp[cons], v_bit))
346                                 goto cmpl_invalid;
347
348                         /* Now account for all the AG completions */
349                         for (i=0; i<ags; i++) {
350                                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
351                                 CMPL_PREFETCH_NEXT(cpr, cons);
352                                 if (!CMP_VALID(&cmp[cons], v_bit))
353                                         goto cmpl_invalid;
354                         }
355                         avail++;
356                         break;
357                 case CMPL_BASE_TYPE_RX_TPA_END:
358                         rtpae = (void *)&cmp[cons];
359                         ags = (rtpae->agg_bufs_v1 &
360                             RX_TPA_END_CMPL_AGG_BUFS_MASK) >>
361                             RX_TPA_END_CMPL_AGG_BUFS_SFT;
362                         NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
363                         CMPL_PREFETCH_NEXT(cpr, cons);
364
365                         if (!CMP_VALID(&cmp[cons], v_bit))
366                                 goto cmpl_invalid;
367                         /* Now account for all the AG completions */
368                         for (i=0; i<ags; i++) {
369                                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
370                                 CMPL_PREFETCH_NEXT(cpr, cons);
371                                 if (!CMP_VALID(&cmp[cons], v_bit))
372                                         goto cmpl_invalid;
373                         }
374                         avail++;
375                         break;
376                 case CMPL_BASE_TYPE_RX_TPA_START:
377                         rtpa = (void *)&cmp[cons];
378                         agg_id = (rtpa->agg_id &
379                             RX_TPA_START_CMPL_AGG_ID_MASK) >>
380                             RX_TPA_START_CMPL_AGG_ID_SFT;
381                         softc->tpa_start[agg_id].low = *rtpa;
382                         NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
383                         CMPL_PREFETCH_NEXT(cpr, cons);
384
385                         if (!CMP_VALID(&cmp[cons], v_bit))
386                                 goto cmpl_invalid;
387                         softc->tpa_start[agg_id].high =
388                             ((struct rx_tpa_start_cmpl_hi *)cmp)[cons];
389                         break;
390                 case CMPL_BASE_TYPE_RX_AGG:
391                         break;
392                 default:
393                         device_printf(softc->dev,
394                             "Unhandled completion type %d on RXQ %d\n",
395                             type, rxqid);
396
397                         /* Odd completion types use two completions */
398                         if (type & 1) {
399                                 NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
400                                 CMPL_PREFETCH_NEXT(cpr, cons);
401
402                                 if (!CMP_VALID(&cmp[cons], v_bit))
403                                         goto cmpl_invalid;
404                         }
405                         break;
406                 }
407                 if (avail > budget)
408                         break;
409         }
410 cmpl_invalid:
411
412         return avail;
413 }
414
415 static int
416 bnxt_pkt_get_l2(struct bnxt_softc *softc, if_rxd_info_t ri,
417     struct bnxt_cp_ring *cpr, uint16_t flags_type)
418 {
419         struct rx_pkt_cmpl *rcp;
420         struct rx_pkt_cmpl_hi *rcph;
421         struct rx_abuf_cmpl *acp;
422         uint32_t flags2;
423         uint32_t errors;
424         uint8_t ags;
425         int i;
426
427         rcp = &((struct rx_pkt_cmpl *)cpr->ring.vaddr)[cpr->cons];
428
429         /* Extract from the first 16-byte BD */
430         if (flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
431                 ri->iri_flowid = le32toh(rcp->rss_hash);
432                 /*
433                  * TODO: Extract something useful from rcp->rss_hash_type
434                  * (undocumented)
435                  * May be documented in the "LSI ES"
436                  * also check the firmware code.
437                  */
438                 ri->iri_rsstype = M_HASHTYPE_OPAQUE;
439         }
440         else {
441                 ri->iri_rsstype = M_HASHTYPE_NONE;
442         }
443         ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >>
444             RX_PKT_CMPL_AGG_BUFS_SFT;
445         ri->iri_nfrags = ags + 1;
446         /* No need to byte-swap the opaque value */
447         ri->iri_frags[0].irf_flid = (rcp->opaque >> 16) & 0xff;
448         ri->iri_frags[0].irf_idx = rcp->opaque & 0xffff;
449         ri->iri_frags[0].irf_len = le16toh(rcp->len);
450         ri->iri_len = le16toh(rcp->len);
451
452         /* Now the second 16-byte BD */
453         NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
454         ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
455         rcph = &((struct rx_pkt_cmpl_hi *)cpr->ring.vaddr)[cpr->cons];
456
457         flags2 = le32toh(rcph->flags2);
458         errors = le16toh(rcph->errors_v2);
459         if ((flags2 & RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK) ==
460             RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN) {
461                 ri->iri_flags |= M_VLANTAG;
462                 /* TODO: Should this be the entire 16-bits? */
463                 ri->iri_vtag = le32toh(rcph->metadata) &
464                     (RX_PKT_CMPL_METADATA_VID_MASK | RX_PKT_CMPL_METADATA_DE |
465                     RX_PKT_CMPL_METADATA_PRI_MASK);
466         }
467         if (flags2 & RX_PKT_CMPL_FLAGS2_IP_CS_CALC) {
468                 ri->iri_csum_flags |= CSUM_IP_CHECKED;
469                 if (!(errors & RX_PKT_CMPL_ERRORS_IP_CS_ERROR))
470                         ri->iri_csum_flags |= CSUM_IP_VALID;
471         }
472         if (flags2 & RX_PKT_CMPL_FLAGS2_L4_CS_CALC) {
473                 ri->iri_csum_flags |= CSUM_L4_CALC;
474                 if (!(errors & RX_PKT_CMPL_ERRORS_L4_CS_ERROR)) {
475                         ri->iri_csum_flags |= CSUM_L4_VALID;
476                         ri->iri_csum_data = 0xffff;
477                 }
478         }
479
480         /* And finally the ag ring stuff. */
481         for (i=1; i < ri->iri_nfrags; i++) {
482                 NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
483                 ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
484                 acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons];
485
486                 /* No need to byte-swap the opaque value */
487                 ri->iri_frags[i].irf_flid = (acp->opaque >> 16 & 0xff);
488                 ri->iri_frags[i].irf_idx = acp->opaque & 0xffff;
489                 ri->iri_frags[i].irf_len = le16toh(acp->len);
490                 ri->iri_len += le16toh(acp->len);
491         }
492
493         return 0;
494 }
495
496 static int
497 bnxt_pkt_get_tpa(struct bnxt_softc *softc, if_rxd_info_t ri,
498     struct bnxt_cp_ring *cpr, uint16_t flags_type)
499 {
500         struct rx_tpa_end_cmpl *agend =
501             &((struct rx_tpa_end_cmpl *)cpr->ring.vaddr)[cpr->cons];
502         struct rx_tpa_end_cmpl_hi *agendh;
503         struct rx_abuf_cmpl *acp;
504         struct bnxt_full_tpa_start *tpas;
505         uint32_t flags2;
506         uint8_t ags;
507         uint8_t agg_id;
508         int i;
509
510         /* Get the agg_id */
511         agg_id = (agend->agg_id & RX_TPA_END_CMPL_AGG_ID_MASK) >>
512             RX_TPA_END_CMPL_AGG_ID_SFT;
513         tpas = &softc->tpa_start[agg_id];
514
515         /* Extract from the first 16-byte BD */
516         if (le16toh(tpas->low.flags_type) & RX_TPA_START_CMPL_FLAGS_RSS_VALID) {
517                 ri->iri_flowid = le32toh(tpas->low.rss_hash);
518                 /*
519                  * TODO: Extract something useful from tpas->low.rss_hash_type
520                  * (undocumented)
521                  * May be documented in the "LSI ES"
522                  * also check the firmware code.
523                  */
524                 ri->iri_rsstype = M_HASHTYPE_OPAQUE;
525         }
526         else {
527                 ri->iri_rsstype = M_HASHTYPE_NONE;
528         }
529         ags = (agend->agg_bufs_v1 & RX_TPA_END_CMPL_AGG_BUFS_MASK) >>
530             RX_TPA_END_CMPL_AGG_BUFS_SFT;
531         ri->iri_nfrags = ags + 1;
532         /* No need to byte-swap the opaque value */
533         ri->iri_frags[0].irf_flid = (tpas->low.opaque >> 16) & 0xff;
534         ri->iri_frags[0].irf_idx = tpas->low.opaque & 0xffff;
535         ri->iri_frags[0].irf_len = le16toh(tpas->low.len);
536         ri->iri_len = le16toh(tpas->low.len);
537
538         /* Now the second 16-byte BD */
539         NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
540         ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
541         agendh = &((struct rx_tpa_end_cmpl_hi *)cpr->ring.vaddr)[cpr->cons];
542
543         flags2 = le32toh(tpas->high.flags2);
544         if ((flags2 & RX_TPA_START_CMPL_FLAGS2_META_FORMAT_MASK) ==
545             RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN) {
546                 ri->iri_flags |= M_VLANTAG;
547                 /* TODO: Should this be the entire 16-bits? */
548                 ri->iri_vtag = le32toh(tpas->high.metadata) &
549                     (RX_TPA_START_CMPL_METADATA_VID_MASK |
550                     RX_TPA_START_CMPL_METADATA_DE |
551                     RX_TPA_START_CMPL_METADATA_PRI_MASK);
552         }
553         if (flags2 & RX_TPA_START_CMPL_FLAGS2_IP_CS_CALC) {
554                 ri->iri_csum_flags |= CSUM_IP_CHECKED;
555                 ri->iri_csum_flags |= CSUM_IP_VALID;
556         }
557         if (flags2 & RX_TPA_START_CMPL_FLAGS2_L4_CS_CALC) {
558                 ri->iri_csum_flags |= CSUM_L4_CALC;
559                 ri->iri_csum_flags |= CSUM_L4_VALID;
560                 ri->iri_csum_data = 0xffff;
561         }
562
563         /* Now the ag ring stuff. */
564         for (i=1; i < ri->iri_nfrags; i++) {
565                 NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
566                 ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
567                 acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons];
568
569                 /* No need to byte-swap the opaque value */
570                 ri->iri_frags[i].irf_flid = (acp->opaque >> 16) & 0xff;
571                 ri->iri_frags[i].irf_idx = acp->opaque & 0xffff;
572                 ri->iri_frags[i].irf_len = le16toh(acp->len);
573                 ri->iri_len += le16toh(acp->len);
574         }
575
576         /* And finally, the empty BD at the end... */
577         ri->iri_nfrags++;
578         /* No need to byte-swap the opaque value */
579         ri->iri_frags[i].irf_flid = (agend->opaque >> 16) % 0xff;
580         ri->iri_frags[i].irf_idx = agend->opaque & 0xffff;
581         ri->iri_frags[i].irf_len = le16toh(agend->len);
582         ri->iri_len += le16toh(agend->len);
583
584         return 0;
585 }
586
587 /* If we return anything but zero, iflib will assert... */
588 static int
589 bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri)
590 {
591         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
592         struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[ri->iri_qsidx];
593         struct cmpl_base *cmp;
594         uint16_t flags_type;
595         uint16_t type;
596
597         for (;;) {
598                 NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
599                 ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
600                 CMPL_PREFETCH_NEXT(cpr, cpr->cons);
601                 cmp = &((struct cmpl_base *)cpr->ring.vaddr)[cpr->cons];
602
603                 flags_type = le16toh(cmp->type);
604                 type = flags_type & CMPL_BASE_TYPE_MASK;
605
606                 switch (type) {
607                 case CMPL_BASE_TYPE_RX_L2:
608                         return bnxt_pkt_get_l2(softc, ri, cpr, flags_type);
609                 case CMPL_BASE_TYPE_RX_TPA_END:
610                         return bnxt_pkt_get_tpa(softc, ri, cpr, flags_type);
611                 case CMPL_BASE_TYPE_RX_TPA_START:
612                         NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
613                         ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
614                         CMPL_PREFETCH_NEXT(cpr, cpr->cons);
615                         break;
616                 default:
617                         device_printf(softc->dev,
618                             "Unhandled completion type %d on RXQ %d get\n",
619                             type, ri->iri_qsidx);
620                         if (type & 1) {
621                                 NEXT_CP_CONS_V(&cpr->ring, cpr->cons,
622                                     cpr->v_bit);
623                                 ri->iri_cidx = RING_NEXT(&cpr->ring,
624                                     ri->iri_cidx);
625                                 CMPL_PREFETCH_NEXT(cpr, cpr->cons);
626                         }
627                         break;
628                 }
629         }
630
631         return 0;
632 }
633
634 static int
635 bnxt_intr(void *sc)
636 {
637         struct bnxt_softc *softc = (struct bnxt_softc *)sc;
638
639         device_printf(softc->dev, "STUB: %s @ %s:%d\n", __func__, __FILE__, __LINE__);
640         return ENOSYS;
641 }