1/******************************************************************************
2
3  Copyright (c) 2013-2018, Intel Corporation
4  All rights reserved.
5
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are met:
8
9   1. Redistributions of source code must retain the above copyright notice,
10      this list of conditions and the following disclaimer.
11
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   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.
19
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.
31
32******************************************************************************/
33/*$FreeBSD$*/
34
35/*
36**	IXL driver TX/RX Routines:
37**	    This was seperated to allow usage by
38** 	    both the PF and VF drivers.
39*/
40
41#ifndef IXL_STANDALONE_BUILD
42#include "opt_inet.h"
43#include "opt_inet6.h"
44#include "opt_rss.h"
45#endif
46
47#include "ixl.h"
48
49#ifdef RSS
50#include <net/rss_config.h>
51#endif
52
53/* Local Prototypes */
54static void	ixl_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype);
55
56static int	ixl_isc_txd_encap(void *arg, if_pkt_info_t pi);
57static void	ixl_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
58static int	ixl_isc_txd_credits_update_hwb(void *arg, uint16_t txqid, bool clear);
59static int	ixl_isc_txd_credits_update_dwb(void *arg, uint16_t txqid, bool clear);
60
61static void	ixl_isc_rxd_refill(void *arg, if_rxd_update_t iru);
62static void	ixl_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused,
63				  qidx_t pidx);
64static int	ixl_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx,
65				      qidx_t budget);
66static int	ixl_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
67
68struct if_txrx ixl_txrx_hwb = {
69	ixl_isc_txd_encap,
70	ixl_isc_txd_flush,
71	ixl_isc_txd_credits_update_hwb,
72	ixl_isc_rxd_available,
73	ixl_isc_rxd_pkt_get,
74	ixl_isc_rxd_refill,
75	ixl_isc_rxd_flush,
76	NULL
77};
78
79struct if_txrx ixl_txrx_dwb = {
80	ixl_isc_txd_encap,
81	ixl_isc_txd_flush,
82	ixl_isc_txd_credits_update_dwb,
83	ixl_isc_rxd_available,
84	ixl_isc_rxd_pkt_get,
85	ixl_isc_rxd_refill,
86	ixl_isc_rxd_flush,
87	NULL
88};
89
90/*
91 * @key key is saved into this parameter
92 */
93void
94ixl_get_default_rss_key(u32 *key)
95{
96	MPASS(key != NULL);
97
98	u32 rss_seed[IXL_RSS_KEY_SIZE_REG] = {0x41b01687,
99	    0x183cfd8c, 0xce880440, 0x580cbc3c,
100	    0x35897377, 0x328b25e1, 0x4fa98922,
101	    0xb7d90c14, 0xd5bad70d, 0xcd15a2c1,
102	    0x0, 0x0, 0x0};
103
104	bcopy(rss_seed, key, IXL_RSS_KEY_SIZE);
105}
106
107/**
108 * i40e_vc_stat_str - convert virtchnl status err code to a string
109 * @hw: pointer to the HW structure
110 * @stat_err: the status error code to convert
111 **/
112const char *
113i40e_vc_stat_str(struct i40e_hw *hw, enum virtchnl_status_code stat_err)
114{
115	switch (stat_err) {
116	case VIRTCHNL_STATUS_SUCCESS:
117		return "OK";
118	case VIRTCHNL_ERR_PARAM:
119		return "VIRTCHNL_ERR_PARAM";
120	case VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH:
121		return "VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH";
122	case VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR:
123		return "VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR";
124	case VIRTCHNL_STATUS_ERR_INVALID_VF_ID:
125		return "VIRTCHNL_STATUS_ERR_INVALID_VF_ID";
126	case VIRTCHNL_STATUS_NOT_SUPPORTED:
127		return "VIRTCHNL_STATUS_NOT_SUPPORTED";
128	}
129
130	snprintf(hw->err_str, sizeof(hw->err_str), "%d", stat_err);
131	return hw->err_str;
132}
133
134void
135ixl_debug_core(device_t dev, u32 enabled_mask, u32 mask, char *fmt, ...)
136{
137	va_list args;
138
139	if (!(mask & enabled_mask))
140		return;
141
142	/* Re-implement device_printf() */
143	device_print_prettyname(dev);
144	va_start(args, fmt);
145	vprintf(fmt, args);
146	va_end(args);
147}
148
149static bool
150ixl_is_tx_desc_done(struct tx_ring *txr, int idx)
151{
152	return (((txr->tx_base[idx].cmd_type_offset_bsz >> I40E_TXD_QW1_DTYPE_SHIFT)
153	    & I40E_TXD_QW1_DTYPE_MASK) == I40E_TX_DESC_DTYPE_DESC_DONE);
154}
155
156static int
157ixl_tso_detect_sparse(bus_dma_segment_t *segs, int nsegs, if_pkt_info_t pi)
158{
159	int	count, curseg, i, hlen, segsz, seglen, tsolen;
160
161	if (nsegs <= IXL_MAX_TX_SEGS-2)
162		return (0);
163	segsz = pi->ipi_tso_segsz;
164	curseg = count = 0;
165
166	hlen = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen;
167	tsolen = pi->ipi_len - hlen;
168
169	i = 0;
170	curseg = segs[0].ds_len;
171	while (hlen > 0) {
172		count++;
173		if (count > IXL_MAX_TX_SEGS - 2)
174			return (1);
175		if (curseg == 0) {
176			i++;
177			if (__predict_false(i == nsegs))
178				return (1);
179
180			curseg = segs[i].ds_len;
181		}
182		seglen = min(curseg, hlen);
183		curseg -= seglen;
184		hlen -= seglen;
185		// printf("H:seglen = %d, count=%d\n", seglen, count);
186	}
187	while (tsolen > 0) {
188		segsz = pi->ipi_tso_segsz;
189		while (segsz > 0 && tsolen != 0) {
190			count++;
191			if (count > IXL_MAX_TX_SEGS - 2) {
192				// printf("bad: count = %d\n", count);
193				return (1);
194			}
195			if (curseg == 0) {
196				i++;
197				if (__predict_false(i == nsegs)) {
198					// printf("bad: tsolen = %d", tsolen);
199					return (1);
200				}
201				curseg = segs[i].ds_len;
202			}
203			seglen = min(curseg, segsz);
204			segsz -= seglen;
205			curseg -= seglen;
206			tsolen -= seglen;
207			// printf("D:seglen = %d, count=%d\n", seglen, count);
208		}
209		count = 0;
210	}
211
212 	return (0);
213}
214
215/*********************************************************************
216 *
217 *  Setup descriptor for hw offloads
218 *
219 **********************************************************************/
220
221static void
222ixl_tx_setup_offload(struct ixl_tx_queue *que,
223    if_pkt_info_t pi, u32 *cmd, u32 *off)
224{
225	switch (pi->ipi_etype) {
226#ifdef INET
227		case ETHERTYPE_IP:
228			if (pi->ipi_csum_flags & IXL_CSUM_IPV4)
229				*cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM;
230			else
231				*cmd |= I40E_TX_DESC_CMD_IIPT_IPV4;
232			break;
233#endif
234#ifdef INET6
235		case ETHERTYPE_IPV6:
236			*cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
237			break;
238#endif
239		default:
240			break;
241	}
242
243	*off |= (pi->ipi_ehdrlen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
244	*off |= (pi->ipi_ip_hlen >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
245
246	switch (pi->ipi_ipproto) {
247		case IPPROTO_TCP:
248			if (pi->ipi_csum_flags & IXL_CSUM_TCP) {
249				*cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
250				*off |= (pi->ipi_tcp_hlen >> 2) <<
251				    I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
252				/* Check for NO_HEAD MDD event */
253				MPASS(pi->ipi_tcp_hlen != 0);
254			}
255			break;
256		case IPPROTO_UDP:
257			if (pi->ipi_csum_flags & IXL_CSUM_UDP) {
258				*cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
259				*off |= (sizeof(struct udphdr) >> 2) <<
260				    I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
261			}
262			break;
263		case IPPROTO_SCTP:
264			if (pi->ipi_csum_flags & IXL_CSUM_SCTP) {
265				*cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
266				*off |= (sizeof(struct sctphdr) >> 2) <<
267				    I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
268			}
269			/* Fall Thru */
270		default:
271			break;
272	}
273}
274
275/**********************************************************************
276 *
277 *  Setup context for hardware segmentation offload (TSO)
278 *
279 **********************************************************************/
280static int
281ixl_tso_setup(struct tx_ring *txr, if_pkt_info_t pi)
282{
283	if_softc_ctx_t			scctx;
284	struct i40e_tx_context_desc	*TXD;
285	u32				cmd, mss, type, tsolen;
286	int				idx, total_hdr_len;
287	u64				type_cmd_tso_mss;
288
289	idx = pi->ipi_pidx;
290	TXD = (struct i40e_tx_context_desc *) &txr->tx_base[idx];
291	total_hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen;
292	tsolen = pi->ipi_len - total_hdr_len;
293	scctx = txr->que->vsi->shared;
294
295	type = I40E_TX_DESC_DTYPE_CONTEXT;
296	cmd = I40E_TX_CTX_DESC_TSO;
297	/*
298	 * TSO MSS must not be less than 64; this prevents a
299	 * BAD_LSO_MSS MDD event when the MSS is too small.
300	 */
301	if (pi->ipi_tso_segsz < IXL_MIN_TSO_MSS) {
302		txr->mss_too_small++;
303		pi->ipi_tso_segsz = IXL_MIN_TSO_MSS;
304	}
305	mss = pi->ipi_tso_segsz;
306
307	/* Check for BAD_LS0_MSS MDD event (mss too large) */
308	MPASS(mss <= IXL_MAX_TSO_MSS);
309	/* Check for NO_HEAD MDD event (header lengths are 0) */
310	MPASS(pi->ipi_ehdrlen != 0);
311	MPASS(pi->ipi_ip_hlen != 0);
312	/* Partial check for BAD_LSO_LEN MDD event */
313	MPASS(tsolen != 0);
314	/* Partial check for WRONG_SIZE MDD event (during TSO) */
315	MPASS(total_hdr_len + mss <= IXL_MAX_FRAME);
316
317	type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) |
318	    ((u64)cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
319	    ((u64)tsolen << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
320	    ((u64)mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
321	TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss);
322
323	TXD->tunneling_params = htole32(0);
324	txr->que->tso++;
325
326	return ((idx + 1) & (scctx->isc_ntxd[0]-1));
327}
328
329/*********************************************************************
330  *
331 *  This routine maps the mbufs to tx descriptors, allowing the
332 *  TX engine to transmit the packets.
333 *  	- return 0 on success, positive on failure
334  *
335  **********************************************************************/
336#define IXL_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
337
338static int
339ixl_isc_txd_encap(void *arg, if_pkt_info_t pi)
340{
341	struct ixl_vsi		*vsi = arg;
342	if_softc_ctx_t		scctx = vsi->shared;
343	struct ixl_tx_queue	*que = &vsi->tx_queues[pi->ipi_qsidx];
344 	struct tx_ring		*txr = &que->txr;
345	int			nsegs = pi->ipi_nsegs;
346	bus_dma_segment_t *segs = pi->ipi_segs;
347	struct i40e_tx_desc	*txd = NULL;
348	int             	i, j, mask, pidx_last;
349	u32			cmd, off, tx_intr;
350
351	cmd = off = 0;
352	i = pi->ipi_pidx;
353
354	tx_intr = (pi->ipi_flags & IPI_TX_INTR);
355
356	/* Set up the TSO/CSUM offload */
357	if (pi->ipi_csum_flags & CSUM_OFFLOAD) {
358		/* Set up the TSO context descriptor if required */
359		if (pi->ipi_csum_flags & CSUM_TSO) {
360			/* Prevent MAX_BUFF MDD event (for TSO) */
361			if (ixl_tso_detect_sparse(segs, nsegs, pi))
362				return (EFBIG);
363			i = ixl_tso_setup(txr, pi);
364		}
365		ixl_tx_setup_offload(que, pi, &cmd, &off);
366	}
367	if (pi->ipi_mflags & M_VLANTAG)
368		cmd |= I40E_TX_DESC_CMD_IL2TAG1;
369
370	cmd |= I40E_TX_DESC_CMD_ICRC;
371	mask = scctx->isc_ntxd[0] - 1;
372	/* Check for WRONG_SIZE MDD event */
373	MPASS(pi->ipi_len >= IXL_MIN_FRAME);
374#ifdef INVARIANTS
375	if (!(pi->ipi_csum_flags & CSUM_TSO))
376		MPASS(pi->ipi_len <= IXL_MAX_FRAME);
377#endif
378	for (j = 0; j < nsegs; j++) {
379		bus_size_t seglen;
380
381		txd = &txr->tx_base[i];
382		seglen = segs[j].ds_len;
383
384		/* Check for ZERO_BSIZE MDD event */
385		MPASS(seglen != 0);
386
387		txd->buffer_addr = htole64(segs[j].ds_addr);
388		txd->cmd_type_offset_bsz =
389		    htole64(I40E_TX_DESC_DTYPE_DATA
390		    | ((u64)cmd  << I40E_TXD_QW1_CMD_SHIFT)
391		    | ((u64)off << I40E_TXD_QW1_OFFSET_SHIFT)
392		    | ((u64)seglen  << I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
393	            | ((u64)htole16(pi->ipi_vtag) << I40E_TXD_QW1_L2TAG1_SHIFT));
394
395		txr->tx_bytes += seglen;
396		pidx_last = i;
397		i = (i+1) & mask;
398	}
399	/* Set the last descriptor for report */
400	txd->cmd_type_offset_bsz |=
401	    htole64(((u64)IXL_TXD_CMD << I40E_TXD_QW1_CMD_SHIFT));
402	/* Add to report status array (if using TX interrupts) */
403	if (!vsi->enable_head_writeback && tx_intr) {
404		txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
405		txr->tx_rs_pidx = (txr->tx_rs_pidx+1) & mask;
406		MPASS(txr->tx_rs_pidx != txr->tx_rs_cidx);
407 	}
408	pi->ipi_new_pidx = i;
409
410	++txr->tx_packets;
411	return (0);
412}
413
414static void
415ixl_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
416{
417	struct ixl_vsi *vsi = arg;
418	struct tx_ring *txr = &vsi->tx_queues[txqid].txr;
419
420 	/*
421	 * Advance the Transmit Descriptor Tail (Tdt), this tells the
422	 * hardware that this frame is available to transmit.
423 	 */
424	/* Check for ENDLESS_TX MDD event */
425	MPASS(pidx < vsi->shared->isc_ntxd[0]);
426	wr32(vsi->hw, txr->tail, pidx);
427}
428
429
430/*********************************************************************
431 *
432 *  (Re)Initialize a queue transmit ring by clearing its memory.
433 *
434 **********************************************************************/
435void
436ixl_init_tx_ring(struct ixl_vsi *vsi, struct ixl_tx_queue *que)
437{
438	struct tx_ring *txr = &que->txr;
439
440	/* Clear the old ring contents */
441	bzero((void *)txr->tx_base,
442	      (sizeof(struct i40e_tx_desc)) *
443	      (vsi->shared->isc_ntxd[0] + (vsi->enable_head_writeback ? 1 : 0)));
444
445	wr32(vsi->hw, txr->tail, 0);
446}
447
448/*
449 * ixl_get_tx_head - Retrieve the value from the
450 *    location the HW records its HEAD index
451 */
452static inline u32
453ixl_get_tx_head(struct ixl_tx_queue *que)
454{
455	if_softc_ctx_t          scctx = que->vsi->shared;
456	struct tx_ring  *txr = &que->txr;
457	void *head = &txr->tx_base[scctx->isc_ntxd[0]];
458
459	return LE32_TO_CPU(*(volatile __le32 *)head);
460}
461
462static int
463ixl_isc_txd_credits_update_hwb(void *arg, uint16_t qid, bool clear)
464{
465	struct ixl_vsi          *vsi = arg;
466	if_softc_ctx_t          scctx = vsi->shared;
467	struct ixl_tx_queue     *que = &vsi->tx_queues[qid];
468	struct tx_ring		*txr = &que->txr;
469	int			 head, credits;
470
471	/* Get the Head WB value */
472	head = ixl_get_tx_head(que);
473
474	credits = head - txr->tx_cidx_processed;
475	if (credits < 0)
476		credits += scctx->isc_ntxd[0];
477	if (clear)
478		txr->tx_cidx_processed = head;
479
480	return (credits);
481}
482
483static int
484ixl_isc_txd_credits_update_dwb(void *arg, uint16_t txqid, bool clear)
485{
486	struct ixl_vsi *vsi = arg;
487	struct ixl_tx_queue *tx_que = &vsi->tx_queues[txqid];
488	if_softc_ctx_t scctx = vsi->shared;
489	struct tx_ring *txr = &tx_que->txr;
490
491	qidx_t processed = 0;
492	qidx_t cur, prev, ntxd, rs_cidx;
493	int32_t delta;
494	bool is_done;
495
496	rs_cidx = txr->tx_rs_cidx;
497#if 0
498	device_printf(iflib_get_dev(vsi->ctx), "%s: (q%d) rs_cidx %d, txr->tx_rs_pidx %d\n", __func__,
499	    txr->me, rs_cidx, txr->tx_rs_pidx);
500#endif
501	if (rs_cidx == txr->tx_rs_pidx)
502		return (0);
503	cur = txr->tx_rsq[rs_cidx];
504	MPASS(cur != QIDX_INVALID);
505	is_done = ixl_is_tx_desc_done(txr, cur);
506
507	if (!is_done)
508		return (0);
509
510	/* If clear is false just let caller know that there
511	 * are descriptors to reclaim */
512	if (!clear)
513		return (1);
514
515	prev = txr->tx_cidx_processed;
516	ntxd = scctx->isc_ntxd[0];
517	do {
518		MPASS(prev != cur);
519		delta = (int32_t)cur - (int32_t)prev;
520		if (delta < 0)
521			delta += ntxd;
522		MPASS(delta > 0);
523#if 0
524		device_printf(iflib_get_dev(vsi->ctx),
525			      "%s: (q%d) cidx_processed=%u cur=%u clear=%d delta=%d\n",
526			      __func__, txr->me, prev, cur, clear, delta);
527#endif
528		processed += delta;
529		prev = cur;
530		rs_cidx = (rs_cidx + 1) & (ntxd-1);
531		if (rs_cidx == txr->tx_rs_pidx)
532			break;
533		cur = txr->tx_rsq[rs_cidx];
534		MPASS(cur != QIDX_INVALID);
535		is_done = ixl_is_tx_desc_done(txr, cur);
536	} while (is_done);
537
538	txr->tx_rs_cidx = rs_cidx;
539	txr->tx_cidx_processed = prev;
540
541#if 0
542	device_printf(iflib_get_dev(vsi->ctx), "%s: (q%d) processed %d\n", __func__, txr->me, processed);
543#endif
544	return (processed);
545}
546
547static void
548ixl_isc_rxd_refill(void *arg, if_rxd_update_t iru)
549{
550	struct ixl_vsi *vsi = arg;
551	if_softc_ctx_t scctx = vsi->shared;
552	struct rx_ring *rxr = &((vsi->rx_queues[iru->iru_qsidx]).rxr);
553	uint64_t *paddrs;
554	uint32_t next_pidx, pidx;
555	uint16_t count;
556	int i;
557
558	paddrs = iru->iru_paddrs;
559	pidx = iru->iru_pidx;
560	count = iru->iru_count;
561
562	for (i = 0, next_pidx = pidx; i < count; i++) {
563		rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
564		if (++next_pidx == scctx->isc_nrxd[0])
565			next_pidx = 0;
566 	}
567}
568
569static void
570ixl_isc_rxd_flush(void * arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx)
571{
572	struct ixl_vsi		*vsi = arg;
573	struct rx_ring		*rxr = &vsi->rx_queues[rxqid].rxr;
574
575	wr32(vsi->hw, rxr->tail, pidx);
576}
577
578static int
579ixl_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
580{
581	struct ixl_vsi *vsi = arg;
582	struct rx_ring *rxr = &vsi->rx_queues[rxqid].rxr;
583	union i40e_rx_desc *rxd;
584	u64 qword;
585	uint32_t status;
586	int cnt, i, nrxd;
587
588	nrxd = vsi->shared->isc_nrxd[0];
589
590	for (cnt = 0, i = idx; cnt < nrxd - 1 && cnt <= budget;) {
591		rxd = &rxr->rx_base[i];
592		qword = le64toh(rxd->wb.qword1.status_error_len);
593		status = (qword & I40E_RXD_QW1_STATUS_MASK)
594			>> I40E_RXD_QW1_STATUS_SHIFT;
595
596		if ((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) == 0)
597			break;
598		if (++i == nrxd)
599			i = 0;
600		if (status & (1 << I40E_RX_DESC_STATUS_EOF_SHIFT))
601			cnt++;
602	}
603
604	return (cnt);
605}
606
607/*
608** i40e_ptype_to_hash: parse the packet type
609** to determine the appropriate hash.
610*/
611static inline int
612ixl_ptype_to_hash(u8 ptype)
613{
614        struct i40e_rx_ptype_decoded	decoded;
615
616	decoded = decode_rx_desc_ptype(ptype);
617
618	if (!decoded.known)
619		return M_HASHTYPE_OPAQUE;
620
621	if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_L2)
622		return M_HASHTYPE_OPAQUE;
623
624	/* Note: anything that gets to this point is IP */
625        if (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6) {
626		switch (decoded.inner_prot) {
627		case I40E_RX_PTYPE_INNER_PROT_TCP:
628			return M_HASHTYPE_RSS_TCP_IPV6;
629		case I40E_RX_PTYPE_INNER_PROT_UDP:
630			return M_HASHTYPE_RSS_UDP_IPV6;
631		default:
632			return M_HASHTYPE_RSS_IPV6;
633		}
634	}
635        if (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4) {
636		switch (decoded.inner_prot) {
637		case I40E_RX_PTYPE_INNER_PROT_TCP:
638			return M_HASHTYPE_RSS_TCP_IPV4;
639		case I40E_RX_PTYPE_INNER_PROT_UDP:
640			return M_HASHTYPE_RSS_UDP_IPV4;
641		default:
642			return M_HASHTYPE_RSS_IPV4;
643		}
644	}
645	/* We should never get here!! */
646	return M_HASHTYPE_OPAQUE;
647}
648
649/*********************************************************************
650 *
651 *  This routine executes in ithread context. It sends data which has been
652 *  dma'ed into host memory to upper layer.
653 *
654 *  Returns 0 upon success, errno on failure
655 *
656 *********************************************************************/
657static int
658ixl_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
659{
660	struct ixl_vsi		*vsi = arg;
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;
664	u32		status, error;
665	u16		plen, vtag;
666	u64		qword;
667	u8		ptype;
668	bool		eop;
669	int i, cidx;
670
671	cidx = ri->iri_cidx;
672	i = 0;
673	do {
674		/* 5 descriptor receive limit */
675		MPASS(i < IXL_MAX_RX_SEGS);
676
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;
687
688		/* we should never be called without a valid descriptor */
689		MPASS((status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) != 0);
690
691		ri->iri_len += plen;
692		rxr->rx_bytes += plen;
693
694		cur->wb.qword1.status_error_len = 0;
695		eop = (status & (1 << I40E_RX_DESC_STATUS_EOF_SHIFT));
696		if (status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT))
697			vtag = le16toh(cur->wb.qword0.lo_dword.l2tag1);
698		else
699			vtag = 0;
700
701		/*
702		** Make sure bad packets are discarded,
703		** note that only EOP descriptor has valid
704		** error results.
705		*/
706		if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) {
707			rxr->desc_errs++;
708			return (EBADMSG);
709		}
710		ri->iri_frags[i].irf_flid = 0;
711		ri->iri_frags[i].irf_idx = cidx;
712		ri->iri_frags[i].irf_len = plen;
713		if (++cidx == vsi->shared->isc_nrxd[0])
714			cidx = 0;
715		i++;
716	} while (!eop);
717
718	/* capture data for dynamic ITR adjustment */
719	rxr->packets++;
720	rxr->rx_packets++;
721
722	if ((if_getcapenable(vsi->ifp) & IFCAP_RXCSUM) != 0)
723		ixl_rx_checksum(ri, status, error, ptype);
724	ri->iri_flowid = le32toh(cur->wb.qword0.hi_dword.rss);
725	ri->iri_rsstype = ixl_ptype_to_hash(ptype);
726	ri->iri_vtag = vtag;
727	ri->iri_nfrags = i;
728	if (vtag)
729		ri->iri_flags |= M_VLANTAG;
730	return (0);
731}
732
733/*********************************************************************
734 *
735 *  Verify that the hardware indicated that the checksum is valid.
736 *  Inform the stack about the status of checksum so that stack
737 *  doesn't spend time verifying the checksum.
738 *
739 *********************************************************************/
740static void
741ixl_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype)
742{
743	struct i40e_rx_ptype_decoded decoded;
744
745	ri->iri_csum_flags = 0;
746
747	/* No L3 or L4 checksum was calculated */
748	if (!(status & (1 << I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
749		return;
750
751	decoded = decode_rx_desc_ptype(ptype);
752
753	/* IPv6 with extension headers likely have bad csum */
754	if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
755	    decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6) {
756		if (status &
757		    (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT)) {
758			ri->iri_csum_flags = 0;
759			return;
760		}
761	}
762
763	ri->iri_csum_flags |= CSUM_L3_CALC;
764
765	/* IPv4 checksum error */
766	if (error & (1 << I40E_RX_DESC_ERROR_IPE_SHIFT))
767		return;
768
769	ri->iri_csum_flags |= CSUM_L3_VALID;
770	ri->iri_csum_flags |= CSUM_L4_CALC;
771
772	/* L4 checksum error */
773	if (error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT))
774		return;
775
776	ri->iri_csum_flags |= CSUM_L4_VALID;
777	ri->iri_csum_data |= htons(0xffff);
778}
779
780/* Set Report Status queue fields to 0 */
781void
782ixl_init_tx_rsqs(struct ixl_vsi *vsi)
783{
784	if_softc_ctx_t scctx = vsi->shared;
785	struct ixl_tx_queue *tx_que;
786	int i, j;
787
788	for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) {
789		struct tx_ring *txr = &tx_que->txr;
790
791		txr->tx_rs_cidx = txr->tx_rs_pidx;
792
793		/* Initialize the last processed descriptor to be the end of
794		 * the ring, rather than the start, so that we avoid an
795		 * off-by-one error when calculating how many descriptors are
796		 * done in the credits_update function.
797		 */
798		txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1;
799
800		for (j = 0; j < scctx->isc_ntxd[0]; j++)
801			txr->tx_rsq[j] = QIDX_INVALID;
802	}
803}
804
805void
806ixl_init_tx_cidx(struct ixl_vsi *vsi)
807{
808	if_softc_ctx_t scctx = vsi->shared;
809	struct ixl_tx_queue *tx_que;
810	int i;
811
812	for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) {
813		struct tx_ring *txr = &tx_que->txr;
814
815		txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1;
816	}
817}
818
819/*
820 * Input: bitmap of enum virtchnl_link_speed
821 */
822u64
823ixl_max_vc_speed_to_value(u8 link_speeds)
824{
825	if (link_speeds & VIRTCHNL_LINK_SPEED_40GB)
826		return IF_Gbps(40);
827	if (link_speeds & VIRTCHNL_LINK_SPEED_25GB)
828		return IF_Gbps(25);
829	if (link_speeds & VIRTCHNL_LINK_SPEED_20GB)
830		return IF_Gbps(20);
831	if (link_speeds & VIRTCHNL_LINK_SPEED_10GB)
832		return IF_Gbps(10);
833	if (link_speeds & VIRTCHNL_LINK_SPEED_1GB)
834		return IF_Gbps(1);
835	if (link_speeds & VIRTCHNL_LINK_SPEED_100MB)
836		return IF_Mbps(100);
837	else
838		/* Minimum supported link speed */
839		return IF_Mbps(100);
840}
841
842void
843ixl_add_vsi_sysctls(device_t dev, struct ixl_vsi *vsi,
844    struct sysctl_ctx_list *ctx, const char *sysctl_name)
845{
846	struct sysctl_oid *tree;
847	struct sysctl_oid_list *child;
848	struct sysctl_oid_list *vsi_list;
849
850	tree = device_get_sysctl_tree(dev);
851	child = SYSCTL_CHILDREN(tree);
852	vsi->vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, sysctl_name,
853	    CTLFLAG_RD, NULL, "VSI Number");
854	vsi_list = SYSCTL_CHILDREN(vsi->vsi_node);
855
856	ixl_add_sysctls_eth_stats(ctx, vsi_list, &vsi->eth_stats);
857}
858
859void
860ixl_add_sysctls_eth_stats(struct sysctl_ctx_list *ctx,
861	struct sysctl_oid_list *child,
862	struct i40e_eth_stats *eth_stats)
863{
864	struct ixl_sysctl_info ctls[] =
865	{
866		{&eth_stats->rx_bytes, "good_octets_rcvd", "Good Octets Received"},
867		{&eth_stats->rx_unicast, "ucast_pkts_rcvd",
868			"Unicast Packets Received"},
869		{&eth_stats->rx_multicast, "mcast_pkts_rcvd",
870			"Multicast Packets Received"},
871		{&eth_stats->rx_broadcast, "bcast_pkts_rcvd",
872			"Broadcast Packets Received"},
873		{&eth_stats->rx_discards, "rx_discards", "Discarded RX packets"},
874		{&eth_stats->tx_bytes, "good_octets_txd", "Good Octets Transmitted"},
875		{&eth_stats->tx_unicast, "ucast_pkts_txd", "Unicast Packets Transmitted"},
876		{&eth_stats->tx_multicast, "mcast_pkts_txd",
877			"Multicast Packets Transmitted"},
878		{&eth_stats->tx_broadcast, "bcast_pkts_txd",
879			"Broadcast Packets Transmitted"},
880		// end
881		{0,0,0}
882	};
883
884	struct ixl_sysctl_info *entry = ctls;
885	while (entry->stat != 0)
886	{
887		SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, entry->name,
888				CTLFLAG_RD, entry->stat,
889				entry->description);
890		entry++;
891	}
892}
893
894void
895ixl_vsi_add_queues_stats(struct ixl_vsi *vsi, struct sysctl_ctx_list *ctx)
896{
897	struct sysctl_oid_list *vsi_list, *queue_list;
898	struct sysctl_oid *queue_node;
899	char queue_namebuf[IXL_QUEUE_NAME_LEN];
900
901	struct ixl_rx_queue *rx_que;
902	struct ixl_tx_queue *tx_que;
903	struct tx_ring *txr;
904	struct rx_ring *rxr;
905
906	vsi_list = SYSCTL_CHILDREN(vsi->vsi_node);
907
908	/* Queue statistics */
909	for (int q = 0; q < vsi->num_rx_queues; q++) {
910		bzero(queue_namebuf, sizeof(queue_namebuf));
911		snprintf(queue_namebuf, sizeof(queue_namebuf), "rxq%02d", q);
912		queue_node = SYSCTL_ADD_NODE(ctx, vsi_list,
913		    OID_AUTO, queue_namebuf, CTLFLAG_RD,
914		    NULL, "RX Queue #");
915		queue_list = SYSCTL_CHILDREN(queue_node);
916
917		rx_que = &(vsi->rx_queues[q]);
918		rxr = &(rx_que->rxr);
919
920		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
921				CTLFLAG_RD, &(rx_que->irqs),
922				"irqs on this queue (both Tx and Rx)");
923
924		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
925				CTLFLAG_RD, &(rxr->rx_packets),
926				"Queue Packets Received");
927		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
928				CTLFLAG_RD, &(rxr->rx_bytes),
929				"Queue Bytes Received");
930		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "desc_err",
931				CTLFLAG_RD, &(rxr->desc_errs),
932				"Queue Rx Descriptor Errors");
933		SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "itr",
934				CTLFLAG_RD, &(rxr->itr), 0,
935				"Queue Rx ITR Interval");
936	}
937	for (int q = 0; q < vsi->num_tx_queues; q++) {
938		bzero(queue_namebuf, sizeof(queue_namebuf));
939		snprintf(queue_namebuf, sizeof(queue_namebuf), "txq%02d", q);
940		queue_node = SYSCTL_ADD_NODE(ctx, vsi_list,
941		    OID_AUTO, queue_namebuf, CTLFLAG_RD,
942		    NULL, "TX Queue #");
943		queue_list = SYSCTL_CHILDREN(queue_node);
944
945		tx_que = &(vsi->tx_queues[q]);
946		txr = &(tx_que->txr);
947
948		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso",
949				CTLFLAG_RD, &(tx_que->tso),
950				"TSO");
951		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "mss_too_small",
952				CTLFLAG_RD, &(txr->mss_too_small),
953				"TSO sends with an MSS less than 64");
954		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
955				CTLFLAG_RD, &(txr->tx_packets),
956				"Queue Packets Transmitted");
957		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
958				CTLFLAG_RD, &(txr->tx_bytes),
959				"Queue Bytes Transmitted");
960		SYSCTL_ADD_UINT(ctx, queue_list, OID_AUTO, "itr",
961				CTLFLAG_RD, &(txr->itr), 0,
962				"Queue Tx ITR Interval");
963	}
964}
965