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