1 /******************************************************************************
3 Copyright (c) 2013-2018, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 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.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ******************************************************************************/
35 ** IXL driver TX/RX Routines:
36 ** This was seperated to allow usage by
37 ** both the PF and VF drivers.
40 #ifndef IXL_STANDALONE_BUILD
42 #include "opt_inet6.h"
49 #include <net/rss_config.h>
52 /* Local Prototypes */
53 static u8
ixl_rx_checksum(if_rxd_info_t ri
, u32 status
, u32 error
, u8 ptype
);
55 static int ixl_isc_txd_encap(void *arg
, if_pkt_info_t pi
);
56 static void ixl_isc_txd_flush(void *arg
, uint16_t txqid
, qidx_t pidx
);
57 static int ixl_isc_txd_credits_update_hwb(void *arg
, uint16_t txqid
, bool clear
);
58 static int ixl_isc_txd_credits_update_dwb(void *arg
, uint16_t txqid
, bool clear
);
60 static void ixl_isc_rxd_refill(void *arg
, if_rxd_update_t iru
);
61 static void ixl_isc_rxd_flush(void *arg
, uint16_t rxqid
, uint8_t flid __unused
,
63 static int ixl_isc_rxd_available(void *arg
, uint16_t rxqid
, qidx_t idx
,
65 static int ixl_isc_rxd_pkt_get(void *arg
, if_rxd_info_t ri
);
67 struct if_txrx ixl_txrx_hwb
= {
70 ixl_isc_txd_credits_update_hwb
,
71 ixl_isc_rxd_available
,
78 struct if_txrx ixl_txrx_dwb
= {
81 ixl_isc_txd_credits_update_dwb
,
82 ixl_isc_rxd_available
,
90 * @key key is saved into this parameter
93 ixl_get_default_rss_key(u32
*key
)
97 u32 rss_seed
[IXL_RSS_KEY_SIZE_REG
] = {0x41b01687,
98 0x183cfd8c, 0xce880440, 0x580cbc3c,
99 0x35897377, 0x328b25e1, 0x4fa98922,
100 0xb7d90c14, 0xd5bad70d, 0xcd15a2c1,
103 bcopy(rss_seed
, key
, IXL_RSS_KEY_SIZE
);
107 * i40e_vc_stat_str - convert virtchnl status err code to a string
108 * @hw: pointer to the HW structure
109 * @stat_err: the status error code to convert
112 i40e_vc_stat_str(struct i40e_hw
*hw
, enum virtchnl_status_code stat_err
)
115 case VIRTCHNL_STATUS_SUCCESS
:
117 case VIRTCHNL_ERR_PARAM
:
118 return "VIRTCHNL_ERR_PARAM";
119 case VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH
:
120 return "VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH";
121 case VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR
:
122 return "VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR";
123 case VIRTCHNL_STATUS_ERR_INVALID_VF_ID
:
124 return "VIRTCHNL_STATUS_ERR_INVALID_VF_ID";
125 case VIRTCHNL_STATUS_NOT_SUPPORTED
:
126 return "VIRTCHNL_STATUS_NOT_SUPPORTED";
129 snprintf(hw
->err_str
, sizeof(hw
->err_str
), "%d", stat_err
);
134 ixl_debug_core(device_t dev
, u32 enabled_mask
, u32 mask
, char *fmt
, ...)
138 if (!(mask
& enabled_mask
))
141 /* Re-implement device_printf() */
142 device_print_prettyname(dev
);
149 ixl_is_tx_desc_done(struct tx_ring
*txr
, int idx
)
151 return (((txr
->tx_base
[idx
].cmd_type_offset_bsz
>> I40E_TXD_QW1_DTYPE_SHIFT
)
152 & I40E_TXD_QW1_DTYPE_MASK
) == I40E_TX_DESC_DTYPE_DESC_DONE
);
156 ixl_tso_detect_sparse(bus_dma_segment_t
*segs
, int nsegs
, if_pkt_info_t pi
)
158 int count
, curseg
, i
, hlen
, segsz
, seglen
, tsolen
;
160 if (nsegs
<= IXL_MAX_TX_SEGS
-2)
162 segsz
= pi
->ipi_tso_segsz
;
165 hlen
= pi
->ipi_ehdrlen
+ pi
->ipi_ip_hlen
+ pi
->ipi_tcp_hlen
;
166 tsolen
= pi
->ipi_len
- hlen
;
169 curseg
= segs
[0].ds_len
;
172 if (count
> IXL_MAX_TX_SEGS
- 2)
176 if (__predict_false(i
== nsegs
))
179 curseg
= segs
[i
].ds_len
;
181 seglen
= min(curseg
, hlen
);
184 // printf("H:seglen = %d, count=%d\n", seglen, count);
187 segsz
= pi
->ipi_tso_segsz
;
188 while (segsz
> 0 && tsolen
!= 0) {
190 if (count
> IXL_MAX_TX_SEGS
- 2) {
191 // printf("bad: count = %d\n", count);
196 if (__predict_false(i
== nsegs
)) {
197 // printf("bad: tsolen = %d", tsolen);
200 curseg
= segs
[i
].ds_len
;
202 seglen
= min(curseg
, segsz
);
206 // printf("D:seglen = %d, count=%d\n", seglen, count);
214 /*********************************************************************
216 * Setup descriptor for hw offloads
218 **********************************************************************/
221 ixl_tx_setup_offload(struct ixl_tx_queue
*que
,
222 if_pkt_info_t pi
, u32
*cmd
, u32
*off
)
224 switch (pi
->ipi_etype
) {
227 if (pi
->ipi_csum_flags
& IXL_CSUM_IPV4
)
228 *cmd
|= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM
;
230 *cmd
|= I40E_TX_DESC_CMD_IIPT_IPV4
;
235 *cmd
|= I40E_TX_DESC_CMD_IIPT_IPV6
;
242 *off
|= (pi
->ipi_ehdrlen
>> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT
;
243 *off
|= (pi
->ipi_ip_hlen
>> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT
;
245 switch (pi
->ipi_ipproto
) {
247 if (pi
->ipi_csum_flags
& IXL_CSUM_TCP
) {
248 *cmd
|= I40E_TX_DESC_CMD_L4T_EOFT_TCP
;
249 *off
|= (pi
->ipi_tcp_hlen
>> 2) <<
250 I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT
;
251 /* Check for NO_HEAD MDD event */
252 MPASS(pi
->ipi_tcp_hlen
!= 0);
256 if (pi
->ipi_csum_flags
& IXL_CSUM_UDP
) {
257 *cmd
|= I40E_TX_DESC_CMD_L4T_EOFT_UDP
;
258 *off
|= (sizeof(struct udphdr
) >> 2) <<
259 I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT
;
263 if (pi
->ipi_csum_flags
& IXL_CSUM_SCTP
) {
264 *cmd
|= I40E_TX_DESC_CMD_L4T_EOFT_SCTP
;
265 *off
|= (sizeof(struct sctphdr
) >> 2) <<
266 I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT
;
274 /**********************************************************************
276 * Setup context for hardware segmentation offload (TSO)
278 **********************************************************************/
280 ixl_tso_setup(struct tx_ring
*txr
, if_pkt_info_t pi
)
282 if_softc_ctx_t scctx
;
283 struct i40e_tx_context_desc
*TXD
;
284 u32 cmd
, mss
, type
, tsolen
;
285 int idx
, total_hdr_len
;
286 u64 type_cmd_tso_mss
;
289 TXD
= (struct i40e_tx_context_desc
*) &txr
->tx_base
[idx
];
290 total_hdr_len
= pi
->ipi_ehdrlen
+ pi
->ipi_ip_hlen
+ pi
->ipi_tcp_hlen
;
291 tsolen
= pi
->ipi_len
- total_hdr_len
;
292 scctx
= txr
->que
->vsi
->shared
;
294 type
= I40E_TX_DESC_DTYPE_CONTEXT
;
295 cmd
= I40E_TX_CTX_DESC_TSO
;
297 * TSO MSS must not be less than 64; this prevents a
298 * BAD_LSO_MSS MDD event when the MSS is too small.
300 if (pi
->ipi_tso_segsz
< IXL_MIN_TSO_MSS
) {
301 txr
->mss_too_small
++;
302 pi
->ipi_tso_segsz
= IXL_MIN_TSO_MSS
;
304 mss
= pi
->ipi_tso_segsz
;
306 /* Check for BAD_LS0_MSS MDD event (mss too large) */
307 MPASS(mss
<= IXL_MAX_TSO_MSS
);
308 /* Check for NO_HEAD MDD event (header lengths are 0) */
309 MPASS(pi
->ipi_ehdrlen
!= 0);
310 MPASS(pi
->ipi_ip_hlen
!= 0);
311 /* Partial check for BAD_LSO_LEN MDD event */
313 /* Partial check for WRONG_SIZE MDD event (during TSO) */
314 MPASS(total_hdr_len
+ mss
<= IXL_MAX_FRAME
);
316 type_cmd_tso_mss
= ((u64
)type
<< I40E_TXD_CTX_QW1_DTYPE_SHIFT
) |
317 ((u64
)cmd
<< I40E_TXD_CTX_QW1_CMD_SHIFT
) |
318 ((u64
)tsolen
<< I40E_TXD_CTX_QW1_TSO_LEN_SHIFT
) |
319 ((u64
)mss
<< I40E_TXD_CTX_QW1_MSS_SHIFT
);
320 TXD
->type_cmd_tso_mss
= htole64(type_cmd_tso_mss
);
322 TXD
->tunneling_params
= htole32(0);
325 return ((idx
+ 1) & (scctx
->isc_ntxd
[0]-1));
328 /*********************************************************************
330 * This routine maps the mbufs to tx descriptors, allowing the
331 * TX engine to transmit the packets.
332 * - return 0 on success, positive on failure
334 **********************************************************************/
335 #define IXL_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
338 ixl_isc_txd_encap(void *arg
, if_pkt_info_t pi
)
340 struct ixl_vsi
*vsi
= arg
;
341 if_softc_ctx_t scctx
= vsi
->shared
;
342 struct ixl_tx_queue
*que
= &vsi
->tx_queues
[pi
->ipi_qsidx
];
343 struct tx_ring
*txr
= &que
->txr
;
344 int nsegs
= pi
->ipi_nsegs
;
345 bus_dma_segment_t
*segs
= pi
->ipi_segs
;
346 struct i40e_tx_desc
*txd
= NULL
;
347 int i
, j
, mask
, pidx_last
;
348 u32 cmd
, off
, tx_intr
;
353 tx_intr
= (pi
->ipi_flags
& IPI_TX_INTR
);
355 /* Set up the TSO/CSUM offload */
356 if (pi
->ipi_csum_flags
& CSUM_OFFLOAD
) {
357 /* Set up the TSO context descriptor if required */
358 if (pi
->ipi_csum_flags
& CSUM_TSO
) {
359 /* Prevent MAX_BUFF MDD event (for TSO) */
360 if (ixl_tso_detect_sparse(segs
, nsegs
, pi
))
362 i
= ixl_tso_setup(txr
, pi
);
364 ixl_tx_setup_offload(que
, pi
, &cmd
, &off
);
366 if (pi
->ipi_mflags
& M_VLANTAG
)
367 cmd
|= I40E_TX_DESC_CMD_IL2TAG1
;
369 cmd
|= I40E_TX_DESC_CMD_ICRC
;
370 mask
= scctx
->isc_ntxd
[0] - 1;
371 /* Check for WRONG_SIZE MDD event */
372 MPASS(pi
->ipi_len
>= IXL_MIN_FRAME
);
374 if (!(pi
->ipi_csum_flags
& CSUM_TSO
))
375 MPASS(pi
->ipi_len
<= IXL_MAX_FRAME
);
377 for (j
= 0; j
< nsegs
; j
++) {
380 txd
= &txr
->tx_base
[i
];
381 seglen
= segs
[j
].ds_len
;
383 /* Check for ZERO_BSIZE MDD event */
386 txd
->buffer_addr
= htole64(segs
[j
].ds_addr
);
387 txd
->cmd_type_offset_bsz
=
388 htole64(I40E_TX_DESC_DTYPE_DATA
389 | ((u64
)cmd
<< I40E_TXD_QW1_CMD_SHIFT
)
390 | ((u64
)off
<< I40E_TXD_QW1_OFFSET_SHIFT
)
391 | ((u64
)seglen
<< I40E_TXD_QW1_TX_BUF_SZ_SHIFT
)
392 | ((u64
)htole16(pi
->ipi_vtag
) << I40E_TXD_QW1_L2TAG1_SHIFT
));
394 txr
->tx_bytes
+= seglen
;
398 /* Set the last descriptor for report */
399 txd
->cmd_type_offset_bsz
|=
400 htole64(((u64
)IXL_TXD_CMD
<< I40E_TXD_QW1_CMD_SHIFT
));
401 /* Add to report status array (if using TX interrupts) */
402 if (!vsi
->enable_head_writeback
&& tx_intr
) {
403 txr
->tx_rsq
[txr
->tx_rs_pidx
] = pidx_last
;
404 txr
->tx_rs_pidx
= (txr
->tx_rs_pidx
+1) & mask
;
405 MPASS(txr
->tx_rs_pidx
!= txr
->tx_rs_cidx
);
407 pi
->ipi_new_pidx
= i
;
414 ixl_isc_txd_flush(void *arg
, uint16_t txqid
, qidx_t pidx
)
416 struct ixl_vsi
*vsi
= arg
;
417 struct tx_ring
*txr
= &vsi
->tx_queues
[txqid
].txr
;
420 * Advance the Transmit Descriptor Tail (Tdt), this tells the
421 * hardware that this frame is available to transmit.
423 /* Check for ENDLESS_TX MDD event */
424 MPASS(pidx
< vsi
->shared
->isc_ntxd
[0]);
425 wr32(vsi
->hw
, txr
->tail
, pidx
);
429 /*********************************************************************
431 * (Re)Initialize a queue transmit ring by clearing its memory.
433 **********************************************************************/
435 ixl_init_tx_ring(struct ixl_vsi
*vsi
, struct ixl_tx_queue
*que
)
437 struct tx_ring
*txr
= &que
->txr
;
439 /* Clear the old ring contents */
440 bzero((void *)txr
->tx_base
,
441 (sizeof(struct i40e_tx_desc
)) *
442 (vsi
->shared
->isc_ntxd
[0] + (vsi
->enable_head_writeback
? 1 : 0)));
444 wr32(vsi
->hw
, txr
->tail
, 0);
448 * ixl_get_tx_head - Retrieve the value from the
449 * location the HW records its HEAD index
452 ixl_get_tx_head(struct ixl_tx_queue
*que
)
454 if_softc_ctx_t scctx
= que
->vsi
->shared
;
455 struct tx_ring
*txr
= &que
->txr
;
456 void *head
= &txr
->tx_base
[scctx
->isc_ntxd
[0]];
458 return LE32_TO_CPU(*(volatile __le32
*)head
);
462 ixl_isc_txd_credits_update_hwb(void *arg
, uint16_t qid
, bool clear
)
464 struct ixl_vsi
*vsi
= arg
;
465 if_softc_ctx_t scctx
= vsi
->shared
;
466 struct ixl_tx_queue
*que
= &vsi
->tx_queues
[qid
];
467 struct tx_ring
*txr
= &que
->txr
;
470 /* Get the Head WB value */
471 head
= ixl_get_tx_head(que
);
473 credits
= head
- txr
->tx_cidx_processed
;
475 credits
+= scctx
->isc_ntxd
[0];
477 txr
->tx_cidx_processed
= head
;
483 ixl_isc_txd_credits_update_dwb(void *arg
, uint16_t txqid
, bool clear
)
485 struct ixl_vsi
*vsi
= arg
;
486 struct ixl_tx_queue
*tx_que
= &vsi
->tx_queues
[txqid
];
487 if_softc_ctx_t scctx
= vsi
->shared
;
488 struct tx_ring
*txr
= &tx_que
->txr
;
490 qidx_t processed
= 0;
491 qidx_t cur
, prev
, ntxd
, rs_cidx
;
495 rs_cidx
= txr
->tx_rs_cidx
;
497 device_printf(iflib_get_dev(vsi
->ctx
), "%s: (q%d) rs_cidx %d, txr->tx_rs_pidx %d\n", __func__
,
498 txr
->me
, rs_cidx
, txr
->tx_rs_pidx
);
500 if (rs_cidx
== txr
->tx_rs_pidx
)
502 cur
= txr
->tx_rsq
[rs_cidx
];
503 MPASS(cur
!= QIDX_INVALID
);
504 is_done
= ixl_is_tx_desc_done(txr
, cur
);
509 /* If clear is false just let caller know that there
510 * are descriptors to reclaim */
514 prev
= txr
->tx_cidx_processed
;
515 ntxd
= scctx
->isc_ntxd
[0];
518 delta
= (int32_t)cur
- (int32_t)prev
;
523 device_printf(iflib_get_dev(vsi
->ctx
),
524 "%s: (q%d) cidx_processed=%u cur=%u clear=%d delta=%d\n",
525 __func__
, txr
->me
, prev
, cur
, clear
, delta
);
529 rs_cidx
= (rs_cidx
+ 1) & (ntxd
-1);
530 if (rs_cidx
== txr
->tx_rs_pidx
)
532 cur
= txr
->tx_rsq
[rs_cidx
];
533 MPASS(cur
!= QIDX_INVALID
);
534 is_done
= ixl_is_tx_desc_done(txr
, cur
);
537 txr
->tx_rs_cidx
= rs_cidx
;
538 txr
->tx_cidx_processed
= prev
;
541 device_printf(iflib_get_dev(vsi
->ctx
), "%s: (q%d) processed %d\n", __func__
, txr
->me
, processed
);
547 ixl_isc_rxd_refill(void *arg
, if_rxd_update_t iru
)
549 struct ixl_vsi
*vsi
= arg
;
550 if_softc_ctx_t scctx
= vsi
->shared
;
551 struct rx_ring
*rxr
= &((vsi
->rx_queues
[iru
->iru_qsidx
]).rxr
);
553 uint32_t next_pidx
, pidx
;
557 paddrs
= iru
->iru_paddrs
;
558 pidx
= iru
->iru_pidx
;
559 count
= iru
->iru_count
;
561 for (i
= 0, next_pidx
= pidx
; i
< count
; i
++) {
562 rxr
->rx_base
[next_pidx
].read
.pkt_addr
= htole64(paddrs
[i
]);
563 if (++next_pidx
== scctx
->isc_nrxd
[0])
569 ixl_isc_rxd_flush(void * arg
, uint16_t rxqid
, uint8_t flid __unused
, qidx_t pidx
)
571 struct ixl_vsi
*vsi
= arg
;
572 struct rx_ring
*rxr
= &vsi
->rx_queues
[rxqid
].rxr
;
574 wr32(vsi
->hw
, rxr
->tail
, pidx
);
578 ixl_isc_rxd_available(void *arg
, uint16_t rxqid
, qidx_t idx
, qidx_t budget
)
580 struct ixl_vsi
*vsi
= arg
;
581 struct rx_ring
*rxr
= &vsi
->rx_queues
[rxqid
].rxr
;
582 union i40e_rx_desc
*rxd
;
587 nrxd
= vsi
->shared
->isc_nrxd
[0];
589 for (cnt
= 0, i
= idx
; cnt
< nrxd
- 1 && cnt
<= budget
;) {
590 rxd
= &rxr
->rx_base
[i
];
591 qword
= le64toh(rxd
->wb
.qword1
.status_error_len
);
592 status
= (qword
& I40E_RXD_QW1_STATUS_MASK
)
593 >> I40E_RXD_QW1_STATUS_SHIFT
;
595 if ((status
& (1 << I40E_RX_DESC_STATUS_DD_SHIFT
)) == 0)
599 if (status
& (1 << I40E_RX_DESC_STATUS_EOF_SHIFT
))
607 ** i40e_ptype_to_hash: parse the packet type
608 ** to determine the appropriate hash.
611 ixl_ptype_to_hash(u8 ptype
)
613 struct i40e_rx_ptype_decoded decoded
;
615 decoded
= decode_rx_desc_ptype(ptype
);
618 return M_HASHTYPE_OPAQUE
;
620 if (decoded
.outer_ip
== I40E_RX_PTYPE_OUTER_L2
)
621 return M_HASHTYPE_OPAQUE
;
623 /* Note: anything that gets to this point is IP */
624 if (decoded
.outer_ip_ver
== I40E_RX_PTYPE_OUTER_IPV6
) {
625 switch (decoded
.inner_prot
) {
626 case I40E_RX_PTYPE_INNER_PROT_TCP
:
627 return M_HASHTYPE_RSS_TCP_IPV6
;
628 case I40E_RX_PTYPE_INNER_PROT_UDP
:
629 return M_HASHTYPE_RSS_UDP_IPV6
;
631 return M_HASHTYPE_RSS_IPV6
;
634 if (decoded
.outer_ip_ver
== I40E_RX_PTYPE_OUTER_IPV4
) {
635 switch (decoded
.inner_prot
) {
636 case I40E_RX_PTYPE_INNER_PROT_TCP
:
637 return M_HASHTYPE_RSS_TCP_IPV4
;
638 case I40E_RX_PTYPE_INNER_PROT_UDP
:
639 return M_HASHTYPE_RSS_UDP_IPV4
;
641 return M_HASHTYPE_RSS_IPV4
;
644 /* We should never get here!! */
645 return M_HASHTYPE_OPAQUE
;
648 /*********************************************************************
650 * This routine executes in ithread context. It sends data which has been
651 * dma'ed into host memory to upper layer.
653 * Returns 0 upon success, errno on failure
655 *********************************************************************/
657 ixl_isc_rxd_pkt_get(void *arg
, if_rxd_info_t ri
)
659 struct ixl_vsi
*vsi
= arg
;
660 if_softc_ctx_t scctx
= vsi
->shared
;
661 struct ixl_rx_queue
*que
= &vsi
->rx_queues
[ri
->iri_qsidx
];
662 struct rx_ring
*rxr
= &que
->rxr
;
663 union i40e_rx_desc
*cur
;
674 /* 5 descriptor receive limit */
675 MPASS(i
< IXL_MAX_RX_SEGS
);
677 cur
= &rxr
->rx_base
[cidx
];
678 qword
= le64toh(cur
->wb
.qword1
.status_error_len
);
679 status
= (qword
& I40E_RXD_QW1_STATUS_MASK
)
680 >> I40E_RXD_QW1_STATUS_SHIFT
;
681 error
= (qword
& I40E_RXD_QW1_ERROR_MASK
)
682 >> I40E_RXD_QW1_ERROR_SHIFT
;
683 plen
= (qword
& I40E_RXD_QW1_LENGTH_PBUF_MASK
)
684 >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT
;
685 ptype
= (qword
& I40E_RXD_QW1_PTYPE_MASK
)
686 >> I40E_RXD_QW1_PTYPE_SHIFT
;
688 /* we should never be called without a valid descriptor */
689 MPASS((status
& (1 << I40E_RX_DESC_STATUS_DD_SHIFT
)) != 0);
692 rxr
->rx_bytes
+= plen
;
694 cur
->wb
.qword1
.status_error_len
= 0;
695 eop
= (status
& (1 << I40E_RX_DESC_STATUS_EOF_SHIFT
));
698 ** Make sure bad packets are discarded,
699 ** note that only EOP descriptor has valid
702 if (eop
&& (error
& (1 << I40E_RX_DESC_ERROR_RXE_SHIFT
))) {
706 ri
->iri_frags
[i
].irf_flid
= 0;
707 ri
->iri_frags
[i
].irf_idx
= cidx
;
708 ri
->iri_frags
[i
].irf_len
= plen
;
709 if (++cidx
== vsi
->shared
->isc_nrxd
[0])
714 /* capture data for dynamic ITR adjustment */
718 if ((scctx
->isc_capenable
& IFCAP_RXCSUM
) != 0)
719 rxr
->csum_errs
+= ixl_rx_checksum(ri
, status
, error
, ptype
);
720 ri
->iri_flowid
= le32toh(cur
->wb
.qword0
.hi_dword
.rss
);
721 ri
->iri_rsstype
= ixl_ptype_to_hash(ptype
);
722 if (status
& (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT
)) {
723 ri
->iri_vtag
= le16toh(cur
->wb
.qword0
.lo_dword
.l2tag1
);
724 ri
->iri_flags
|= M_VLANTAG
;
730 /*********************************************************************
732 * Verify that the hardware indicated that the checksum is valid.
733 * Inform the stack about the status of checksum so that stack
734 * doesn't spend time verifying the checksum.
736 *********************************************************************/
738 ixl_rx_checksum(if_rxd_info_t ri
, u32 status
, u32 error
, u8 ptype
)
740 struct i40e_rx_ptype_decoded decoded
;
742 ri
->iri_csum_flags
= 0;
744 /* No L3 or L4 checksum was calculated */
745 if (!(status
& (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT
)))
748 decoded
= decode_rx_desc_ptype(ptype
);
750 /* IPv6 with extension headers likely have bad csum */
751 if (decoded
.outer_ip
== I40E_RX_PTYPE_OUTER_IP
&&
752 decoded
.outer_ip_ver
== I40E_RX_PTYPE_OUTER_IPV6
) {
754 (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT
)) {
755 ri
->iri_csum_flags
= 0;
760 ri
->iri_csum_flags
|= CSUM_L3_CALC
;
762 /* IPv4 checksum error */
763 if (error
& (1 << I40E_RX_DESC_ERROR_IPE_SHIFT
))
766 ri
->iri_csum_flags
|= CSUM_L3_VALID
;
767 ri
->iri_csum_flags
|= CSUM_L4_CALC
;
769 /* L4 checksum error */
770 if (error
& (1 << I40E_RX_DESC_ERROR_L4E_SHIFT
))
773 ri
->iri_csum_flags
|= CSUM_L4_VALID
;
774 ri
->iri_csum_data
|= htons(0xffff);
779 /* Set Report Status queue fields to 0 */
781 ixl_init_tx_rsqs(struct ixl_vsi
*vsi
)
783 if_softc_ctx_t scctx
= vsi
->shared
;
784 struct ixl_tx_queue
*tx_que
;
787 for (i
= 0, tx_que
= vsi
->tx_queues
; i
< vsi
->num_tx_queues
; i
++, tx_que
++) {
788 struct tx_ring
*txr
= &tx_que
->txr
;
790 txr
->tx_rs_cidx
= txr
->tx_rs_pidx
;
792 /* Initialize the last processed descriptor to be the end of
793 * the ring, rather than the start, so that we avoid an
794 * off-by-one error when calculating how many descriptors are
795 * done in the credits_update function.
797 txr
->tx_cidx_processed
= scctx
->isc_ntxd
[0] - 1;
799 for (j
= 0; j
< scctx
->isc_ntxd
[0]; j
++)
800 txr
->tx_rsq
[j
] = QIDX_INVALID
;
805 ixl_init_tx_cidx(struct ixl_vsi
*vsi
)
807 if_softc_ctx_t scctx
= vsi
->shared
;
808 struct ixl_tx_queue
*tx_que
;
811 for (i
= 0, tx_que
= vsi
->tx_queues
; i
< vsi
->num_tx_queues
; i
++, tx_que
++) {
812 struct tx_ring
*txr
= &tx_que
->txr
;
814 txr
->tx_cidx_processed
= scctx
->isc_ntxd
[0] - 1;
819 * Input: bitmap of enum virtchnl_link_speed
822 ixl_max_vc_speed_to_value(u8 link_speeds
)
824 if (link_speeds
& VIRTCHNL_LINK_SPEED_40GB
)
826 if (link_speeds
& VIRTCHNL_LINK_SPEED_25GB
)
828 if (link_speeds
& VIRTCHNL_LINK_SPEED_20GB
)
830 if (link_speeds
& VIRTCHNL_LINK_SPEED_10GB
)
832 if (link_speeds
& VIRTCHNL_LINK_SPEED_1GB
)
834 if (link_speeds
& VIRTCHNL_LINK_SPEED_100MB
)
837 /* Minimum supported link speed */
842 ixl_add_vsi_sysctls(device_t dev
, struct ixl_vsi
*vsi
,
843 struct sysctl_ctx_list
*ctx
, const char *sysctl_name
)
845 struct sysctl_oid
*tree
;
846 struct sysctl_oid_list
*child
;
847 struct sysctl_oid_list
*vsi_list
;
849 tree
= device_get_sysctl_tree(dev
);
850 child
= SYSCTL_CHILDREN(tree
);
851 vsi
->vsi_node
= SYSCTL_ADD_NODE(ctx
, child
, OID_AUTO
, sysctl_name
,
852 CTLFLAG_RD
| CTLFLAG_MPSAFE
, NULL
, "VSI Number");
853 vsi_list
= SYSCTL_CHILDREN(vsi
->vsi_node
);
855 ixl_add_sysctls_eth_stats(ctx
, vsi_list
, &vsi
->eth_stats
);
859 ixl_add_sysctls_eth_stats(struct sysctl_ctx_list
*ctx
,
860 struct sysctl_oid_list
*child
,
861 struct i40e_eth_stats
*eth_stats
)
863 struct ixl_sysctl_info ctls
[] =
865 {ð_stats
->rx_bytes
, "good_octets_rcvd", "Good Octets Received"},
866 {ð_stats
->rx_unicast
, "ucast_pkts_rcvd",
867 "Unicast Packets Received"},
868 {ð_stats
->rx_multicast
, "mcast_pkts_rcvd",
869 "Multicast Packets Received"},
870 {ð_stats
->rx_broadcast
, "bcast_pkts_rcvd",
871 "Broadcast Packets Received"},
872 {ð_stats
->rx_discards
, "rx_discards", "Discarded RX packets"},
873 {ð_stats
->tx_bytes
, "good_octets_txd", "Good Octets Transmitted"},
874 {ð_stats
->tx_unicast
, "ucast_pkts_txd", "Unicast Packets Transmitted"},
875 {ð_stats
->tx_multicast
, "mcast_pkts_txd",
876 "Multicast Packets Transmitted"},
877 {ð_stats
->tx_broadcast
, "bcast_pkts_txd",
878 "Broadcast Packets Transmitted"},
883 struct ixl_sysctl_info
*entry
= ctls
;
884 while (entry
->stat
!= 0)
886 SYSCTL_ADD_UQUAD(ctx
, child
, OID_AUTO
, entry
->name
,
887 CTLFLAG_RD
, entry
->stat
,
894 ixl_vsi_add_queues_stats(struct ixl_vsi
*vsi
, struct sysctl_ctx_list
*ctx
)
896 struct sysctl_oid_list
*vsi_list
, *queue_list
;
897 struct sysctl_oid
*queue_node
;
898 char queue_namebuf
[IXL_QUEUE_NAME_LEN
];
900 struct ixl_rx_queue
*rx_que
;
901 struct ixl_tx_queue
*tx_que
;
905 vsi_list
= SYSCTL_CHILDREN(vsi
->vsi_node
);
907 /* Queue statistics */
908 for (int q
= 0; q
< vsi
->num_rx_queues
; q
++) {
909 bzero(queue_namebuf
, sizeof(queue_namebuf
));
910 snprintf(queue_namebuf
, sizeof(queue_namebuf
), "rxq%02d", q
);
911 queue_node
= SYSCTL_ADD_NODE(ctx
, vsi_list
,
912 OID_AUTO
, queue_namebuf
, CTLFLAG_RD
| CTLFLAG_MPSAFE
,
914 queue_list
= SYSCTL_CHILDREN(queue_node
);
916 rx_que
= &(vsi
->rx_queues
[q
]);
917 rxr
= &(rx_que
->rxr
);
919 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "irqs",
920 CTLFLAG_RD
, &(rx_que
->irqs
),
921 "irqs on this queue (both Tx and Rx)");
923 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "packets",
924 CTLFLAG_RD
, &(rxr
->rx_packets
),
925 "Queue Packets Received");
926 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "bytes",
927 CTLFLAG_RD
, &(rxr
->rx_bytes
),
928 "Queue Bytes Received");
929 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "desc_err",
930 CTLFLAG_RD
, &(rxr
->desc_errs
),
931 "Queue Rx Descriptor Errors");
932 SYSCTL_ADD_UINT(ctx
, queue_list
, OID_AUTO
, "itr",
933 CTLFLAG_RD
, &(rxr
->itr
), 0,
934 "Queue Rx ITR Interval");
936 for (int q
= 0; q
< vsi
->num_tx_queues
; q
++) {
937 bzero(queue_namebuf
, sizeof(queue_namebuf
));
938 snprintf(queue_namebuf
, sizeof(queue_namebuf
), "txq%02d", q
);
939 queue_node
= SYSCTL_ADD_NODE(ctx
, vsi_list
,
940 OID_AUTO
, queue_namebuf
, CTLFLAG_RD
| CTLFLAG_MPSAFE
,
942 queue_list
= SYSCTL_CHILDREN(queue_node
);
944 tx_que
= &(vsi
->tx_queues
[q
]);
945 txr
= &(tx_que
->txr
);
947 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "tso",
948 CTLFLAG_RD
, &(tx_que
->tso
),
950 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "mss_too_small",
951 CTLFLAG_RD
, &(txr
->mss_too_small
),
952 "TSO sends with an MSS less than 64");
953 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "packets",
954 CTLFLAG_RD
, &(txr
->tx_packets
),
955 "Queue Packets Transmitted");
956 SYSCTL_ADD_UQUAD(ctx
, queue_list
, OID_AUTO
, "bytes",
957 CTLFLAG_RD
, &(txr
->tx_bytes
),
958 "Queue Bytes Transmitted");
959 SYSCTL_ADD_UINT(ctx
, queue_list
, OID_AUTO
, "itr",
960 CTLFLAG_RD
, &(txr
->itr
), 0,
961 "Queue Tx ITR Interval");