xref: /freebsd/sys/dev/iavf/iavf_vc_iflib.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1*ca853deeSEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2*ca853deeSEric Joyner /*  Copyright (c) 2021, Intel Corporation
3*ca853deeSEric Joyner  *  All rights reserved.
4*ca853deeSEric Joyner  *
5*ca853deeSEric Joyner  *  Redistribution and use in source and binary forms, with or without
6*ca853deeSEric Joyner  *  modification, are permitted provided that the following conditions are met:
7*ca853deeSEric Joyner  *
8*ca853deeSEric Joyner  *   1. Redistributions of source code must retain the above copyright notice,
9*ca853deeSEric Joyner  *      this list of conditions and the following disclaimer.
10*ca853deeSEric Joyner  *
11*ca853deeSEric Joyner  *   2. Redistributions in binary form must reproduce the above copyright
12*ca853deeSEric Joyner  *      notice, this list of conditions and the following disclaimer in the
13*ca853deeSEric Joyner  *      documentation and/or other materials provided with the distribution.
14*ca853deeSEric Joyner  *
15*ca853deeSEric Joyner  *   3. Neither the name of the Intel Corporation nor the names of its
16*ca853deeSEric Joyner  *      contributors may be used to endorse or promote products derived from
17*ca853deeSEric Joyner  *      this software without specific prior written permission.
18*ca853deeSEric Joyner  *
19*ca853deeSEric Joyner  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*ca853deeSEric Joyner  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*ca853deeSEric Joyner  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*ca853deeSEric Joyner  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23*ca853deeSEric Joyner  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*ca853deeSEric Joyner  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*ca853deeSEric Joyner  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*ca853deeSEric Joyner  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*ca853deeSEric Joyner  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*ca853deeSEric Joyner  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*ca853deeSEric Joyner  *  POSSIBILITY OF SUCH DAMAGE.
30*ca853deeSEric Joyner  */
31*ca853deeSEric Joyner 
32*ca853deeSEric Joyner /**
33*ca853deeSEric Joyner  * @file iavf_vc_iflib.c
34*ca853deeSEric Joyner  * @brief iflib-specific Virtchnl interface functions
35*ca853deeSEric Joyner  *
36*ca853deeSEric Joyner  * Contains functions implementing the virtchnl interface for communicating
37*ca853deeSEric Joyner  * with the PF driver. This file contains definitions specific to the iflib
38*ca853deeSEric Joyner  * driver implementation.
39*ca853deeSEric Joyner  */
40*ca853deeSEric Joyner 
41*ca853deeSEric Joyner #include "iavf_iflib.h"
42*ca853deeSEric Joyner #include "iavf_vc_common.h"
43*ca853deeSEric Joyner 
44*ca853deeSEric Joyner /**
45*ca853deeSEric Joyner  * iavf_configure_queues - Configure queues
46*ca853deeSEric Joyner  * @sc: device softc
47*ca853deeSEric Joyner  *
48*ca853deeSEric Joyner  * Request that the PF set up our queues.
49*ca853deeSEric Joyner  *
50*ca853deeSEric Joyner  * @returns zero on success, or an error code on failure.
51*ca853deeSEric Joyner  */
52*ca853deeSEric Joyner int
iavf_configure_queues(struct iavf_sc * sc)53*ca853deeSEric Joyner iavf_configure_queues(struct iavf_sc *sc)
54*ca853deeSEric Joyner {
55*ca853deeSEric Joyner 	device_t dev = sc->dev;
56*ca853deeSEric Joyner 	struct iavf_vsi *vsi = &sc->vsi;
57*ca853deeSEric Joyner 	if_softc_ctx_t		scctx = iflib_get_softc_ctx(vsi->ctx);
58*ca853deeSEric Joyner 	struct iavf_tx_queue	*tx_que = vsi->tx_queues;
59*ca853deeSEric Joyner 	struct iavf_rx_queue	*rx_que = vsi->rx_queues;
60*ca853deeSEric Joyner 	struct tx_ring		*txr;
61*ca853deeSEric Joyner 	struct rx_ring		*rxr;
62*ca853deeSEric Joyner 	int			len, pairs;
63*ca853deeSEric Joyner 
64*ca853deeSEric Joyner 	struct virtchnl_vsi_queue_config_info *vqci;
65*ca853deeSEric Joyner 	struct virtchnl_queue_pair_info *vqpi;
66*ca853deeSEric Joyner 
67*ca853deeSEric Joyner 	/* XXX: Linux PF driver wants matching ids in each tx/rx struct, so both TX/RX
68*ca853deeSEric Joyner 	 * queues of a pair need to be configured */
69*ca853deeSEric Joyner 	pairs = max(vsi->num_tx_queues, vsi->num_rx_queues);
70*ca853deeSEric Joyner 	len = sizeof(struct virtchnl_vsi_queue_config_info) +
71*ca853deeSEric Joyner 		       (sizeof(struct virtchnl_queue_pair_info) * pairs);
72*ca853deeSEric Joyner 	vqci = malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
73*ca853deeSEric Joyner 	if (!vqci) {
74*ca853deeSEric Joyner 		device_printf(dev, "%s: unable to allocate memory\n", __func__);
75*ca853deeSEric Joyner 		return (ENOMEM);
76*ca853deeSEric Joyner 	}
77*ca853deeSEric Joyner 	vqci->vsi_id = sc->vsi_res->vsi_id;
78*ca853deeSEric Joyner 	vqci->num_queue_pairs = pairs;
79*ca853deeSEric Joyner 	vqpi = vqci->qpair;
80*ca853deeSEric Joyner 	/* Size check is not needed here - HW max is 16 queue pairs, and we
81*ca853deeSEric Joyner 	 * can fit info for 31 of them into the AQ buffer before it overflows.
82*ca853deeSEric Joyner 	 */
83*ca853deeSEric Joyner 	// TODO: the above is wrong now; X722 VFs can have 256 queues
84*ca853deeSEric Joyner 	for (int i = 0; i < pairs; i++, tx_que++, rx_que++, vqpi++) {
85*ca853deeSEric Joyner 		txr = &tx_que->txr;
86*ca853deeSEric Joyner 		rxr = &rx_que->rxr;
87*ca853deeSEric Joyner 
88*ca853deeSEric Joyner 		vqpi->txq.vsi_id = vqci->vsi_id;
89*ca853deeSEric Joyner 		vqpi->txq.queue_id = i;
90*ca853deeSEric Joyner 		vqpi->txq.ring_len = scctx->isc_ntxd[0];
91*ca853deeSEric Joyner 		vqpi->txq.dma_ring_addr = txr->tx_paddr;
92*ca853deeSEric Joyner 		/* Enable Head writeback */
93*ca853deeSEric Joyner 		if (!vsi->enable_head_writeback) {
94*ca853deeSEric Joyner 			vqpi->txq.headwb_enabled = 0;
95*ca853deeSEric Joyner 			vqpi->txq.dma_headwb_addr = 0;
96*ca853deeSEric Joyner 		} else {
97*ca853deeSEric Joyner 			vqpi->txq.headwb_enabled = 1;
98*ca853deeSEric Joyner 			vqpi->txq.dma_headwb_addr = txr->tx_paddr +
99*ca853deeSEric Joyner 			    sizeof(struct iavf_tx_desc) * scctx->isc_ntxd[0];
100*ca853deeSEric Joyner 		}
101*ca853deeSEric Joyner 
102*ca853deeSEric Joyner 		vqpi->rxq.vsi_id = vqci->vsi_id;
103*ca853deeSEric Joyner 		vqpi->rxq.queue_id = i;
104*ca853deeSEric Joyner 		vqpi->rxq.ring_len = scctx->isc_nrxd[0];
105*ca853deeSEric Joyner 		vqpi->rxq.dma_ring_addr = rxr->rx_paddr;
106*ca853deeSEric Joyner 		vqpi->rxq.max_pkt_size = scctx->isc_max_frame_size;
107*ca853deeSEric Joyner 		vqpi->rxq.databuffer_size = rxr->mbuf_sz;
108*ca853deeSEric Joyner 		vqpi->rxq.splithdr_enabled = 0;
109*ca853deeSEric Joyner 	}
110*ca853deeSEric Joyner 
111*ca853deeSEric Joyner 	iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
112*ca853deeSEric Joyner 			   (u8 *)vqci, len);
113*ca853deeSEric Joyner 	free(vqci, M_IAVF);
114*ca853deeSEric Joyner 
115*ca853deeSEric Joyner 	return (0);
116*ca853deeSEric Joyner }
117*ca853deeSEric Joyner 
118*ca853deeSEric Joyner /**
119*ca853deeSEric Joyner  * iavf_map_queues - Map queues to interrupt vectors
120*ca853deeSEric Joyner  * @sc: device softc
121*ca853deeSEric Joyner  *
122*ca853deeSEric Joyner  * Request that the PF map queues to interrupt vectors. Misc causes, including
123*ca853deeSEric Joyner  * admin queue, are always mapped to vector 0.
124*ca853deeSEric Joyner  *
125*ca853deeSEric Joyner  * @returns zero on success, or an error code on failure.
126*ca853deeSEric Joyner  */
127*ca853deeSEric Joyner int
iavf_map_queues(struct iavf_sc * sc)128*ca853deeSEric Joyner iavf_map_queues(struct iavf_sc *sc)
129*ca853deeSEric Joyner {
130*ca853deeSEric Joyner 	struct virtchnl_irq_map_info *vm;
131*ca853deeSEric Joyner 	int			i, q, len;
132*ca853deeSEric Joyner 	struct iavf_vsi		*vsi = &sc->vsi;
133*ca853deeSEric Joyner 	struct iavf_rx_queue	*rx_que = vsi->rx_queues;
134*ca853deeSEric Joyner 	if_softc_ctx_t		scctx = vsi->shared;
135*ca853deeSEric Joyner 	device_t		dev = sc->dev;
136*ca853deeSEric Joyner 
137*ca853deeSEric Joyner 	// XXX: What happens if we only get 1 MSI-X vector?
138*ca853deeSEric Joyner 	MPASS(scctx->isc_vectors > 1);
139*ca853deeSEric Joyner 
140*ca853deeSEric Joyner 	/* How many queue vectors, adminq uses one */
141*ca853deeSEric Joyner 	// XXX: How do we know how many interrupt vectors we have?
142*ca853deeSEric Joyner 	q = scctx->isc_vectors - 1;
143*ca853deeSEric Joyner 
144*ca853deeSEric Joyner 	len = sizeof(struct virtchnl_irq_map_info) +
145*ca853deeSEric Joyner 	      (scctx->isc_vectors * sizeof(struct virtchnl_vector_map));
146*ca853deeSEric Joyner 	vm = malloc(len, M_IAVF, M_NOWAIT);
147*ca853deeSEric Joyner 	if (!vm) {
148*ca853deeSEric Joyner 		device_printf(dev, "%s: unable to allocate memory\n", __func__);
149*ca853deeSEric Joyner 		return (ENOMEM);
150*ca853deeSEric Joyner 	}
151*ca853deeSEric Joyner 
152*ca853deeSEric Joyner 	vm->num_vectors = scctx->isc_vectors;
153*ca853deeSEric Joyner 	/* Queue vectors first */
154*ca853deeSEric Joyner 	for (i = 0; i < q; i++, rx_que++) {
155*ca853deeSEric Joyner 		vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id;
156*ca853deeSEric Joyner 		vm->vecmap[i].vector_id = i + 1; /* first is adminq */
157*ca853deeSEric Joyner 		// TODO: Re-examine this
158*ca853deeSEric Joyner 		vm->vecmap[i].txq_map = (1 << rx_que->rxr.me);
159*ca853deeSEric Joyner 		vm->vecmap[i].rxq_map = (1 << rx_que->rxr.me);
160*ca853deeSEric Joyner 		vm->vecmap[i].rxitr_idx = 0;
161*ca853deeSEric Joyner 		vm->vecmap[i].txitr_idx = 1;
162*ca853deeSEric Joyner 	}
163*ca853deeSEric Joyner 
164*ca853deeSEric Joyner 	/* Misc vector last - this is only for AdminQ messages */
165*ca853deeSEric Joyner 	vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id;
166*ca853deeSEric Joyner 	vm->vecmap[i].vector_id = 0;
167*ca853deeSEric Joyner 	vm->vecmap[i].txq_map = 0;
168*ca853deeSEric Joyner 	vm->vecmap[i].rxq_map = 0;
169*ca853deeSEric Joyner 	vm->vecmap[i].rxitr_idx = 0;
170*ca853deeSEric Joyner 	vm->vecmap[i].txitr_idx = 0;
171*ca853deeSEric Joyner 
172*ca853deeSEric Joyner 	iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_IRQ_MAP,
173*ca853deeSEric Joyner 	    (u8 *)vm, len);
174*ca853deeSEric Joyner 	free(vm, M_IAVF);
175*ca853deeSEric Joyner 
176*ca853deeSEric Joyner 	return (0);
177*ca853deeSEric Joyner }
178