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
32 /**
33 * @file iavf_vc_iflib.c
34 * @brief iflib-specific Virtchnl interface functions
35 *
36 * Contains functions implementing the virtchnl interface for communicating
37 * with the PF driver. This file contains definitions specific to the iflib
38 * driver implementation.
39 */
40
41 #include "iavf_iflib.h"
42 #include "iavf_vc_common.h"
43
44 /**
45 * iavf_configure_queues - Configure queues
46 * @sc: device softc
47 *
48 * Request that the PF set up our queues.
49 *
50 * @returns zero on success, or an error code on failure.
51 */
52 int
iavf_configure_queues(struct iavf_sc * sc)53 iavf_configure_queues(struct iavf_sc *sc)
54 {
55 device_t dev = sc->dev;
56 struct iavf_vsi *vsi = &sc->vsi;
57 if_softc_ctx_t scctx = iflib_get_softc_ctx(vsi->ctx);
58 struct iavf_tx_queue *tx_que = vsi->tx_queues;
59 struct iavf_rx_queue *rx_que = vsi->rx_queues;
60 struct tx_ring *txr;
61 struct rx_ring *rxr;
62 int len, pairs;
63
64 struct virtchnl_vsi_queue_config_info *vqci;
65 struct virtchnl_queue_pair_info *vqpi;
66
67 /* XXX: Linux PF driver wants matching ids in each tx/rx struct, so both TX/RX
68 * queues of a pair need to be configured */
69 pairs = max(vsi->num_tx_queues, vsi->num_rx_queues);
70 len = sizeof(struct virtchnl_vsi_queue_config_info) +
71 (sizeof(struct virtchnl_queue_pair_info) * pairs);
72 vqci = malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
73 if (!vqci) {
74 device_printf(dev, "%s: unable to allocate memory\n", __func__);
75 return (ENOMEM);
76 }
77 vqci->vsi_id = sc->vsi_res->vsi_id;
78 vqci->num_queue_pairs = pairs;
79 vqpi = vqci->qpair;
80 /* Size check is not needed here - HW max is 16 queue pairs, and we
81 * can fit info for 31 of them into the AQ buffer before it overflows.
82 */
83 // TODO: the above is wrong now; X722 VFs can have 256 queues
84 for (int i = 0; i < pairs; i++, tx_que++, rx_que++, vqpi++) {
85 txr = &tx_que->txr;
86 rxr = &rx_que->rxr;
87
88 vqpi->txq.vsi_id = vqci->vsi_id;
89 vqpi->txq.queue_id = i;
90 vqpi->txq.ring_len = scctx->isc_ntxd[0];
91 vqpi->txq.dma_ring_addr = txr->tx_paddr;
92 /* Enable Head writeback */
93 if (!vsi->enable_head_writeback) {
94 vqpi->txq.headwb_enabled = 0;
95 vqpi->txq.dma_headwb_addr = 0;
96 } else {
97 vqpi->txq.headwb_enabled = 1;
98 vqpi->txq.dma_headwb_addr = txr->tx_paddr +
99 sizeof(struct iavf_tx_desc) * scctx->isc_ntxd[0];
100 }
101
102 vqpi->rxq.vsi_id = vqci->vsi_id;
103 vqpi->rxq.queue_id = i;
104 vqpi->rxq.ring_len = scctx->isc_nrxd[0];
105 vqpi->rxq.dma_ring_addr = rxr->rx_paddr;
106 vqpi->rxq.max_pkt_size = scctx->isc_max_frame_size;
107 vqpi->rxq.databuffer_size = rxr->mbuf_sz;
108 vqpi->rxq.splithdr_enabled = 0;
109 }
110
111 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
112 (u8 *)vqci, len);
113 free(vqci, M_IAVF);
114
115 return (0);
116 }
117
118 /**
119 * iavf_map_queues - Map queues to interrupt vectors
120 * @sc: device softc
121 *
122 * Request that the PF map queues to interrupt vectors. Misc causes, including
123 * admin queue, are always mapped to vector 0.
124 *
125 * @returns zero on success, or an error code on failure.
126 */
127 int
iavf_map_queues(struct iavf_sc * sc)128 iavf_map_queues(struct iavf_sc *sc)
129 {
130 struct virtchnl_irq_map_info *vm;
131 int i, q, len;
132 struct iavf_vsi *vsi = &sc->vsi;
133 struct iavf_rx_queue *rx_que = vsi->rx_queues;
134 if_softc_ctx_t scctx = vsi->shared;
135 device_t dev = sc->dev;
136
137 // XXX: What happens if we only get 1 MSI-X vector?
138 MPASS(scctx->isc_vectors > 1);
139
140 /* How many queue vectors, adminq uses one */
141 // XXX: How do we know how many interrupt vectors we have?
142 q = scctx->isc_vectors - 1;
143
144 len = sizeof(struct virtchnl_irq_map_info) +
145 (scctx->isc_vectors * sizeof(struct virtchnl_vector_map));
146 vm = malloc(len, M_IAVF, M_NOWAIT);
147 if (!vm) {
148 device_printf(dev, "%s: unable to allocate memory\n", __func__);
149 return (ENOMEM);
150 }
151
152 vm->num_vectors = scctx->isc_vectors;
153 /* Queue vectors first */
154 for (i = 0; i < q; i++, rx_que++) {
155 vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id;
156 vm->vecmap[i].vector_id = i + 1; /* first is adminq */
157 // TODO: Re-examine this
158 vm->vecmap[i].txq_map = (1 << rx_que->rxr.me);
159 vm->vecmap[i].rxq_map = (1 << rx_que->rxr.me);
160 vm->vecmap[i].rxitr_idx = 0;
161 vm->vecmap[i].txitr_idx = 1;
162 }
163
164 /* Misc vector last - this is only for AdminQ messages */
165 vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id;
166 vm->vecmap[i].vector_id = 0;
167 vm->vecmap[i].txq_map = 0;
168 vm->vecmap[i].rxq_map = 0;
169 vm->vecmap[i].rxitr_idx = 0;
170 vm->vecmap[i].txitr_idx = 0;
171
172 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_IRQ_MAP,
173 (u8 *)vm, len);
174 free(vm, M_IAVF);
175
176 return (0);
177 }
178