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