Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2008-2019 Cisco Systems, Inc. All rights reserved.
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <stdio.h>
7 : :
8 : : #include <bus_pci_driver.h>
9 : : #include <rte_common.h>
10 : : #include <dev_driver.h>
11 : : #include <ethdev_driver.h>
12 : : #include <ethdev_pci.h>
13 : : #include <rte_flow_driver.h>
14 : : #include <rte_kvargs.h>
15 : : #include <rte_pci.h>
16 : : #include <rte_string_fns.h>
17 : :
18 : : #include "enic_compat.h"
19 : : #include "enic.h"
20 : : #include "vnic_dev.h"
21 : : #include "vnic_enet.h"
22 : : #include "vnic_intr.h"
23 : : #include "vnic_cq.h"
24 : : #include "vnic_wq.h"
25 : : #include "vnic_rq.h"
26 : :
27 : 0 : static uint16_t enic_vf_recv_pkts(void *rx_queue,
28 : : struct rte_mbuf **rx_pkts,
29 : : uint16_t nb_pkts)
30 : : {
31 : 0 : return enic_recv_pkts(rx_queue, rx_pkts, nb_pkts);
32 : : }
33 : :
34 : 0 : static uint16_t enic_vf_xmit_pkts(void *tx_queue,
35 : : struct rte_mbuf **tx_pkts,
36 : : uint16_t nb_pkts)
37 : : {
38 : 0 : return enic_xmit_pkts(tx_queue, tx_pkts, nb_pkts);
39 : : }
40 : :
41 : 0 : static int enic_vf_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
42 : : uint16_t queue_idx,
43 : : uint16_t nb_desc,
44 : : unsigned int socket_id,
45 : : const struct rte_eth_txconf *tx_conf)
46 : : {
47 : : struct enic_vf_representor *vf;
48 : : struct vnic_wq *wq;
49 : : struct enic *pf;
50 : : int err;
51 : :
52 : 0 : ENICPMD_FUNC_TRACE();
53 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
54 : : return -E_RTE_SECONDARY;
55 : : /* Only one queue now */
56 [ # # ]: 0 : if (queue_idx != 0)
57 : : return -EINVAL;
58 : 0 : vf = eth_dev->data->dev_private;
59 : 0 : pf = vf->pf;
60 : 0 : wq = &pf->wq[vf->pf_wq_idx];
61 : 0 : wq->offloads = tx_conf->offloads |
62 : 0 : eth_dev->data->dev_conf.txmode.offloads;
63 : 0 : eth_dev->data->tx_queues[0] = (void *)wq;
64 : : /* Pass vf not pf because of cq index calculation. See enic_alloc_wq */
65 : 0 : err = enic_alloc_wq(&vf->enic, queue_idx, socket_id, nb_desc);
66 [ # # ]: 0 : if (err) {
67 : 0 : ENICPMD_LOG(ERR, "error in allocating wq\n");
68 : 0 : return err;
69 : : }
70 : : return 0;
71 : : }
72 : :
73 : 0 : static void enic_vf_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
74 : : {
75 : 0 : void *txq = dev->data->tx_queues[qid];
76 : :
77 : 0 : ENICPMD_FUNC_TRACE();
78 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
79 : : return;
80 : 0 : enic_free_wq(txq);
81 : : }
82 : :
83 : 0 : static int enic_vf_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
84 : : uint16_t queue_idx,
85 : : uint16_t nb_desc,
86 : : unsigned int socket_id,
87 : : const struct rte_eth_rxconf *rx_conf,
88 : : struct rte_mempool *mp)
89 : : {
90 : : struct enic_vf_representor *vf;
91 : : struct enic *pf;
92 : : int ret;
93 : :
94 : 0 : ENICPMD_FUNC_TRACE();
95 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
96 : : return -E_RTE_SECONDARY;
97 : : /* Only 1 queue now */
98 [ # # ]: 0 : if (queue_idx != 0)
99 : : return -EINVAL;
100 : 0 : vf = eth_dev->data->dev_private;
101 : 0 : pf = vf->pf;
102 : 0 : eth_dev->data->rx_queues[queue_idx] =
103 : 0 : (void *)&pf->rq[vf->pf_rq_sop_idx];
104 : 0 : ret = enic_alloc_rq(&vf->enic, queue_idx, socket_id, mp, nb_desc,
105 : 0 : rx_conf->rx_free_thresh);
106 [ # # ]: 0 : if (ret) {
107 : 0 : ENICPMD_LOG(ERR, "error in allocating rq\n");
108 : 0 : return ret;
109 : : }
110 : : return 0;
111 : : }
112 : :
113 : 0 : static void enic_vf_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
114 : : {
115 : 0 : void *rxq = dev->data->rx_queues[qid];
116 : :
117 : 0 : ENICPMD_FUNC_TRACE();
118 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
119 : : return;
120 : 0 : enic_free_rq(rxq);
121 : : }
122 : :
123 : 0 : static int enic_vf_dev_configure(struct rte_eth_dev *eth_dev __rte_unused)
124 : : {
125 : 0 : ENICPMD_FUNC_TRACE();
126 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
127 : 0 : return -E_RTE_SECONDARY;
128 : : return 0;
129 : : }
130 : :
131 : : static int
132 : 0 : setup_rep_vf_fwd(struct enic_vf_representor *vf)
133 : : {
134 : : int ret;
135 : :
136 : 0 : ENICPMD_FUNC_TRACE();
137 : : /* Representor -> VF rule
138 : : * Egress packets from this representor are on the representor's WQ.
139 : : * So, loop back that WQ to VF.
140 : : */
141 : 0 : ret = enic_fm_add_rep2vf_flow(vf);
142 [ # # ]: 0 : if (ret) {
143 : 0 : ENICPMD_LOG(ERR, "Cannot create representor->VF flow");
144 : 0 : return ret;
145 : : }
146 : : /* VF -> representor rule
147 : : * Packets from VF loop back to the representor, unless they match
148 : : * user-added flows.
149 : : */
150 : 0 : ret = enic_fm_add_vf2rep_flow(vf);
151 [ # # ]: 0 : if (ret) {
152 : 0 : ENICPMD_LOG(ERR, "Cannot create VF->representor flow");
153 : 0 : return ret;
154 : : }
155 : : return 0;
156 : : }
157 : :
158 : 0 : static int enic_vf_dev_start(struct rte_eth_dev *eth_dev)
159 : : {
160 : : struct enic_vf_representor *vf;
161 : : struct vnic_rq *data_rq;
162 : : int index, cq_idx;
163 : : struct enic *pf;
164 : : int ret;
165 : :
166 : 0 : ENICPMD_FUNC_TRACE();
167 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
168 : : return -E_RTE_SECONDARY;
169 : :
170 : 0 : vf = eth_dev->data->dev_private;
171 : 0 : pf = vf->pf;
172 : : /* Get representor flowman for flow API and representor path */
173 : 0 : ret = enic_fm_init(&vf->enic);
174 [ # # ]: 0 : if (ret)
175 : : return ret;
176 : : /* Set up implicit flow rules to forward between representor and VF */
177 : 0 : ret = setup_rep_vf_fwd(vf);
178 [ # # ]: 0 : if (ret) {
179 : 0 : ENICPMD_LOG(ERR, "Cannot set up representor-VF flows");
180 : 0 : return ret;
181 : : }
182 : : /* Remove all packet filters so no ingress packets go to VF.
183 : : * When PF enables switchdev, it will ensure packet filters
184 : : * are removed. So, this is not technically needed.
185 : : */
186 : 0 : ENICPMD_LOG(DEBUG, "Clear packet filters");
187 : 0 : ret = vnic_dev_packet_filter(vf->enic.vdev, 0, 0, 0, 0, 0);
188 [ # # ]: 0 : if (ret) {
189 : 0 : ENICPMD_LOG(ERR, "Cannot clear packet filters");
190 : 0 : return ret;
191 : : }
192 : :
193 : : /* Start WQ: see enic_init_vnic_resources */
194 : 0 : index = vf->pf_wq_idx;
195 : 0 : cq_idx = vf->pf_wq_cq_idx;
196 : 0 : vnic_wq_init(&pf->wq[index], cq_idx, 1, 0);
197 : 0 : vnic_cq_init(&pf->cq[cq_idx],
198 : : 0 /* flow_control_enable */,
199 : : 1 /* color_enable */,
200 : : 0 /* cq_head */,
201 : : 0 /* cq_tail */,
202 : : 1 /* cq_tail_color */,
203 : : 0 /* interrupt_enable */,
204 : : 0 /* cq_entry_enable */,
205 : : 1 /* cq_message_enable */,
206 : : 0 /* interrupt offset */,
207 : 0 : (uint64_t)pf->wq[index].cqmsg_rz->iova);
208 : : /* enic_start_wq */
209 : 0 : vnic_wq_enable(&pf->wq[index]);
210 : 0 : eth_dev->data->tx_queue_state[0] = RTE_ETH_QUEUE_STATE_STARTED;
211 : :
212 : : /* Start RQ: see enic_init_vnic_resources */
213 : 0 : index = vf->pf_rq_sop_idx;
214 : 0 : cq_idx = enic_cq_rq(vf->pf, index);
215 : 0 : vnic_rq_init(&pf->rq[index], cq_idx, 1, 0);
216 : 0 : data_rq = &pf->rq[vf->pf_rq_data_idx];
217 [ # # ]: 0 : if (data_rq->in_use)
218 : 0 : vnic_rq_init(data_rq, cq_idx, 1, 0);
219 : 0 : vnic_cq_init(&pf->cq[cq_idx],
220 : : 0 /* flow_control_enable */,
221 : : 1 /* color_enable */,
222 : : 0 /* cq_head */,
223 : : 0 /* cq_tail */,
224 : : 1 /* cq_tail_color */,
225 : : 0,
226 : : 1 /* cq_entry_enable */,
227 : : 0 /* cq_message_enable */,
228 : : 0,
229 : : 0 /* cq_message_addr */);
230 : : /* enic_enable */
231 : 0 : ret = enic_alloc_rx_queue_mbufs(pf, &pf->rq[index]);
232 [ # # ]: 0 : if (ret) {
233 : 0 : ENICPMD_LOG(ERR, "Failed to alloc sop RX queue mbufs\n");
234 : 0 : return ret;
235 : : }
236 : 0 : ret = enic_alloc_rx_queue_mbufs(pf, data_rq);
237 [ # # ]: 0 : if (ret) {
238 : : /* Release the allocated mbufs for the sop rq*/
239 : 0 : enic_rxmbuf_queue_release(pf, &pf->rq[index]);
240 : 0 : ENICPMD_LOG(ERR, "Failed to alloc data RX queue mbufs\n");
241 : 0 : return ret;
242 : : }
243 : 0 : enic_start_rq(pf, vf->pf_rq_sop_idx);
244 : 0 : eth_dev->data->tx_queue_state[0] = RTE_ETH_QUEUE_STATE_STARTED;
245 : 0 : eth_dev->data->rx_queue_state[0] = RTE_ETH_QUEUE_STATE_STARTED;
246 : 0 : return 0;
247 : : }
248 : :
249 : 0 : static int enic_vf_dev_stop(struct rte_eth_dev *eth_dev)
250 : : {
251 : : struct enic_vf_representor *vf;
252 : : struct vnic_rq *rq;
253 : : struct enic *pf;
254 : :
255 : 0 : ENICPMD_FUNC_TRACE();
256 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
257 : : return 0;
258 : : /* Undo dev_start. Disable/clean WQ */
259 : 0 : vf = eth_dev->data->dev_private;
260 : 0 : pf = vf->pf;
261 : 0 : vnic_wq_disable(&pf->wq[vf->pf_wq_idx]);
262 : 0 : vnic_wq_clean(&pf->wq[vf->pf_wq_idx], enic_free_wq_buf);
263 : 0 : vnic_cq_clean(&pf->cq[vf->pf_wq_cq_idx]);
264 : : /* Disable/clean RQ */
265 : 0 : rq = &pf->rq[vf->pf_rq_sop_idx];
266 : 0 : vnic_rq_disable(rq);
267 : 0 : vnic_rq_clean(rq, enic_free_rq_buf);
268 : 0 : rq = &pf->rq[vf->pf_rq_data_idx];
269 [ # # ]: 0 : if (rq->in_use) {
270 : 0 : vnic_rq_disable(rq);
271 : 0 : vnic_rq_clean(rq, enic_free_rq_buf);
272 : : }
273 : 0 : vnic_cq_clean(&pf->cq[enic_cq_rq(vf->pf, vf->pf_rq_sop_idx)]);
274 : 0 : eth_dev->data->tx_queue_state[0] = RTE_ETH_QUEUE_STATE_STOPPED;
275 : 0 : eth_dev->data->rx_queue_state[0] = RTE_ETH_QUEUE_STATE_STOPPED;
276 : : /* Clean up representor flowman */
277 : 0 : enic_fm_destroy(&vf->enic);
278 : :
279 : 0 : return 0;
280 : : }
281 : :
282 : : /*
283 : : * "close" is no-op for now and solely exists so that rte_eth_dev_close()
284 : : * can finish its own cleanup without errors.
285 : : */
286 : 0 : static int enic_vf_dev_close(struct rte_eth_dev *eth_dev __rte_unused)
287 : : {
288 : 0 : ENICPMD_FUNC_TRACE();
289 : 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
290 : : return 0;
291 : : return 0;
292 : : }
293 : :
294 : : static int
295 : 0 : adjust_flow_attr(const struct rte_flow_attr *attrs,
296 : : struct rte_flow_attr *vf_attrs,
297 : : struct rte_flow_error *error)
298 : : {
299 [ # # ]: 0 : if (!attrs) {
300 : 0 : return rte_flow_error_set(error, EINVAL,
301 : : RTE_FLOW_ERROR_TYPE_ATTR,
302 : : NULL, "no attribute specified");
303 : : }
304 : : /*
305 : : * Swap ingress and egress as the firmware view of direction
306 : : * is the opposite of the representor.
307 : : */
308 : 0 : *vf_attrs = *attrs;
309 [ # # ]: 0 : if (attrs->ingress && !attrs->egress) {
310 : 0 : vf_attrs->ingress = 0;
311 : 0 : vf_attrs->egress = 1;
312 : 0 : return 0;
313 : : }
314 : 0 : return rte_flow_error_set(error, ENOTSUP,
315 : : RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
316 : : "representor only supports ingress");
317 : : }
318 : :
319 : : static int
320 : 0 : enic_vf_flow_validate(struct rte_eth_dev *dev,
321 : : const struct rte_flow_attr *attrs,
322 : : const struct rte_flow_item pattern[],
323 : : const struct rte_flow_action actions[],
324 : : struct rte_flow_error *error)
325 : : {
326 : : struct rte_flow_attr vf_attrs;
327 : : int ret;
328 : :
329 : 0 : ret = adjust_flow_attr(attrs, &vf_attrs, error);
330 [ # # ]: 0 : if (ret)
331 : : return ret;
332 : : attrs = &vf_attrs;
333 : 0 : return enic_fm_flow_ops.validate(dev, attrs, pattern, actions, error);
334 : : }
335 : :
336 : : static struct rte_flow *
337 : 0 : enic_vf_flow_create(struct rte_eth_dev *dev,
338 : : const struct rte_flow_attr *attrs,
339 : : const struct rte_flow_item pattern[],
340 : : const struct rte_flow_action actions[],
341 : : struct rte_flow_error *error)
342 : : {
343 : : struct rte_flow_attr vf_attrs;
344 : :
345 [ # # ]: 0 : if (adjust_flow_attr(attrs, &vf_attrs, error))
346 : : return NULL;
347 : : attrs = &vf_attrs;
348 : 0 : return enic_fm_flow_ops.create(dev, attrs, pattern, actions, error);
349 : : }
350 : :
351 : : static int
352 : 0 : enic_vf_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
353 : : struct rte_flow_error *error)
354 : : {
355 : 0 : return enic_fm_flow_ops.destroy(dev, flow, error);
356 : : }
357 : :
358 : : static int
359 : 0 : enic_vf_flow_query(struct rte_eth_dev *dev,
360 : : struct rte_flow *flow,
361 : : const struct rte_flow_action *actions,
362 : : void *data,
363 : : struct rte_flow_error *error)
364 : : {
365 : 0 : return enic_fm_flow_ops.query(dev, flow, actions, data, error);
366 : : }
367 : :
368 : : static int
369 : 0 : enic_vf_flow_flush(struct rte_eth_dev *dev,
370 : : struct rte_flow_error *error)
371 : : {
372 : 0 : return enic_fm_flow_ops.flush(dev, error);
373 : : }
374 : :
375 : : static const struct rte_flow_ops enic_vf_flow_ops = {
376 : : .validate = enic_vf_flow_validate,
377 : : .create = enic_vf_flow_create,
378 : : .destroy = enic_vf_flow_destroy,
379 : : .flush = enic_vf_flow_flush,
380 : : .query = enic_vf_flow_query,
381 : : };
382 : :
383 : : static int
384 : 0 : enic_vf_flow_ops_get(struct rte_eth_dev *eth_dev,
385 : : const struct rte_flow_ops **ops)
386 : : {
387 : : struct enic_vf_representor *vf;
388 : :
389 : 0 : ENICPMD_FUNC_TRACE();
390 : 0 : vf = eth_dev->data->dev_private;
391 [ # # ]: 0 : if (vf->enic.flow_filter_mode != FILTER_FLOWMAN) {
392 : 0 : ENICPMD_LOG(WARNING,
393 : : "VF representors require flowman support for rte_flow API");
394 : 0 : return -EINVAL;
395 : : }
396 : :
397 : 0 : *ops = &enic_vf_flow_ops;
398 : 0 : return 0;
399 : : }
400 : :
401 : 0 : static int enic_vf_link_update(struct rte_eth_dev *eth_dev,
402 : : int wait_to_complete __rte_unused)
403 : : {
404 : : struct enic_vf_representor *vf;
405 : : struct rte_eth_link link;
406 : : struct enic *pf;
407 : :
408 : 0 : ENICPMD_FUNC_TRACE();
409 : 0 : vf = eth_dev->data->dev_private;
410 : 0 : pf = vf->pf;
411 : : /*
412 : : * Link status and speed are same as PF. Update PF status and then
413 : : * copy it to VF.
414 : : */
415 : 0 : enic_link_update(pf->rte_dev);
416 : 0 : rte_eth_linkstatus_get(pf->rte_dev, &link);
417 : 0 : rte_eth_linkstatus_set(eth_dev, &link);
418 : 0 : return 0;
419 : : }
420 : :
421 : 0 : static int enic_vf_stats_get(struct rte_eth_dev *eth_dev,
422 : : struct rte_eth_stats *stats)
423 : : {
424 : : struct enic_vf_representor *vf;
425 : : struct vnic_stats *vs;
426 : : int err;
427 : :
428 : 0 : ENICPMD_FUNC_TRACE();
429 : 0 : vf = eth_dev->data->dev_private;
430 : : /* Get VF stats via PF */
431 : 0 : err = vnic_dev_stats_dump(vf->enic.vdev, &vs);
432 [ # # ]: 0 : if (err) {
433 : 0 : ENICPMD_LOG(ERR, "error in getting stats\n");
434 : 0 : return err;
435 : : }
436 : 0 : stats->ipackets = vs->rx.rx_frames_ok;
437 : 0 : stats->opackets = vs->tx.tx_frames_ok;
438 : 0 : stats->ibytes = vs->rx.rx_bytes_ok;
439 : 0 : stats->obytes = vs->tx.tx_bytes_ok;
440 : 0 : stats->ierrors = vs->rx.rx_errors + vs->rx.rx_drop;
441 : 0 : stats->oerrors = vs->tx.tx_errors;
442 : 0 : stats->imissed = vs->rx.rx_no_bufs;
443 : 0 : return 0;
444 : : }
445 : :
446 : 0 : static int enic_vf_stats_reset(struct rte_eth_dev *eth_dev)
447 : : {
448 : : struct enic_vf_representor *vf;
449 : : int err;
450 : :
451 : 0 : ENICPMD_FUNC_TRACE();
452 : 0 : vf = eth_dev->data->dev_private;
453 : : /* Ask PF to clear VF stats */
454 : 0 : err = vnic_dev_stats_clear(vf->enic.vdev);
455 [ # # ]: 0 : if (err)
456 : 0 : ENICPMD_LOG(ERR, "error in clearing stats\n");
457 : 0 : return err;
458 : : }
459 : :
460 : 0 : static int enic_vf_dev_infos_get(struct rte_eth_dev *eth_dev,
461 : : struct rte_eth_dev_info *device_info)
462 : : {
463 : : struct enic_vf_representor *vf;
464 : : struct enic *pf;
465 : :
466 : 0 : ENICPMD_FUNC_TRACE();
467 : 0 : vf = eth_dev->data->dev_private;
468 : 0 : pf = vf->pf;
469 : 0 : device_info->max_rx_queues = eth_dev->data->nb_rx_queues;
470 : 0 : device_info->max_tx_queues = eth_dev->data->nb_tx_queues;
471 : 0 : device_info->min_rx_bufsize = ENIC_MIN_MTU;
472 : : /* Max packet size is same as PF */
473 : 0 : device_info->max_rx_pktlen = enic_mtu_to_max_rx_pktlen(pf->max_mtu);
474 : 0 : device_info->max_mac_addrs = ENIC_UNICAST_PERFECT_FILTERS;
475 : : /* No offload capa, RSS, etc. until Tx/Rx handlers are added */
476 : 0 : device_info->rx_offload_capa = 0;
477 : 0 : device_info->tx_offload_capa = 0;
478 : 0 : device_info->switch_info.name = pf->rte_dev->device->name;
479 : 0 : device_info->switch_info.domain_id = vf->switch_domain_id;
480 : 0 : device_info->switch_info.port_id = vf->vf_id;
481 : 0 : return 0;
482 : : }
483 : :
484 : 0 : static void set_vf_packet_filter(struct enic_vf_representor *vf)
485 : : {
486 : : /* switchdev: packet filters are ignored */
487 [ # # ]: 0 : if (vf->enic.switchdev_mode)
488 : : return;
489 : : /* Ask PF to apply filters on VF */
490 : 0 : vnic_dev_packet_filter(vf->enic.vdev, 1 /* unicast */, 1 /* mcast */,
491 : : 1 /* bcast */, vf->promisc, vf->allmulti);
492 : : }
493 : :
494 : 0 : static int enic_vf_promiscuous_enable(struct rte_eth_dev *eth_dev)
495 : : {
496 : : struct enic_vf_representor *vf;
497 : :
498 : 0 : ENICPMD_FUNC_TRACE();
499 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
500 : : return -E_RTE_SECONDARY;
501 : 0 : vf = eth_dev->data->dev_private;
502 : 0 : vf->promisc = 1;
503 : 0 : set_vf_packet_filter(vf);
504 : 0 : return 0;
505 : : }
506 : :
507 : 0 : static int enic_vf_promiscuous_disable(struct rte_eth_dev *eth_dev)
508 : : {
509 : : struct enic_vf_representor *vf;
510 : :
511 : 0 : ENICPMD_FUNC_TRACE();
512 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
513 : : return -E_RTE_SECONDARY;
514 : 0 : vf = eth_dev->data->dev_private;
515 : 0 : vf->promisc = 0;
516 : 0 : set_vf_packet_filter(vf);
517 : 0 : return 0;
518 : : }
519 : :
520 : 0 : static int enic_vf_allmulticast_enable(struct rte_eth_dev *eth_dev)
521 : : {
522 : : struct enic_vf_representor *vf;
523 : :
524 : 0 : ENICPMD_FUNC_TRACE();
525 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
526 : : return -E_RTE_SECONDARY;
527 : 0 : vf = eth_dev->data->dev_private;
528 : 0 : vf->allmulti = 1;
529 : 0 : set_vf_packet_filter(vf);
530 : 0 : return 0;
531 : : }
532 : :
533 : 0 : static int enic_vf_allmulticast_disable(struct rte_eth_dev *eth_dev)
534 : : {
535 : : struct enic_vf_representor *vf;
536 : :
537 : 0 : ENICPMD_FUNC_TRACE();
538 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
539 : : return -E_RTE_SECONDARY;
540 : 0 : vf = eth_dev->data->dev_private;
541 : 0 : vf->allmulti = 0;
542 : 0 : set_vf_packet_filter(vf);
543 : 0 : return 0;
544 : : }
545 : :
546 : : /*
547 : : * A minimal set of handlers.
548 : : * The representor can get/set a small set of VF settings via "proxy" devcmd.
549 : : * With proxy devcmd, the PF driver basically tells the VIC firmware to
550 : : * "perform this devcmd on that VF".
551 : : */
552 : : static const struct eth_dev_ops enic_vf_representor_dev_ops = {
553 : : .allmulticast_enable = enic_vf_allmulticast_enable,
554 : : .allmulticast_disable = enic_vf_allmulticast_disable,
555 : : .dev_configure = enic_vf_dev_configure,
556 : : .dev_infos_get = enic_vf_dev_infos_get,
557 : : .dev_start = enic_vf_dev_start,
558 : : .dev_stop = enic_vf_dev_stop,
559 : : .dev_close = enic_vf_dev_close,
560 : : .flow_ops_get = enic_vf_flow_ops_get,
561 : : .link_update = enic_vf_link_update,
562 : : .promiscuous_enable = enic_vf_promiscuous_enable,
563 : : .promiscuous_disable = enic_vf_promiscuous_disable,
564 : : .stats_get = enic_vf_stats_get,
565 : : .stats_reset = enic_vf_stats_reset,
566 : : .rx_queue_setup = enic_vf_dev_rx_queue_setup,
567 : : .rx_queue_release = enic_vf_dev_rx_queue_release,
568 : : .tx_queue_setup = enic_vf_dev_tx_queue_setup,
569 : : .tx_queue_release = enic_vf_dev_tx_queue_release,
570 : : };
571 : :
572 : 0 : static int get_vf_config(struct enic_vf_representor *vf)
573 : : {
574 : : struct vnic_enet_config *c;
575 : : struct enic *pf;
576 : : int switch_mtu;
577 : : int err;
578 : :
579 : : c = &vf->config;
580 : 0 : pf = vf->pf;
581 : : /* VF MAC */
582 : 0 : err = vnic_dev_get_mac_addr(vf->enic.vdev, vf->mac_addr.addr_bytes);
583 [ # # ]: 0 : if (err) {
584 : 0 : ENICPMD_LOG(ERR, "error in getting MAC address\n");
585 : 0 : return err;
586 : : }
587 : 0 : rte_ether_addr_copy(&vf->mac_addr, vf->eth_dev->data->mac_addrs);
588 : :
589 : : /* VF MTU per its vNIC setting */
590 : 0 : err = vnic_dev_spec(vf->enic.vdev,
591 : : offsetof(struct vnic_enet_config, mtu),
592 : 0 : sizeof(c->mtu), &c->mtu);
593 [ # # ]: 0 : if (err) {
594 : 0 : ENICPMD_LOG(ERR, "error in getting MTU\n");
595 : 0 : return err;
596 : : }
597 : : /*
598 : : * Blade switch (fabric interconnect) port's MTU. Assume the kernel
599 : : * enic driver runs on VF. That driver automatically adjusts its MTU
600 : : * according to the switch MTU.
601 : : */
602 : 0 : switch_mtu = vnic_dev_mtu(pf->vdev);
603 : 0 : vf->eth_dev->data->mtu = c->mtu;
604 [ # # ]: 0 : if (switch_mtu > c->mtu)
605 : 0 : vf->eth_dev->data->mtu = RTE_MIN(ENIC_MAX_MTU, switch_mtu);
606 : : return 0;
607 : : }
608 : :
609 : 0 : int enic_vf_representor_init(struct rte_eth_dev *eth_dev, void *init_params)
610 : : {
611 : : struct enic_vf_representor *vf, *params;
612 : : struct rte_pci_device *pdev;
613 : : struct enic *pf, *vf_enic;
614 : : struct rte_pci_addr *addr;
615 : : int ret;
616 : :
617 : 0 : ENICPMD_FUNC_TRACE();
618 : : params = init_params;
619 : 0 : vf = eth_dev->data->dev_private;
620 : 0 : vf->switch_domain_id = params->switch_domain_id;
621 : 0 : vf->vf_id = params->vf_id;
622 : 0 : vf->eth_dev = eth_dev;
623 : 0 : vf->pf = params->pf;
624 : 0 : vf->allmulti = 1;
625 : 0 : vf->promisc = 0;
626 : : pf = vf->pf;
627 : 0 : vf->enic.switchdev_mode = pf->switchdev_mode;
628 : : /* Only switchdev is supported now */
629 : : RTE_ASSERT(vf->enic.switchdev_mode);
630 : : /* Allocate WQ, RQ, CQ for the representor */
631 : 0 : vf->pf_wq_idx = vf_wq_idx(vf);
632 : 0 : vf->pf_wq_cq_idx = vf_wq_cq_idx(vf);
633 : 0 : vf->pf_rq_sop_idx = vf_rq_sop_idx(vf);
634 : 0 : vf->pf_rq_data_idx = vf_rq_data_idx(vf);
635 : : /* Remove these assertions once queue allocation has an easy-to-use
636 : : * allocator API instead of index number calculations used throughout
637 : : * the driver..
638 : : */
639 : : RTE_ASSERT(enic_cq_rq(pf, vf->pf_rq_sop_idx) == vf->pf_rq_sop_idx);
640 : : RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(vf->pf_rq_sop_idx) ==
641 : : vf->pf_rq_sop_idx);
642 : : /* RX handlers use enic_cq_rq(sop) to get CQ, so do not save it */
643 : 0 : pf->vf_required_wq++;
644 : 0 : pf->vf_required_rq += 2; /* sop and data */
645 : 0 : pf->vf_required_cq += 2; /* 1 for rq sop and 1 for wq */
646 : 0 : ENICPMD_LOG(DEBUG, "vf_id %u wq %u rq_sop %u rq_data %u wq_cq %u rq_cq %u",
647 : : vf->vf_id, vf->pf_wq_idx, vf->pf_rq_sop_idx, vf->pf_rq_data_idx,
648 : : vf->pf_wq_cq_idx, enic_cq_rq(pf, vf->pf_rq_sop_idx));
649 [ # # ]: 0 : if (enic_cq_rq(pf, vf->pf_rq_sop_idx) >= pf->conf_cq_count) {
650 : 0 : ENICPMD_LOG(ERR, "Insufficient CQs. Please ensure number of CQs (%u)"
651 : : " >= number of RQs (%u) in CIMC or UCSM",
652 : : pf->conf_cq_count, pf->conf_rq_count);
653 : 0 : return -EINVAL;
654 : : }
655 : :
656 : : /* Check for non-existent VFs */
657 : 0 : pdev = RTE_ETH_DEV_TO_PCI(pf->rte_dev);
658 [ # # ]: 0 : if (vf->vf_id >= pdev->max_vfs) {
659 : 0 : ENICPMD_LOG(ERR, "VF ID is invalid. vf_id %u max_vfs %u",
660 : : vf->vf_id, pdev->max_vfs);
661 : 0 : return -ENODEV;
662 : : }
663 : :
664 : 0 : eth_dev->device->driver = pf->rte_dev->device->driver;
665 : 0 : eth_dev->dev_ops = &enic_vf_representor_dev_ops;
666 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
667 : 0 : eth_dev->data->representor_id = vf->vf_id;
668 : 0 : eth_dev->data->backer_port_id = pf->port_id;
669 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("enic_mac_addr_vf",
670 : : sizeof(struct rte_ether_addr) *
671 : : ENIC_UNICAST_PERFECT_FILTERS, 0);
672 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL)
673 : : return -ENOMEM;
674 : : /* Use 1 RX queue and 1 TX queue for representor path */
675 : 0 : eth_dev->data->nb_rx_queues = 1;
676 : 0 : eth_dev->data->nb_tx_queues = 1;
677 : 0 : eth_dev->rx_pkt_burst = &enic_vf_recv_pkts;
678 : 0 : eth_dev->tx_pkt_burst = &enic_vf_xmit_pkts;
679 : : /* Initial link state copied from PF */
680 : 0 : eth_dev->data->dev_link = pf->rte_dev->data->dev_link;
681 : : /* Representor vdev to perform devcmd */
682 : 0 : vf->enic.vdev = vnic_vf_rep_register(&vf->enic, pf->vdev, vf->vf_id);
683 [ # # ]: 0 : if (vf->enic.vdev == NULL)
684 : : return -ENOMEM;
685 : 0 : ret = vnic_dev_alloc_stats_mem(vf->enic.vdev);
686 [ # # ]: 0 : if (ret)
687 : : return ret;
688 : : /* Get/copy VF vNIC MAC, MTU, etc. into eth_dev */
689 : 0 : ret = get_vf_config(vf);
690 [ # # ]: 0 : if (ret)
691 : : return ret;
692 : :
693 : : /*
694 : : * Calculate VF BDF. The firmware ensures that PF BDF is always
695 : : * bus:dev.0, and VF BDFs are dev.1, dev.2, and so on.
696 : : */
697 : 0 : vf->bdf = pdev->addr;
698 : 0 : vf->bdf.function += vf->vf_id + 1;
699 : :
700 : : /* Copy a few fields used by enic_fm_flow */
701 : : vf_enic = &vf->enic;
702 : 0 : vf_enic->switch_domain_id = vf->switch_domain_id;
703 : 0 : vf_enic->flow_filter_mode = pf->flow_filter_mode;
704 : 0 : vf_enic->rte_dev = eth_dev;
705 : 0 : vf_enic->dev_data = eth_dev->data;
706 : 0 : LIST_INIT(&vf_enic->flows);
707 : 0 : LIST_INIT(&vf_enic->memzone_list);
708 : : rte_spinlock_init(&vf_enic->memzone_list_lock);
709 : : addr = &vf->bdf;
710 : 0 : snprintf(vf_enic->bdf_name, PCI_PRI_STR_SIZE, PCI_PRI_FMT,
711 : 0 : addr->domain, addr->bus, addr->devid, addr->function);
712 : 0 : return 0;
713 : : }
714 : :
715 : 0 : int enic_vf_representor_uninit(struct rte_eth_dev *eth_dev)
716 : : {
717 : : struct enic_vf_representor *vf;
718 : :
719 : 0 : ENICPMD_FUNC_TRACE();
720 : 0 : vf = eth_dev->data->dev_private;
721 : 0 : vnic_dev_unregister(vf->enic.vdev);
722 : 0 : return 0;
723 : : }
|