Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2022 Advanced Micro Devices, Inc.
3 : : */
4 : :
5 : : #include <rte_malloc.h>
6 : : #include <ethdev_driver.h>
7 : :
8 : : #include "ionic.h"
9 : : #include "ionic_logs.h"
10 : : #include "ionic_lif.h"
11 : : #include "ionic_ethdev.h"
12 : : #include "ionic_rx_filter.h"
13 : : #include "ionic_rxtx.h"
14 : :
15 : : /* queuetype support level */
16 : : static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = {
17 : : [IONIC_QTYPE_ADMINQ] = 0, /* 0 = Base version with CQ support */
18 : : [IONIC_QTYPE_NOTIFYQ] = 0, /* 0 = Base version */
19 : : [IONIC_QTYPE_RXQ] = 2, /* 0 = Base version with CQ+SG support
20 : : * 1 = ... with EQ
21 : : * 2 = ... with CMB
22 : : */
23 : : [IONIC_QTYPE_TXQ] = 3, /* 0 = Base version with CQ+SG support
24 : : * 1 = ... with Tx SG version 1
25 : : * 2 = ... with EQ
26 : : * 3 = ... with CMB
27 : : */
28 : : };
29 : :
30 : : static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
31 : : static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
32 : :
33 : : static int
34 : 0 : ionic_qcq_disable(struct ionic_qcq *qcq)
35 : : {
36 : : struct ionic_queue *q = &qcq->q;
37 : 0 : struct ionic_lif *lif = qcq->lif;
38 : 0 : struct ionic_admin_ctx ctx = {
39 : : .pending_work = true,
40 : : .cmd.q_control = {
41 : : .opcode = IONIC_CMD_Q_CONTROL,
42 : 0 : .type = q->type,
43 : 0 : .index = rte_cpu_to_le_32(q->index),
44 : : .oper = IONIC_Q_DISABLE,
45 : : },
46 : : };
47 : :
48 : 0 : return ionic_adminq_post_wait(lif, &ctx);
49 : : }
50 : :
51 : : void
52 : 0 : ionic_lif_stop(struct ionic_lif *lif)
53 : : {
54 : : uint32_t i;
55 : :
56 : 0 : IONIC_PRINT_CALL();
57 : :
58 : 0 : lif->state &= ~IONIC_LIF_F_UP;
59 : :
60 [ # # ]: 0 : for (i = 0; i < lif->nrxqcqs; i++) {
61 : 0 : struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
62 [ # # ]: 0 : if (rxq->flags & IONIC_QCQ_F_INITED)
63 : 0 : (void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
64 : : }
65 : :
66 [ # # ]: 0 : for (i = 0; i < lif->ntxqcqs; i++) {
67 : 0 : struct ionic_tx_qcq *txq = lif->txqcqs[i];
68 [ # # ]: 0 : if (txq->flags & IONIC_QCQ_F_INITED)
69 : 0 : (void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
70 : : }
71 : 0 : }
72 : :
73 : : void
74 : 0 : ionic_lif_reset(struct ionic_lif *lif)
75 : : {
76 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
77 : : int err;
78 : :
79 : 0 : IONIC_PRINT_CALL();
80 : :
81 : 0 : ionic_dev_cmd_lif_reset(idev);
82 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
83 [ # # ]: 0 : if (err)
84 : 0 : IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
85 : 0 : }
86 : :
87 : : static void
88 : 0 : ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
89 : : {
90 : 0 : struct ionic_lif_stats *ls = &lif->info->stats;
91 : : uint32_t i;
92 : 0 : uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
93 : : RTE_ETHDEV_QUEUE_STAT_CNTRS);
94 : 0 : uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
95 : : RTE_ETHDEV_QUEUE_STAT_CNTRS);
96 : :
97 : : memset(stats, 0, sizeof(*stats));
98 : :
99 : : if (ls == NULL) {
100 : : IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
101 : : lif->port_id);
102 : : return;
103 : : }
104 : :
105 : : /* RX */
106 : :
107 : 0 : stats->ipackets = ls->rx_ucast_packets +
108 : 0 : ls->rx_mcast_packets +
109 : 0 : ls->rx_bcast_packets;
110 : :
111 : 0 : stats->ibytes = ls->rx_ucast_bytes +
112 : 0 : ls->rx_mcast_bytes +
113 : 0 : ls->rx_bcast_bytes;
114 : :
115 [ # # ]: 0 : for (i = 0; i < lif->nrxqcqs; i++) {
116 : 0 : struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
117 : 0 : stats->ierrors +=
118 : 0 : rx_stats->bad_cq_status +
119 : 0 : rx_stats->bad_len;
120 : : }
121 : :
122 : 0 : stats->imissed +=
123 : 0 : ls->rx_ucast_drop_packets +
124 : 0 : ls->rx_mcast_drop_packets +
125 : 0 : ls->rx_bcast_drop_packets;
126 : :
127 : 0 : stats->ierrors +=
128 : 0 : ls->rx_dma_error +
129 : 0 : ls->rx_desc_fetch_error +
130 : 0 : ls->rx_desc_data_error;
131 : :
132 [ # # ]: 0 : for (i = 0; i < num_rx_q_counters; i++) {
133 : 0 : struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
134 : 0 : stats->q_ipackets[i] = rx_stats->packets;
135 : 0 : stats->q_ibytes[i] = rx_stats->bytes;
136 : 0 : stats->q_errors[i] =
137 : 0 : rx_stats->bad_cq_status +
138 : 0 : rx_stats->bad_len;
139 : : }
140 : :
141 : : /* TX */
142 : :
143 : 0 : stats->opackets = ls->tx_ucast_packets +
144 : 0 : ls->tx_mcast_packets +
145 : 0 : ls->tx_bcast_packets;
146 : :
147 : 0 : stats->obytes = ls->tx_ucast_bytes +
148 : 0 : ls->tx_mcast_bytes +
149 : 0 : ls->tx_bcast_bytes;
150 : :
151 [ # # ]: 0 : for (i = 0; i < lif->ntxqcqs; i++) {
152 : 0 : struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
153 : 0 : stats->oerrors += tx_stats->drop;
154 : : }
155 : :
156 : 0 : stats->oerrors +=
157 : 0 : ls->tx_ucast_drop_packets +
158 : 0 : ls->tx_mcast_drop_packets +
159 : 0 : ls->tx_bcast_drop_packets;
160 : :
161 : 0 : stats->oerrors +=
162 : 0 : ls->tx_dma_error +
163 : 0 : ls->tx_queue_disabled +
164 : 0 : ls->tx_desc_fetch_error +
165 : 0 : ls->tx_desc_data_error;
166 : :
167 [ # # ]: 0 : for (i = 0; i < num_tx_q_counters; i++) {
168 : 0 : struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
169 : 0 : stats->q_opackets[i] = tx_stats->packets;
170 : 0 : stats->q_obytes[i] = tx_stats->bytes;
171 : : }
172 : : }
173 : :
174 : : void
175 : 0 : ionic_lif_get_stats(const struct ionic_lif *lif,
176 : : struct rte_eth_stats *stats)
177 : : {
178 : 0 : ionic_lif_get_abs_stats(lif, stats);
179 : :
180 : 0 : stats->ipackets -= lif->stats_base.ipackets;
181 : 0 : stats->opackets -= lif->stats_base.opackets;
182 : 0 : stats->ibytes -= lif->stats_base.ibytes;
183 : 0 : stats->obytes -= lif->stats_base.obytes;
184 : 0 : stats->imissed -= lif->stats_base.imissed;
185 : 0 : stats->ierrors -= lif->stats_base.ierrors;
186 : 0 : stats->oerrors -= lif->stats_base.oerrors;
187 : 0 : stats->rx_nombuf -= lif->stats_base.rx_nombuf;
188 : 0 : }
189 : :
190 : : void
191 : 0 : ionic_lif_reset_stats(struct ionic_lif *lif)
192 : : {
193 : : uint32_t i;
194 : :
195 [ # # ]: 0 : for (i = 0; i < lif->nrxqcqs; i++) {
196 : 0 : memset(&lif->rxqcqs[i]->stats, 0,
197 : : sizeof(struct ionic_rx_stats));
198 : 0 : memset(&lif->txqcqs[i]->stats, 0,
199 : : sizeof(struct ionic_tx_stats));
200 : : }
201 : :
202 : 0 : ionic_lif_get_abs_stats(lif, &lif->stats_base);
203 : 0 : }
204 : :
205 : : void
206 : 0 : ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
207 : : {
208 : : uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
209 : : uint64_t *stats64 = (uint64_t *)stats;
210 : 0 : uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
211 : 0 : uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
212 : :
213 [ # # ]: 0 : for (i = 0; i < count; i++)
214 : 0 : stats64[i] = lif_stats64[i] - lif_stats64_base[i];
215 : 0 : }
216 : :
217 : : void
218 : 0 : ionic_lif_reset_hw_stats(struct ionic_lif *lif)
219 : : {
220 : : uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
221 : 0 : uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
222 : 0 : uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
223 : :
224 [ # # ]: 0 : for (i = 0; i < count; i++)
225 : 0 : lif_stats64_base[i] = lif_stats64[i];
226 : 0 : }
227 : :
228 : : static int
229 : 0 : ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
230 : : {
231 : 0 : struct ionic_admin_ctx ctx = {
232 : : .pending_work = true,
233 : : .cmd.rx_filter_add = {
234 : : .opcode = IONIC_CMD_RX_FILTER_ADD,
235 : : .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
236 : : },
237 : : };
238 : : int err;
239 : :
240 : : memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
241 : :
242 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
243 [ # # ]: 0 : if (err)
244 : : return err;
245 : :
246 : 0 : IONIC_PRINT(INFO, "rx_filter add (id %d)",
247 : : rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
248 : :
249 : 0 : return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
250 : : }
251 : :
252 : : static int
253 : 0 : ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
254 : : {
255 : 0 : struct ionic_admin_ctx ctx = {
256 : : .pending_work = true,
257 : : .cmd.rx_filter_del = {
258 : : .opcode = IONIC_CMD_RX_FILTER_DEL,
259 : : },
260 : : };
261 : : struct ionic_rx_filter *f;
262 : : int err;
263 : :
264 : 0 : IONIC_PRINT_CALL();
265 : :
266 : 0 : rte_spinlock_lock(&lif->rx_filters.lock);
267 : :
268 : 0 : f = ionic_rx_filter_by_addr(lif, addr);
269 [ # # ]: 0 : if (!f) {
270 : : rte_spinlock_unlock(&lif->rx_filters.lock);
271 : 0 : return -ENOENT;
272 : : }
273 : :
274 : 0 : ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
275 : 0 : ionic_rx_filter_free(f);
276 : :
277 : : rte_spinlock_unlock(&lif->rx_filters.lock);
278 : :
279 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
280 [ # # ]: 0 : if (err)
281 : : return err;
282 : :
283 : 0 : IONIC_PRINT(INFO, "rx_filter del (id %d)",
284 : : rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
285 : :
286 : 0 : return 0;
287 : : }
288 : :
289 : : int
290 : 0 : ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
291 : : struct rte_ether_addr *mac_addr,
292 : : uint32_t index __rte_unused, uint32_t pool __rte_unused)
293 : : {
294 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
295 : :
296 : 0 : IONIC_PRINT_CALL();
297 : :
298 : 0 : return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
299 : : }
300 : :
301 : : void
302 : 0 : ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
303 : : {
304 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
305 : 0 : struct ionic_adapter *adapter = lif->adapter;
306 : : struct rte_ether_addr *mac_addr;
307 : :
308 : 0 : IONIC_PRINT_CALL();
309 : :
310 [ # # ]: 0 : if (index >= adapter->max_mac_addrs) {
311 : 0 : IONIC_PRINT(WARNING,
312 : : "Index %u is above MAC filter limit %u",
313 : : index, adapter->max_mac_addrs);
314 : 0 : return;
315 : : }
316 : :
317 [ # # ]: 0 : mac_addr = ð_dev->data->mac_addrs[index];
318 : :
319 : : if (!rte_is_valid_assigned_ether_addr(mac_addr))
320 : : return;
321 : :
322 : 0 : ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
323 : : }
324 : :
325 : : int
326 : 0 : ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
327 : : {
328 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
329 : :
330 : 0 : IONIC_PRINT_CALL();
331 : :
332 [ # # ]: 0 : if (mac_addr == NULL) {
333 : 0 : IONIC_PRINT(NOTICE, "New mac is null");
334 : 0 : return -1;
335 : : }
336 : :
337 [ # # ]: 0 : if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
338 : 0 : IONIC_PRINT(INFO, "Deleting mac addr %pM",
339 : : lif->mac_addr);
340 : 0 : ionic_lif_addr_del(lif, lif->mac_addr);
341 : : memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
342 : : }
343 : :
344 : 0 : IONIC_PRINT(INFO, "Updating mac addr");
345 : :
346 : : rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
347 : :
348 : 0 : return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
349 : : }
350 : :
351 : : static int
352 : 0 : ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
353 : : {
354 : 0 : struct ionic_admin_ctx ctx = {
355 : : .pending_work = true,
356 : : .cmd.rx_filter_add = {
357 : : .opcode = IONIC_CMD_RX_FILTER_ADD,
358 : : .match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
359 : : .vlan.vlan = rte_cpu_to_le_16(vid),
360 : : },
361 : : };
362 : : int err;
363 : :
364 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
365 [ # # ]: 0 : if (err)
366 : : return err;
367 : :
368 : 0 : IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
369 : : rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
370 : :
371 : 0 : return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
372 : : }
373 : :
374 : : static int
375 : 0 : ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
376 : : {
377 : 0 : struct ionic_admin_ctx ctx = {
378 : : .pending_work = true,
379 : : .cmd.rx_filter_del = {
380 : : .opcode = IONIC_CMD_RX_FILTER_DEL,
381 : : },
382 : : };
383 : : struct ionic_rx_filter *f;
384 : : int err;
385 : :
386 : 0 : IONIC_PRINT_CALL();
387 : :
388 : 0 : rte_spinlock_lock(&lif->rx_filters.lock);
389 : :
390 : 0 : f = ionic_rx_filter_by_vlan(lif, vid);
391 [ # # ]: 0 : if (!f) {
392 : : rte_spinlock_unlock(&lif->rx_filters.lock);
393 : 0 : return -ENOENT;
394 : : }
395 : :
396 : 0 : ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
397 : 0 : ionic_rx_filter_free(f);
398 : : rte_spinlock_unlock(&lif->rx_filters.lock);
399 : :
400 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
401 [ # # ]: 0 : if (err)
402 : : return err;
403 : :
404 : 0 : IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
405 : : rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
406 : :
407 : 0 : return 0;
408 : : }
409 : :
410 : : int
411 : 0 : ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
412 : : int on)
413 : : {
414 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
415 : : int err;
416 : :
417 [ # # ]: 0 : if (on)
418 : 0 : err = ionic_vlan_rx_add_vid(lif, vlan_id);
419 : : else
420 : 0 : err = ionic_vlan_rx_kill_vid(lif, vlan_id);
421 : :
422 : 0 : return err;
423 : : }
424 : :
425 : : static void
426 : 0 : ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
427 : : {
428 : 0 : struct ionic_admin_ctx ctx = {
429 : : .pending_work = true,
430 : : .cmd.rx_mode_set = {
431 : : .opcode = IONIC_CMD_RX_MODE_SET,
432 : : .rx_mode = rte_cpu_to_le_16(rx_mode),
433 : : },
434 : : };
435 : : int err;
436 : :
437 [ # # ]: 0 : if (rx_mode & IONIC_RX_MODE_F_UNICAST)
438 : 0 : IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
439 [ # # ]: 0 : if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
440 : 0 : IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
441 [ # # ]: 0 : if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
442 : 0 : IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
443 [ # # ]: 0 : if (rx_mode & IONIC_RX_MODE_F_PROMISC)
444 : 0 : IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
445 [ # # ]: 0 : if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
446 : 0 : IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
447 : :
448 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
449 [ # # ]: 0 : if (err)
450 : 0 : IONIC_PRINT(ERR, "Failure setting RX mode");
451 : 0 : }
452 : :
453 : : static void
454 : : ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
455 : : {
456 [ # # ]: 0 : if (lif->rx_mode != rx_mode) {
457 : 0 : lif->rx_mode = rx_mode;
458 : 0 : ionic_lif_rx_mode(lif, rx_mode);
459 : : }
460 : : }
461 : :
462 : : int
463 : 0 : ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
464 : : {
465 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
466 : 0 : uint32_t rx_mode = lif->rx_mode;
467 : :
468 : 0 : IONIC_PRINT_CALL();
469 : :
470 [ # # ]: 0 : rx_mode |= IONIC_RX_MODE_F_PROMISC;
471 : :
472 : : ionic_set_rx_mode(lif, rx_mode);
473 : :
474 : 0 : return 0;
475 : : }
476 : :
477 : : int
478 : 0 : ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
479 : : {
480 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
481 : 0 : uint32_t rx_mode = lif->rx_mode;
482 : :
483 [ # # ]: 0 : rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
484 : :
485 : : ionic_set_rx_mode(lif, rx_mode);
486 : :
487 : 0 : return 0;
488 : : }
489 : :
490 : : int
491 : 0 : ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
492 : : {
493 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
494 : 0 : uint32_t rx_mode = lif->rx_mode;
495 : :
496 [ # # ]: 0 : rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
497 : :
498 : : ionic_set_rx_mode(lif, rx_mode);
499 : :
500 : 0 : return 0;
501 : : }
502 : :
503 : : int
504 : 0 : ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
505 : : {
506 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
507 : 0 : uint32_t rx_mode = lif->rx_mode;
508 : :
509 [ # # ]: 0 : rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
510 : :
511 : : ionic_set_rx_mode(lif, rx_mode);
512 : :
513 : 0 : return 0;
514 : : }
515 : :
516 : : int
517 : 0 : ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
518 : : {
519 : 0 : struct ionic_admin_ctx ctx = {
520 : : .pending_work = true,
521 : : .cmd.lif_setattr = {
522 : : .opcode = IONIC_CMD_LIF_SETATTR,
523 : : .attr = IONIC_LIF_ATTR_MTU,
524 : : .mtu = rte_cpu_to_le_32(new_mtu),
525 : : },
526 : : };
527 : :
528 : 0 : return ionic_adminq_post_wait(lif, &ctx);
529 : : }
530 : :
531 : : int
532 : 0 : ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
533 : : {
534 : 0 : struct ionic_adapter *adapter = lif->adapter;
535 : 0 : struct ionic_dev *idev = &adapter->idev;
536 : : unsigned long index;
537 : :
538 : : /*
539 : : * Note: interrupt handler is called for index = 0 only
540 : : * (we use interrupts for the notifyq only anyway,
541 : : * which has index = 0)
542 : : */
543 : :
544 [ # # ]: 0 : for (index = 0; index < adapter->nintrs; index++)
545 [ # # ]: 0 : if (!adapter->intrs[index])
546 : : break;
547 : :
548 [ # # ]: 0 : if (index == adapter->nintrs)
549 : : return -ENOSPC;
550 : :
551 : 0 : adapter->intrs[index] = true;
552 : :
553 : 0 : ionic_intr_init(idev, intr, index);
554 : :
555 : 0 : return 0;
556 : : }
557 : :
558 : : static int
559 : 0 : ionic_qcq_alloc(struct ionic_lif *lif,
560 : : uint8_t type,
561 : : size_t struct_size,
562 : : uint32_t socket_id,
563 : : uint32_t index,
564 : : const char *type_name,
565 : : uint16_t flags,
566 : : uint16_t num_descs,
567 : : uint16_t num_segs,
568 : : uint16_t desc_size,
569 : : uint16_t cq_desc_size,
570 : : uint16_t sg_desc_size,
571 : : struct ionic_qcq **qcq)
572 : : {
573 : : struct ionic_qcq *new;
574 : : uint32_t q_size, cq_size, sg_size, total_size;
575 : : void *q_base, *cq_base, *sg_base;
576 : : rte_iova_t q_base_pa = 0;
577 : : rte_iova_t cq_base_pa = 0;
578 : : rte_iova_t sg_base_pa = 0;
579 : 0 : size_t page_size = rte_mem_page_size();
580 : : int err;
581 : :
582 : 0 : *qcq = NULL;
583 : :
584 : 0 : q_size = num_descs * desc_size;
585 : 0 : cq_size = num_descs * cq_desc_size;
586 : 0 : sg_size = num_descs * sg_desc_size;
587 : :
588 : 0 : total_size = RTE_ALIGN(q_size, page_size) +
589 : 0 : RTE_ALIGN(cq_size, page_size);
590 : : /*
591 : : * Note: aligning q_size/cq_size is not enough due to cq_base address
592 : : * aligning as q_base could be not aligned to the page.
593 : : * Adding page_size.
594 : : */
595 : 0 : total_size += page_size;
596 : :
597 [ # # ]: 0 : if (flags & IONIC_QCQ_F_SG) {
598 : 0 : total_size += RTE_ALIGN(sg_size, page_size);
599 : 0 : total_size += page_size;
600 : : }
601 : :
602 : 0 : new = rte_zmalloc_socket("ionic", struct_size,
603 : : RTE_CACHE_LINE_SIZE, socket_id);
604 [ # # ]: 0 : if (!new) {
605 : 0 : IONIC_PRINT(ERR, "Cannot allocate queue structure");
606 : 0 : return -ENOMEM;
607 : : }
608 : :
609 : 0 : new->lif = lif;
610 : :
611 : : /* Most queue types will store 1 ptr per descriptor */
612 : 0 : new->q.info = rte_calloc_socket("ionic",
613 : 0 : (uint64_t)num_descs * num_segs,
614 : : sizeof(void *), page_size, socket_id);
615 [ # # ]: 0 : if (!new->q.info) {
616 : 0 : IONIC_PRINT(ERR, "Cannot allocate queue info");
617 : : err = -ENOMEM;
618 : 0 : goto err_out_free_qcq;
619 : : }
620 : :
621 : 0 : new->q.num_segs = num_segs;
622 : 0 : new->q.type = type;
623 : :
624 : 0 : err = ionic_q_init(&new->q, index, num_descs);
625 [ # # ]: 0 : if (err) {
626 : 0 : IONIC_PRINT(ERR, "Queue initialization failed");
627 : 0 : goto err_out_free_info;
628 : : }
629 : :
630 : 0 : err = ionic_cq_init(&new->cq, num_descs);
631 [ # # ]: 0 : if (err) {
632 : 0 : IONIC_PRINT(ERR, "Completion queue initialization failed");
633 : 0 : goto err_out_free_info;
634 : : }
635 : :
636 : 0 : new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
637 : : type_name, index /* queue_idx */,
638 : : total_size, IONIC_ALIGN, socket_id);
639 : :
640 [ # # ]: 0 : if (!new->base_z) {
641 : 0 : IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
642 : : err = -ENOMEM;
643 : 0 : goto err_out_free_info;
644 : : }
645 : :
646 : 0 : new->base = new->base_z->addr;
647 : 0 : new->base_pa = new->base_z->iova;
648 : :
649 : : q_base = new->base;
650 : : q_base_pa = new->base_pa;
651 : :
652 : 0 : cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
653 : 0 : cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
654 : :
655 [ # # ]: 0 : if (flags & IONIC_QCQ_F_SG) {
656 : 0 : sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
657 : : page_size);
658 : 0 : sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
659 : 0 : ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
660 : : }
661 : :
662 [ # # ]: 0 : if (flags & IONIC_QCQ_F_CMB) {
663 : : /* alloc descriptor ring from nic memory */
664 : 0 : if (lif->adapter->cmb_offset + q_size >
665 [ # # ]: 0 : lif->adapter->bars.bar[2].len) {
666 : 0 : IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem");
667 : 0 : return -ENOMEM;
668 : : }
669 : 0 : q_base = (void *)
670 : 0 : ((uintptr_t)lif->adapter->bars.bar[2].vaddr +
671 : : (uintptr_t)lif->adapter->cmb_offset);
672 : : /* CMB PA is a relative address */
673 : : q_base_pa = lif->adapter->cmb_offset;
674 : 0 : lif->adapter->cmb_offset += q_size;
675 : : }
676 : :
677 : 0 : IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
678 : : "SG-base-PA = %#jx",
679 : : q_base_pa, cq_base_pa, sg_base_pa);
680 : :
681 : 0 : ionic_q_map(&new->q, q_base, q_base_pa);
682 : 0 : ionic_cq_map(&new->cq, cq_base, cq_base_pa);
683 : :
684 : 0 : *qcq = new;
685 : :
686 : 0 : return 0;
687 : :
688 : 0 : err_out_free_info:
689 : 0 : rte_free(new->q.info);
690 : 0 : err_out_free_qcq:
691 : 0 : rte_free(new);
692 : :
693 : 0 : return err;
694 : : }
695 : :
696 : : void
697 : 0 : ionic_qcq_free(struct ionic_qcq *qcq)
698 : : {
699 [ # # ]: 0 : if (qcq->base_z) {
700 : 0 : qcq->base = NULL;
701 : 0 : qcq->base_pa = 0;
702 : 0 : rte_memzone_free(qcq->base_z);
703 : 0 : qcq->base_z = NULL;
704 : : }
705 : :
706 [ # # ]: 0 : if (qcq->q.info) {
707 : 0 : rte_free(qcq->q.info);
708 : 0 : qcq->q.info = NULL;
709 : : }
710 : :
711 : 0 : rte_free(qcq);
712 : 0 : }
713 : :
714 : : static uint64_t
715 : 0 : ionic_rx_rearm_data(struct ionic_lif *lif)
716 : : {
717 : : struct rte_mbuf rxm;
718 : :
719 : : memset(&rxm, 0, sizeof(rxm));
720 : :
721 : : rte_mbuf_refcnt_set(&rxm, 1);
722 : 0 : rxm.data_off = RTE_PKTMBUF_HEADROOM;
723 : 0 : rxm.nb_segs = 1;
724 : 0 : rxm.port = lif->port_id;
725 : :
726 : 0 : rte_compiler_barrier();
727 : :
728 : : RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
729 : 0 : return rxm.rearm_data[0];
730 : : }
731 : :
732 : : static uint64_t
733 : 0 : ionic_rx_seg_rearm_data(struct ionic_lif *lif)
734 : : {
735 : : struct rte_mbuf rxm;
736 : :
737 : : memset(&rxm, 0, sizeof(rxm));
738 : :
739 : : rte_mbuf_refcnt_set(&rxm, 1);
740 : 0 : rxm.data_off = 0; /* no headroom */
741 : 0 : rxm.nb_segs = 1;
742 : 0 : rxm.port = lif->port_id;
743 : :
744 : 0 : rte_compiler_barrier();
745 : :
746 : : RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
747 : 0 : return rxm.rearm_data[0];
748 : : }
749 : :
750 : : int
751 : 0 : ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
752 : : uint16_t nrxq_descs, struct rte_mempool *mb_pool,
753 : : struct ionic_rx_qcq **rxq_out)
754 : : {
755 : : struct ionic_rx_qcq *rxq;
756 : : uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1;
757 : : uint32_t max_mtu;
758 : : int err;
759 : :
760 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_Q_IN_CMB)
761 : : flags |= IONIC_QCQ_F_CMB;
762 : :
763 : : seg_size = rte_pktmbuf_data_room_size(mb_pool);
764 : :
765 : : /* The first mbuf needs to leave headroom */
766 : 0 : hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
767 : :
768 : 0 : max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
769 : :
770 : : /* If mbufs are too small to hold received packets, enable SG */
771 [ # # ]: 0 : if (max_mtu > hdr_seg_size) {
772 : 0 : IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER");
773 : 0 : lif->eth_dev->data->dev_conf.rxmode.offloads |=
774 : : RTE_ETH_RX_OFFLOAD_SCATTER;
775 : 0 : ionic_lif_configure_rx_sg_offload(lif);
776 : : }
777 : :
778 [ # # ]: 0 : if (lif->features & IONIC_ETH_HW_RX_SG) {
779 : 0 : flags |= IONIC_QCQ_F_SG;
780 : : max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
781 : : }
782 : :
783 : : /*
784 : : * Calculate how many fragment pointers might be stored in queue.
785 : : * This is the worst-case number, so that there's enough room in
786 : : * the info array.
787 : : */
788 : 0 : max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
789 : :
790 : 0 : IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
791 : : index, max_mtu, seg_size, max_segs);
792 [ # # ]: 0 : if (max_segs > max_segs_fw) {
793 : 0 : IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
794 : : max_segs, max_segs_fw);
795 : 0 : return -EINVAL;
796 : : }
797 : :
798 : 0 : err = ionic_qcq_alloc(lif,
799 : : IONIC_QTYPE_RXQ,
800 : : sizeof(struct ionic_rx_qcq),
801 : : socket_id,
802 : : index,
803 : : "rx",
804 : : flags,
805 : : nrxq_descs,
806 : : max_segs,
807 : : sizeof(struct ionic_rxq_desc),
808 : : sizeof(struct ionic_rxq_comp),
809 : : sizeof(struct ionic_rxq_sg_desc),
810 : : (struct ionic_qcq **)&rxq);
811 [ # # ]: 0 : if (err)
812 : : return err;
813 : :
814 : 0 : rxq->flags = flags;
815 : 0 : rxq->seg_size = seg_size;
816 : 0 : rxq->hdr_seg_size = hdr_seg_size;
817 : 0 : rxq->rearm_data = ionic_rx_rearm_data(lif);
818 : 0 : rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
819 : :
820 : 0 : lif->rxqcqs[index] = rxq;
821 : 0 : *rxq_out = rxq;
822 : :
823 : 0 : return 0;
824 : : }
825 : :
826 : : int
827 : 0 : ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
828 : : uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
829 : : {
830 : : struct ionic_tx_qcq *txq;
831 : : uint16_t flags = 0, num_segs_fw = 1;
832 : : int err;
833 : :
834 [ # # ]: 0 : if (lif->features & IONIC_ETH_HW_TX_SG) {
835 : : flags |= IONIC_QCQ_F_SG;
836 : : num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
837 : : }
838 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_Q_IN_CMB)
839 : 0 : flags |= IONIC_QCQ_F_CMB;
840 : :
841 : 0 : IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw);
842 : :
843 : 0 : err = ionic_qcq_alloc(lif,
844 : : IONIC_QTYPE_TXQ,
845 : : sizeof(struct ionic_tx_qcq),
846 : : socket_id,
847 : : index,
848 : : "tx",
849 : : flags,
850 : : ntxq_descs,
851 : : num_segs_fw,
852 : : sizeof(struct ionic_txq_desc),
853 : : sizeof(struct ionic_txq_comp),
854 : : sizeof(struct ionic_txq_sg_desc_v1),
855 : : (struct ionic_qcq **)&txq);
856 [ # # ]: 0 : if (err)
857 : : return err;
858 : :
859 : 0 : txq->flags = flags;
860 : 0 : txq->num_segs_fw = num_segs_fw;
861 : :
862 : 0 : lif->txqcqs[index] = txq;
863 : 0 : *txq_out = txq;
864 : :
865 : 0 : return 0;
866 : : }
867 : :
868 : : static int
869 : 0 : ionic_admin_qcq_alloc(struct ionic_lif *lif)
870 : : {
871 : : uint16_t flags = 0;
872 : : int err;
873 : :
874 : 0 : err = ionic_qcq_alloc(lif,
875 : : IONIC_QTYPE_ADMINQ,
876 : : sizeof(struct ionic_admin_qcq),
877 : : rte_socket_id(),
878 : : 0,
879 : : "admin",
880 : : flags,
881 : : IONIC_ADMINQ_LENGTH,
882 : : 1,
883 : : sizeof(struct ionic_admin_cmd),
884 : : sizeof(struct ionic_admin_comp),
885 : : 0,
886 : 0 : (struct ionic_qcq **)&lif->adminqcq);
887 [ # # ]: 0 : if (err)
888 : 0 : return err;
889 : :
890 : : return 0;
891 : : }
892 : :
893 : : static int
894 : 0 : ionic_notify_qcq_alloc(struct ionic_lif *lif)
895 : : {
896 : : struct ionic_notify_qcq *nqcq;
897 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
898 : : uint16_t flags = 0;
899 : : int err;
900 : :
901 : 0 : err = ionic_qcq_alloc(lif,
902 : : IONIC_QTYPE_NOTIFYQ,
903 : : sizeof(struct ionic_notify_qcq),
904 : : rte_socket_id(),
905 : : 0,
906 : : "notify",
907 : : flags,
908 : : IONIC_NOTIFYQ_LENGTH,
909 : : 1,
910 : : sizeof(struct ionic_notifyq_cmd),
911 : : sizeof(union ionic_notifyq_comp),
912 : : 0,
913 : : (struct ionic_qcq **)&nqcq);
914 [ # # ]: 0 : if (err)
915 : : return err;
916 : :
917 : 0 : err = ionic_intr_alloc(lif, &nqcq->intr);
918 [ # # ]: 0 : if (err) {
919 : 0 : ionic_qcq_free(&nqcq->qcq);
920 : 0 : return err;
921 : : }
922 : :
923 : 0 : ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
924 : : IONIC_INTR_MASK_SET);
925 : :
926 : 0 : lif->notifyqcq = nqcq;
927 : :
928 : 0 : return 0;
929 : : }
930 : :
931 : : static void
932 : 0 : ionic_lif_queue_identify(struct ionic_lif *lif)
933 : : {
934 : 0 : struct ionic_adapter *adapter = lif->adapter;
935 : 0 : struct ionic_dev *idev = &adapter->idev;
936 : : union ionic_q_identity *q_ident = &adapter->ident.txq;
937 : : uint32_t q_words = RTE_DIM(q_ident->words);
938 : : uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
939 : : uint32_t i, nwords, qtype;
940 : : int err;
941 : :
942 [ # # ]: 0 : for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
943 : 0 : struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
944 : :
945 : : /* Filter out the types this driver knows about */
946 [ # # ]: 0 : switch (qtype) {
947 : : case IONIC_QTYPE_ADMINQ:
948 : : case IONIC_QTYPE_NOTIFYQ:
949 : : case IONIC_QTYPE_RXQ:
950 : : case IONIC_QTYPE_TXQ:
951 : : break;
952 : 0 : default:
953 : 0 : continue;
954 : : }
955 : :
956 : : memset(qti, 0, sizeof(*qti));
957 : :
958 : 0 : ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
959 : 0 : qtype, ionic_qtype_vers[qtype]);
960 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
961 [ # # ]: 0 : if (err == -EINVAL) {
962 : 0 : IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
963 : 0 : continue;
964 [ # # ]: 0 : } else if (err == -EIO) {
965 : 0 : IONIC_PRINT(ERR, "q_ident failed, older FW\n");
966 : 0 : return;
967 [ # # ]: 0 : } else if (err) {
968 : 0 : IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
969 : : qtype, err);
970 : 0 : return;
971 : : }
972 : :
973 : : nwords = RTE_MIN(q_words, cmd_words);
974 [ # # ]: 0 : for (i = 0; i < nwords; i++)
975 : 0 : q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
976 : :
977 : 0 : qti->version = q_ident->version;
978 : 0 : qti->supported = q_ident->supported;
979 : 0 : qti->features = rte_le_to_cpu_64(q_ident->features);
980 : 0 : qti->desc_sz = rte_le_to_cpu_16(q_ident->desc_sz);
981 : 0 : qti->comp_sz = rte_le_to_cpu_16(q_ident->comp_sz);
982 : 0 : qti->sg_desc_sz = rte_le_to_cpu_16(q_ident->sg_desc_sz);
983 : 0 : qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
984 : 0 : qti->sg_desc_stride =
985 : 0 : rte_le_to_cpu_16(q_ident->sg_desc_stride);
986 : :
987 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
988 : : qtype, qti->version);
989 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
990 : : qtype, qti->supported);
991 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
992 : : qtype, qti->features);
993 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
994 : : qtype, qti->desc_sz);
995 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
996 : : qtype, qti->comp_sz);
997 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
998 : : qtype, qti->sg_desc_sz);
999 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
1000 : : qtype, qti->max_sg_elems);
1001 : 0 : IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
1002 : : qtype, qti->sg_desc_stride);
1003 : : }
1004 : : }
1005 : :
1006 : : int
1007 : 0 : ionic_lif_alloc(struct ionic_lif *lif)
1008 : : {
1009 : 0 : struct ionic_adapter *adapter = lif->adapter;
1010 : 0 : uint32_t socket_id = rte_socket_id();
1011 : : int err;
1012 : :
1013 : : /*
1014 : : * lif->name was zeroed on allocation.
1015 : : * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
1016 : : */
1017 : 0 : memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
1018 : :
1019 : 0 : IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
1020 : :
1021 : 0 : ionic_lif_queue_identify(lif);
1022 : :
1023 [ # # ]: 0 : if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
1024 : 0 : IONIC_PRINT(ERR, "FW too old, please upgrade");
1025 : 0 : return -ENXIO;
1026 : : }
1027 : :
1028 [ # # ]: 0 : if (adapter->q_in_cmb) {
1029 [ # # ]: 0 : if (adapter->bars.num_bars >= 3 &&
1030 [ # # # # ]: 0 : lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 &&
1031 : : lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) {
1032 : 0 : IONIC_PRINT(INFO, "%s enabled on %s",
1033 : : PMD_IONIC_CMB_KVARG, lif->name);
1034 : 0 : lif->state |= IONIC_LIF_F_Q_IN_CMB;
1035 : : } else {
1036 : 0 : IONIC_PRINT(ERR, "%s not supported on %s, disabled",
1037 : : PMD_IONIC_CMB_KVARG, lif->name);
1038 : : }
1039 : : }
1040 : :
1041 : 0 : IONIC_PRINT(DEBUG, "Allocating Lif Info");
1042 : :
1043 : : rte_spinlock_init(&lif->adminq_lock);
1044 : : rte_spinlock_init(&lif->adminq_service_lock);
1045 : :
1046 : 0 : lif->kern_dbpage = adapter->idev.db_pages;
1047 [ # # ]: 0 : if (!lif->kern_dbpage) {
1048 : 0 : IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1049 : 0 : return -ENOMEM;
1050 : : }
1051 : :
1052 : 0 : lif->txqcqs = rte_calloc_socket("ionic",
1053 : 0 : adapter->max_ntxqs_per_lif,
1054 : : sizeof(*lif->txqcqs),
1055 : : RTE_CACHE_LINE_SIZE, socket_id);
1056 [ # # ]: 0 : if (!lif->txqcqs) {
1057 : 0 : IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1058 : 0 : return -ENOMEM;
1059 : : }
1060 : :
1061 : 0 : lif->rxqcqs = rte_calloc_socket("ionic",
1062 : 0 : adapter->max_nrxqs_per_lif,
1063 : : sizeof(*lif->rxqcqs),
1064 : : RTE_CACHE_LINE_SIZE, socket_id);
1065 [ # # ]: 0 : if (!lif->rxqcqs) {
1066 : 0 : IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1067 : 0 : return -ENOMEM;
1068 : : }
1069 : :
1070 : 0 : IONIC_PRINT(DEBUG, "Allocating Notify Queue");
1071 : :
1072 : 0 : err = ionic_notify_qcq_alloc(lif);
1073 [ # # ]: 0 : if (err) {
1074 : 0 : IONIC_PRINT(ERR, "Cannot allocate notify queue");
1075 : 0 : return err;
1076 : : }
1077 : :
1078 : 0 : IONIC_PRINT(DEBUG, "Allocating Admin Queue");
1079 : :
1080 : 0 : err = ionic_admin_qcq_alloc(lif);
1081 [ # # ]: 0 : if (err) {
1082 : 0 : IONIC_PRINT(ERR, "Cannot allocate admin queue");
1083 : 0 : return err;
1084 : : }
1085 : :
1086 : 0 : IONIC_PRINT(DEBUG, "Allocating Lif Info");
1087 : :
1088 : 0 : lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1089 : :
1090 : 0 : lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1091 : : "lif_info", 0 /* queue_idx*/,
1092 : : lif->info_sz, IONIC_ALIGN, socket_id);
1093 [ # # ]: 0 : if (!lif->info_z) {
1094 : 0 : IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1095 : 0 : return -ENOMEM;
1096 : : }
1097 : :
1098 : 0 : lif->info = lif->info_z->addr;
1099 : 0 : lif->info_pa = lif->info_z->iova;
1100 : :
1101 : 0 : return 0;
1102 : : }
1103 : :
1104 : : void
1105 : 0 : ionic_lif_free(struct ionic_lif *lif)
1106 : : {
1107 [ # # ]: 0 : if (lif->notifyqcq) {
1108 : 0 : ionic_qcq_free(&lif->notifyqcq->qcq);
1109 : 0 : lif->notifyqcq = NULL;
1110 : : }
1111 : :
1112 [ # # ]: 0 : if (lif->adminqcq) {
1113 : 0 : ionic_qcq_free(&lif->adminqcq->qcq);
1114 : 0 : lif->adminqcq = NULL;
1115 : : }
1116 : :
1117 [ # # ]: 0 : if (lif->txqcqs) {
1118 : 0 : rte_free(lif->txqcqs);
1119 : 0 : lif->txqcqs = NULL;
1120 : : }
1121 : :
1122 [ # # ]: 0 : if (lif->rxqcqs) {
1123 : 0 : rte_free(lif->rxqcqs);
1124 : 0 : lif->rxqcqs = NULL;
1125 : : }
1126 : :
1127 [ # # ]: 0 : if (lif->info) {
1128 : 0 : rte_memzone_free(lif->info_z);
1129 : 0 : lif->info = NULL;
1130 : : }
1131 : 0 : }
1132 : :
1133 : : void
1134 : 0 : ionic_lif_free_queues(struct ionic_lif *lif)
1135 : : {
1136 : : uint32_t i;
1137 : :
1138 [ # # ]: 0 : for (i = 0; i < lif->ntxqcqs; i++) {
1139 : 0 : ionic_dev_tx_queue_release(lif->eth_dev, i);
1140 : 0 : lif->eth_dev->data->tx_queues[i] = NULL;
1141 : : }
1142 [ # # ]: 0 : for (i = 0; i < lif->nrxqcqs; i++) {
1143 : 0 : ionic_dev_rx_queue_release(lif->eth_dev, i);
1144 : 0 : lif->eth_dev->data->rx_queues[i] = NULL;
1145 : : }
1146 : 0 : }
1147 : :
1148 : : int
1149 : 0 : ionic_lif_rss_config(struct ionic_lif *lif,
1150 : : const uint16_t types, const uint8_t *key, const uint32_t *indir)
1151 : : {
1152 : 0 : struct ionic_adapter *adapter = lif->adapter;
1153 : 0 : struct ionic_admin_ctx ctx = {
1154 : : .pending_work = true,
1155 : : .cmd.lif_setattr = {
1156 : : .opcode = IONIC_CMD_LIF_SETATTR,
1157 : : .attr = IONIC_LIF_ATTR_RSS,
1158 : : .rss.types = rte_cpu_to_le_16(types),
1159 : 0 : .rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
1160 : : },
1161 : : };
1162 : : unsigned int i;
1163 : 0 : uint16_t tbl_sz =
1164 : : rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
1165 : :
1166 : 0 : IONIC_PRINT_CALL();
1167 : :
1168 : 0 : lif->rss_types = types;
1169 : :
1170 [ # # ]: 0 : if (key)
1171 : 0 : memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
1172 : :
1173 [ # # ]: 0 : if (indir)
1174 [ # # ]: 0 : for (i = 0; i < tbl_sz; i++)
1175 : 0 : lif->rss_ind_tbl[i] = indir[i];
1176 : :
1177 : : memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
1178 : : IONIC_RSS_HASH_KEY_SIZE);
1179 : :
1180 : 0 : return ionic_adminq_post_wait(lif, &ctx);
1181 : : }
1182 : :
1183 : : static int
1184 : 0 : ionic_lif_rss_setup(struct ionic_lif *lif)
1185 : : {
1186 : 0 : struct ionic_adapter *adapter = lif->adapter;
1187 : : static const uint8_t toeplitz_symmetric_key[] = {
1188 : : 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
1189 : : 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
1190 : : 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
1191 : : 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
1192 : : 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
1193 : : };
1194 : : uint32_t i;
1195 : 0 : uint16_t tbl_sz =
1196 : : rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
1197 : :
1198 : 0 : IONIC_PRINT_CALL();
1199 : :
1200 [ # # ]: 0 : if (!lif->rss_ind_tbl_z) {
1201 : 0 : lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1202 : : "rss_ind_tbl", 0 /* queue_idx */,
1203 : : sizeof(*lif->rss_ind_tbl) * tbl_sz,
1204 : 0 : IONIC_ALIGN, rte_socket_id());
1205 [ # # ]: 0 : if (!lif->rss_ind_tbl_z) {
1206 : 0 : IONIC_PRINT(ERR, "OOM");
1207 : 0 : return -ENOMEM;
1208 : : }
1209 : :
1210 : 0 : lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
1211 : 0 : lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
1212 : : }
1213 : :
1214 [ # # ]: 0 : if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
1215 : 0 : lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
1216 : :
1217 : : /* Fill indirection table with 'default' values */
1218 [ # # ]: 0 : for (i = 0; i < tbl_sz; i++)
1219 : 0 : lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
1220 : : }
1221 : :
1222 : 0 : return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
1223 : : toeplitz_symmetric_key, NULL);
1224 : : }
1225 : :
1226 : : static void
1227 : 0 : ionic_lif_rss_teardown(struct ionic_lif *lif)
1228 : : {
1229 [ # # ]: 0 : if (!lif->rss_ind_tbl)
1230 : : return;
1231 : :
1232 [ # # ]: 0 : if (lif->rss_ind_tbl_z) {
1233 : : /* Disable RSS on the NIC */
1234 : 0 : ionic_lif_rss_config(lif, 0x0, NULL, NULL);
1235 : :
1236 : 0 : lif->rss_ind_tbl = NULL;
1237 : 0 : lif->rss_ind_tbl_pa = 0;
1238 : 0 : rte_memzone_free(lif->rss_ind_tbl_z);
1239 : 0 : lif->rss_ind_tbl_z = NULL;
1240 : : }
1241 : : }
1242 : :
1243 : : void
1244 : 0 : ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1245 : : {
1246 : 0 : ionic_qcq_disable(&txq->qcq);
1247 : :
1248 : 0 : txq->flags &= ~IONIC_QCQ_F_INITED;
1249 : 0 : }
1250 : :
1251 : : void
1252 : 0 : ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1253 : : {
1254 : 0 : ionic_qcq_disable(&rxq->qcq);
1255 : :
1256 : 0 : rxq->flags &= ~IONIC_QCQ_F_INITED;
1257 : 0 : }
1258 : :
1259 : : static void
1260 : : ionic_lif_adminq_deinit(struct ionic_lif *lif)
1261 : : {
1262 : 0 : lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
1263 : : }
1264 : :
1265 : : static void
1266 : : ionic_lif_notifyq_deinit(struct ionic_lif *lif)
1267 : : {
1268 : 0 : struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1269 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
1270 : :
1271 [ # # ]: 0 : if (!(nqcq->flags & IONIC_QCQ_F_INITED))
1272 : : return;
1273 : :
1274 : 0 : ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
1275 : : IONIC_INTR_MASK_SET);
1276 : :
1277 : 0 : nqcq->flags &= ~IONIC_QCQ_F_INITED;
1278 : : }
1279 : :
1280 : : /* This acts like ionic_napi */
1281 : : int
1282 : 0 : ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
1283 : : void *cb_arg)
1284 : : {
1285 : 0 : struct ionic_cq *cq = &qcq->cq;
1286 : : uint32_t work_done;
1287 : :
1288 : 0 : work_done = ionic_cq_service(cq, budget, cb, cb_arg);
1289 : :
1290 : 0 : return work_done;
1291 : : }
1292 : :
1293 : : static void
1294 : 0 : ionic_link_status_check(struct ionic_lif *lif)
1295 : : {
1296 : 0 : struct ionic_adapter *adapter = lif->adapter;
1297 : : bool link_up;
1298 : :
1299 : 0 : lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
1300 : :
1301 [ # # ]: 0 : if (!lif->info)
1302 : : return;
1303 : :
1304 : 0 : link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
1305 : :
1306 [ # # # # : 0 : if ((link_up && adapter->link_up) ||
# # ]
1307 [ # # ]: 0 : (!link_up && !adapter->link_up))
1308 : : return;
1309 : :
1310 [ # # ]: 0 : if (link_up) {
1311 : 0 : adapter->link_speed =
1312 : 0 : rte_le_to_cpu_32(lif->info->status.link_speed);
1313 : 0 : IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1314 : : adapter->link_speed);
1315 : : } else {
1316 : 0 : IONIC_PRINT(DEBUG, "Link down");
1317 : : }
1318 : :
1319 : 0 : adapter->link_up = link_up;
1320 : 0 : ionic_dev_link_update(lif->eth_dev, 0);
1321 : : }
1322 : :
1323 : : static void
1324 : 0 : ionic_lif_handle_fw_down(struct ionic_lif *lif)
1325 : : {
1326 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_FW_RESET)
1327 : : return;
1328 : :
1329 : 0 : lif->state |= IONIC_LIF_F_FW_RESET;
1330 : :
1331 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_UP) {
1332 : 0 : IONIC_PRINT(NOTICE,
1333 : : "Surprise FW stop, stopping %s\n", lif->name);
1334 : 0 : ionic_lif_stop(lif);
1335 : : }
1336 : :
1337 : 0 : IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
1338 : : }
1339 : :
1340 : : static bool
1341 : 0 : ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
1342 : : {
1343 : 0 : union ionic_notifyq_comp *cq_desc_base = cq->base;
1344 : 0 : union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
1345 : : struct ionic_lif *lif = cb_arg;
1346 : :
1347 : 0 : IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
1348 : : cq_desc->event.eid, cq_desc->event.ecode);
1349 : :
1350 : : /* Have we run out of new completions to process? */
1351 [ # # ]: 0 : if (!(cq_desc->event.eid > lif->last_eid))
1352 : : return false;
1353 : :
1354 : 0 : lif->last_eid = cq_desc->event.eid;
1355 : :
1356 [ # # # ]: 0 : switch (cq_desc->event.ecode) {
1357 : 0 : case IONIC_EVENT_LINK_CHANGE:
1358 : 0 : IONIC_PRINT(DEBUG,
1359 : : "Notifyq IONIC_EVENT_LINK_CHANGE %s "
1360 : : "eid=%jd link_status=%d link_speed=%d",
1361 : : lif->name,
1362 : : cq_desc->event.eid,
1363 : : cq_desc->link_change.link_status,
1364 : : cq_desc->link_change.link_speed);
1365 : :
1366 : 0 : lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
1367 : 0 : break;
1368 : :
1369 : 0 : case IONIC_EVENT_RESET:
1370 : 0 : IONIC_PRINT(NOTICE,
1371 : : "Notifyq IONIC_EVENT_RESET %s "
1372 : : "eid=%jd, reset_code=%d state=%d",
1373 : : lif->name,
1374 : : cq_desc->event.eid,
1375 : : cq_desc->reset.reset_code,
1376 : : cq_desc->reset.state);
1377 : 0 : ionic_lif_handle_fw_down(lif);
1378 : 0 : break;
1379 : :
1380 : 0 : default:
1381 : 0 : IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
1382 : : cq_desc->event.ecode, cq_desc->event.eid);
1383 : 0 : break;
1384 : : }
1385 : :
1386 : : return true;
1387 : : }
1388 : :
1389 : : int
1390 : 0 : ionic_notifyq_handler(struct ionic_lif *lif, int budget)
1391 : : {
1392 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
1393 : 0 : struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1394 : : uint32_t work_done;
1395 : :
1396 [ # # ]: 0 : if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
1397 : 0 : IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
1398 : 0 : return -1;
1399 : : }
1400 : :
1401 : 0 : ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
1402 : : IONIC_INTR_MASK_SET);
1403 : :
1404 : 0 : work_done = ionic_qcq_service(&nqcq->qcq, budget,
1405 : : ionic_notifyq_cb, lif);
1406 : :
1407 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
1408 : 0 : ionic_link_status_check(lif);
1409 : :
1410 : 0 : ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
1411 : : work_done, IONIC_INTR_CRED_RESET_COALESCE);
1412 : :
1413 : 0 : ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
1414 : : IONIC_INTR_MASK_CLEAR);
1415 : :
1416 : 0 : return 0;
1417 : : }
1418 : :
1419 : : static int
1420 : 0 : ionic_lif_adminq_init(struct ionic_lif *lif)
1421 : : {
1422 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
1423 : 0 : struct ionic_admin_qcq *aqcq = lif->adminqcq;
1424 : 0 : struct ionic_queue *q = &aqcq->qcq.q;
1425 : : struct ionic_q_init_comp comp;
1426 : : uint32_t retries = 5;
1427 : : int err;
1428 : :
1429 : 0 : retry_adminq_init:
1430 : 0 : ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
1431 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1432 [ # # ]: 0 : if (err == -EAGAIN && retries > 0) {
1433 : 0 : retries--;
1434 : 0 : rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
1435 : 0 : goto retry_adminq_init;
1436 : : }
1437 [ # # ]: 0 : if (err)
1438 : : return err;
1439 : :
1440 : 0 : ionic_dev_cmd_comp(idev, &comp);
1441 : :
1442 : 0 : q->hw_type = comp.hw_type;
1443 : 0 : q->hw_index = rte_le_to_cpu_32(comp.hw_index);
1444 : 0 : q->db = ionic_db_map(lif, q);
1445 : :
1446 : 0 : IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
1447 : 0 : IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
1448 : 0 : IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
1449 : :
1450 : 0 : aqcq->flags |= IONIC_QCQ_F_INITED;
1451 : :
1452 : 0 : return 0;
1453 : : }
1454 : :
1455 : : static int
1456 : 0 : ionic_lif_notifyq_init(struct ionic_lif *lif)
1457 : : {
1458 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
1459 : 0 : struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1460 : : struct ionic_queue *q = &nqcq->qcq.q;
1461 : : uint16_t flags = IONIC_QINIT_F_ENA;
1462 : : int err;
1463 : :
1464 : 0 : struct ionic_admin_ctx ctx = {
1465 : : .pending_work = true,
1466 : : .cmd.q_init = {
1467 : : .opcode = IONIC_CMD_Q_INIT,
1468 : 0 : .type = q->type,
1469 : 0 : .ver = lif->qtype_info[q->type].version,
1470 : 0 : .index = rte_cpu_to_le_32(q->index),
1471 : : .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1472 [ # # ]: 0 : .ring_size = rte_log2_u32(q->num_descs),
1473 : 0 : .ring_base = rte_cpu_to_le_64(q->base_pa),
1474 : : }
1475 : : };
1476 : :
1477 : : /* Only enable an interrupt if the device supports them */
1478 [ # # ]: 0 : if (lif->adapter->intf->configure_intr != NULL) {
1479 : : flags |= IONIC_QINIT_F_IRQ;
1480 : 0 : ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
1481 : : }
1482 : 0 : ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
1483 : :
1484 : 0 : IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
1485 : 0 : IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1486 : 0 : IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
1487 : : ctx.cmd.q_init.ring_size);
1488 : 0 : IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
1489 : :
1490 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
1491 [ # # ]: 0 : if (err)
1492 : : return err;
1493 : :
1494 : 0 : q->hw_type = ctx.comp.q_init.hw_type;
1495 : 0 : q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1496 : 0 : q->db = NULL;
1497 : :
1498 : 0 : IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
1499 : 0 : IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
1500 : 0 : IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
1501 : :
1502 : 0 : ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
1503 : : IONIC_INTR_MASK_CLEAR);
1504 : :
1505 : 0 : nqcq->flags |= IONIC_QCQ_F_INITED;
1506 : :
1507 : 0 : return 0;
1508 : : }
1509 : :
1510 : : int
1511 : 0 : ionic_lif_set_features(struct ionic_lif *lif)
1512 : : {
1513 : 0 : struct ionic_admin_ctx ctx = {
1514 : : .pending_work = true,
1515 : : .cmd.lif_setattr = {
1516 : : .opcode = IONIC_CMD_LIF_SETATTR,
1517 : : .attr = IONIC_LIF_ATTR_FEATURES,
1518 : 0 : .features = rte_cpu_to_le_64(lif->features),
1519 : : },
1520 : : };
1521 : : int err;
1522 : :
1523 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
1524 [ # # ]: 0 : if (err)
1525 : : return err;
1526 : :
1527 : 0 : lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1528 : : ctx.comp.lif_setattr.features);
1529 : :
1530 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1531 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1532 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1533 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1534 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1535 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1536 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1537 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1538 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1539 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1540 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1541 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1542 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1543 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1544 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1545 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1546 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO)
1547 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1548 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1549 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1550 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1551 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1552 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1553 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1554 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1555 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1556 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1557 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1558 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1559 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1560 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1561 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1562 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1563 : 0 : IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1564 : :
1565 : : return 0;
1566 : : }
1567 : :
1568 : : int
1569 : 0 : ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1570 : : {
1571 : : struct ionic_qcq *qcq = &txq->qcq;
1572 : 0 : struct ionic_queue *q = &qcq->q;
1573 : 0 : struct ionic_lif *lif = qcq->lif;
1574 : 0 : struct ionic_cq *cq = &qcq->cq;
1575 : 0 : struct ionic_admin_ctx ctx = {
1576 : : .pending_work = true,
1577 : : .cmd.q_init = {
1578 : : .opcode = IONIC_CMD_Q_INIT,
1579 : 0 : .type = q->type,
1580 : 0 : .ver = lif->qtype_info[q->type].version,
1581 : 0 : .index = rte_cpu_to_le_32(q->index),
1582 : : .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
1583 : : .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1584 [ # # ]: 0 : .ring_size = rte_log2_u32(q->num_descs),
1585 : 0 : .ring_base = rte_cpu_to_le_64(q->base_pa),
1586 : 0 : .cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
1587 : 0 : .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1588 : : },
1589 : : };
1590 : : int err;
1591 : :
1592 [ # # ]: 0 : if (txq->flags & IONIC_QCQ_F_SG)
1593 : 0 : ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
1594 [ # # ]: 0 : if (txq->flags & IONIC_QCQ_F_CMB)
1595 : 0 : ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1596 : :
1597 : 0 : IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
1598 : 0 : IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1599 : 0 : IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1600 : : ctx.cmd.q_init.ring_size);
1601 : 0 : IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1602 : :
1603 : 0 : ionic_q_reset(q);
1604 : 0 : ionic_cq_reset(cq);
1605 : :
1606 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
1607 [ # # ]: 0 : if (err)
1608 : : return err;
1609 : :
1610 : 0 : q->hw_type = ctx.comp.q_init.hw_type;
1611 : 0 : q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1612 : 0 : q->db = ionic_db_map(lif, q);
1613 : :
1614 : 0 : IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1615 : 0 : IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1616 : 0 : IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1617 : :
1618 : 0 : txq->flags |= IONIC_QCQ_F_INITED;
1619 : :
1620 : 0 : return 0;
1621 : : }
1622 : :
1623 : : int
1624 : 0 : ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1625 : : {
1626 : : struct ionic_qcq *qcq = &rxq->qcq;
1627 : 0 : struct ionic_queue *q = &qcq->q;
1628 : 0 : struct ionic_lif *lif = qcq->lif;
1629 : 0 : struct ionic_cq *cq = &qcq->cq;
1630 : 0 : struct ionic_admin_ctx ctx = {
1631 : : .pending_work = true,
1632 : : .cmd.q_init = {
1633 : : .opcode = IONIC_CMD_Q_INIT,
1634 : 0 : .type = q->type,
1635 : 0 : .ver = lif->qtype_info[q->type].version,
1636 : 0 : .index = rte_cpu_to_le_32(q->index),
1637 : : .flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
1638 : : .intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1639 [ # # ]: 0 : .ring_size = rte_log2_u32(q->num_descs),
1640 : 0 : .ring_base = rte_cpu_to_le_64(q->base_pa),
1641 : 0 : .cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
1642 : 0 : .sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1643 : : },
1644 : : };
1645 : : int err;
1646 : :
1647 [ # # ]: 0 : if (rxq->flags & IONIC_QCQ_F_SG)
1648 : 0 : ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
1649 [ # # ]: 0 : if (rxq->flags & IONIC_QCQ_F_CMB)
1650 : 0 : ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1651 : :
1652 : 0 : IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
1653 : 0 : IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1654 : 0 : IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1655 : : ctx.cmd.q_init.ring_size);
1656 : 0 : IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1657 : :
1658 : 0 : ionic_q_reset(q);
1659 : 0 : ionic_cq_reset(cq);
1660 : :
1661 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
1662 [ # # ]: 0 : if (err)
1663 : : return err;
1664 : :
1665 : 0 : q->hw_type = ctx.comp.q_init.hw_type;
1666 : 0 : q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1667 : 0 : q->db = ionic_db_map(lif, q);
1668 : :
1669 : 0 : rxq->flags |= IONIC_QCQ_F_INITED;
1670 : :
1671 : 0 : IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1672 : 0 : IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1673 : 0 : IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1674 : :
1675 : 0 : return 0;
1676 : : }
1677 : :
1678 : : static int
1679 : 0 : ionic_station_set(struct ionic_lif *lif)
1680 : : {
1681 : 0 : struct ionic_admin_ctx ctx = {
1682 : : .pending_work = true,
1683 : : .cmd.lif_getattr = {
1684 : : .opcode = IONIC_CMD_LIF_GETATTR,
1685 : : .attr = IONIC_LIF_ATTR_MAC,
1686 : : },
1687 : : };
1688 : : int err;
1689 : :
1690 : 0 : IONIC_PRINT_CALL();
1691 : :
1692 : 0 : err = ionic_adminq_post_wait(lif, &ctx);
1693 [ # # ]: 0 : if (err)
1694 : : return err;
1695 : :
1696 : 0 : memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1697 : :
1698 : 0 : return 0;
1699 : : }
1700 : :
1701 : : static void
1702 : 0 : ionic_lif_set_name(struct ionic_lif *lif)
1703 : : {
1704 : 0 : struct ionic_admin_ctx ctx = {
1705 : : .pending_work = true,
1706 : : .cmd.lif_setattr = {
1707 : : .opcode = IONIC_CMD_LIF_SETATTR,
1708 : : .attr = IONIC_LIF_ATTR_NAME,
1709 : : },
1710 : : };
1711 : :
1712 : 0 : memcpy(ctx.cmd.lif_setattr.name, lif->name,
1713 : : sizeof(ctx.cmd.lif_setattr.name) - 1);
1714 : :
1715 : 0 : ionic_adminq_post_wait(lif, &ctx);
1716 : 0 : }
1717 : :
1718 : : int
1719 : 0 : ionic_lif_init(struct ionic_lif *lif)
1720 : : {
1721 : 0 : struct ionic_dev *idev = &lif->adapter->idev;
1722 : : struct ionic_lif_init_comp comp;
1723 : : uint32_t retries = 5;
1724 : : int err;
1725 : :
1726 : 0 : memset(&lif->stats_base, 0, sizeof(lif->stats_base));
1727 : :
1728 : 0 : retry_lif_init:
1729 : 0 : ionic_dev_cmd_lif_init(idev, lif->info_pa);
1730 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1731 [ # # ]: 0 : if (err == -EAGAIN && retries > 0) {
1732 : 0 : retries--;
1733 : 0 : rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
1734 : 0 : goto retry_lif_init;
1735 : : }
1736 [ # # ]: 0 : if (err)
1737 : : return err;
1738 : :
1739 : 0 : ionic_dev_cmd_comp(idev, &comp);
1740 : :
1741 : 0 : lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1742 : :
1743 : 0 : err = ionic_lif_adminq_init(lif);
1744 [ # # ]: 0 : if (err)
1745 : : return err;
1746 : :
1747 : 0 : err = ionic_lif_notifyq_init(lif);
1748 [ # # ]: 0 : if (err)
1749 : 0 : goto err_out_adminq_deinit;
1750 : :
1751 : : /*
1752 : : * Configure initial feature set
1753 : : * This will be updated later by the dev_configure() step
1754 : : */
1755 : 0 : lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1756 : :
1757 : 0 : err = ionic_lif_set_features(lif);
1758 [ # # ]: 0 : if (err)
1759 : 0 : goto err_out_notifyq_deinit;
1760 : :
1761 : 0 : err = ionic_rx_filters_init(lif);
1762 [ # # ]: 0 : if (err)
1763 : 0 : goto err_out_notifyq_deinit;
1764 : :
1765 : 0 : err = ionic_station_set(lif);
1766 [ # # ]: 0 : if (err)
1767 : 0 : goto err_out_rx_filter_deinit;
1768 : :
1769 : 0 : ionic_lif_set_name(lif);
1770 : :
1771 : 0 : lif->state |= IONIC_LIF_F_INITED;
1772 : :
1773 : 0 : return 0;
1774 : :
1775 : : err_out_rx_filter_deinit:
1776 : 0 : ionic_rx_filters_deinit(lif);
1777 : :
1778 [ # # ]: 0 : err_out_notifyq_deinit:
1779 : : ionic_lif_notifyq_deinit(lif);
1780 : :
1781 : 0 : err_out_adminq_deinit:
1782 : : ionic_lif_adminq_deinit(lif);
1783 : :
1784 : 0 : return err;
1785 : : }
1786 : :
1787 : : void
1788 : 0 : ionic_lif_deinit(struct ionic_lif *lif)
1789 : : {
1790 [ # # ]: 0 : if (!(lif->state & IONIC_LIF_F_INITED))
1791 : : return;
1792 : :
1793 : 0 : ionic_rx_filters_deinit(lif);
1794 : 0 : ionic_lif_rss_teardown(lif);
1795 : : ionic_lif_notifyq_deinit(lif);
1796 : : ionic_lif_adminq_deinit(lif);
1797 : :
1798 : 0 : lif->state &= ~IONIC_LIF_F_INITED;
1799 : : }
1800 : :
1801 : : void
1802 : 0 : ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
1803 : : {
1804 : 0 : struct rte_eth_dev *eth_dev = lif->eth_dev;
1805 : 0 : struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode;
1806 : :
1807 : : /*
1808 : : * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1809 : : * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
1810 : : */
1811 : 0 : rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
1812 : :
1813 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1814 [ # # ]: 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
1815 : 0 : lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
1816 : : else
1817 : 0 : lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
1818 : : }
1819 : 0 : }
1820 : :
1821 : : void
1822 : 0 : ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif)
1823 : : {
1824 : 0 : struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
1825 : :
1826 [ # # ]: 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
1827 : 0 : lif->features |= IONIC_ETH_HW_RX_SG;
1828 : 0 : lif->eth_dev->data->scattered_rx = 1;
1829 : : } else {
1830 : 0 : lif->features &= ~IONIC_ETH_HW_RX_SG;
1831 : 0 : lif->eth_dev->data->scattered_rx = 0;
1832 : : }
1833 : 0 : }
1834 : :
1835 : : void
1836 : 0 : ionic_lif_configure(struct ionic_lif *lif)
1837 : : {
1838 : 0 : struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
1839 : : struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
1840 : 0 : struct ionic_identity *ident = &lif->adapter->ident;
1841 : : union ionic_lif_config *cfg = &ident->lif.eth.config;
1842 : 0 : uint32_t ntxqs_per_lif =
1843 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1844 : 0 : uint32_t nrxqs_per_lif =
1845 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1846 : 0 : uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
1847 : 0 : uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
1848 : :
1849 : 0 : lif->port_id = lif->eth_dev->data->port_id;
1850 : :
1851 : 0 : IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
1852 : : lif->port_id);
1853 : :
1854 [ # # ]: 0 : if (nrxqs > 0)
1855 : 0 : nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
1856 : :
1857 [ # # ]: 0 : if (ntxqs > 0)
1858 : 0 : ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
1859 : :
1860 : 0 : lif->nrxqcqs = nrxqs_per_lif;
1861 : 0 : lif->ntxqcqs = ntxqs_per_lif;
1862 : :
1863 : : /* Update the LIF configuration based on the eth_dev */
1864 : :
1865 : : /*
1866 : : * NB: While it is true that RSS_HASH is always enabled on ionic,
1867 : : * setting this flag unconditionally causes problems in DTS.
1868 : : * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
1869 : : */
1870 : :
1871 : : /* RX per-port */
1872 : :
1873 : 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1874 [ # # ]: 0 : rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1875 : : rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
1876 : 0 : lif->features |= IONIC_ETH_HW_RX_CSUM;
1877 : : else
1878 : 0 : lif->features &= ~IONIC_ETH_HW_RX_CSUM;
1879 : :
1880 : : /*
1881 : : * NB: RX_SG may be enabled later during rx_queue_setup() if
1882 : : * required by the mbuf/mtu configuration
1883 : : */
1884 : 0 : ionic_lif_configure_rx_sg_offload(lif);
1885 : :
1886 : : /* Covers VLAN_STRIP */
1887 : 0 : ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
1888 : :
1889 : : /* TX per-port */
1890 : :
1891 : 0 : if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1892 : : txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1893 : : txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1894 [ # # ]: 0 : txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1895 : : txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
1896 : 0 : lif->features |= IONIC_ETH_HW_TX_CSUM;
1897 : : else
1898 : 0 : lif->features &= ~IONIC_ETH_HW_TX_CSUM;
1899 : :
1900 [ # # ]: 0 : if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
1901 : 0 : lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
1902 : : else
1903 : 0 : lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
1904 : :
1905 [ # # ]: 0 : if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
1906 : 0 : lif->features |= IONIC_ETH_HW_TX_SG;
1907 : : else
1908 : 0 : lif->features &= ~IONIC_ETH_HW_TX_SG;
1909 : :
1910 [ # # ]: 0 : if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
1911 : 0 : lif->features |= IONIC_ETH_HW_TSO;
1912 : 0 : lif->features |= IONIC_ETH_HW_TSO_IPV6;
1913 : 0 : lif->features |= IONIC_ETH_HW_TSO_ECN;
1914 : : } else {
1915 : 0 : lif->features &= ~IONIC_ETH_HW_TSO;
1916 : 0 : lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
1917 : 0 : lif->features &= ~IONIC_ETH_HW_TSO_ECN;
1918 : : }
1919 : 0 : }
1920 : :
1921 : : int
1922 : 0 : ionic_lif_start(struct ionic_lif *lif)
1923 : : {
1924 : : uint32_t rx_mode;
1925 : : uint32_t i;
1926 : : int err;
1927 : :
1928 : 0 : err = ionic_lif_rss_setup(lif);
1929 [ # # ]: 0 : if (err)
1930 : : return err;
1931 : :
1932 [ # # ]: 0 : if (!lif->rx_mode) {
1933 : 0 : IONIC_PRINT(DEBUG, "Setting RX mode on %s",
1934 : : lif->name);
1935 : :
1936 : : rx_mode = IONIC_RX_MODE_F_UNICAST;
1937 : : rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1938 : : rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1939 : :
1940 : : ionic_set_rx_mode(lif, rx_mode);
1941 : : }
1942 : :
1943 : 0 : IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1944 : : "on port %u",
1945 : : lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1946 : :
1947 [ # # ]: 0 : for (i = 0; i < lif->nrxqcqs; i++) {
1948 : 0 : struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
1949 [ # # ]: 0 : if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1950 : 0 : err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1951 : :
1952 [ # # ]: 0 : if (err)
1953 : 0 : return err;
1954 : : }
1955 : : }
1956 : :
1957 [ # # ]: 0 : for (i = 0; i < lif->ntxqcqs; i++) {
1958 : 0 : struct ionic_tx_qcq *txq = lif->txqcqs[i];
1959 [ # # ]: 0 : if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1960 : 0 : err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1961 : :
1962 [ # # ]: 0 : if (err)
1963 : 0 : return err;
1964 : : }
1965 : : }
1966 : :
1967 : : /* Carrier ON here */
1968 : 0 : lif->state |= IONIC_LIF_F_UP;
1969 : :
1970 : 0 : ionic_link_status_check(lif);
1971 : :
1972 : 0 : return 0;
1973 : : }
1974 : :
1975 : : int
1976 : 0 : ionic_lif_identify(struct ionic_adapter *adapter)
1977 : : {
1978 : 0 : struct ionic_dev *idev = &adapter->idev;
1979 : : struct ionic_identity *ident = &adapter->ident;
1980 : : union ionic_lif_config *cfg = &ident->lif.eth.config;
1981 : : uint32_t lif_words = RTE_DIM(ident->lif.words);
1982 : : uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
1983 : : uint32_t i, nwords;
1984 : : int err;
1985 : :
1986 : 0 : ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1987 : : IONIC_IDENTITY_VERSION_1);
1988 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1989 [ # # ]: 0 : if (err)
1990 : : return (err);
1991 : :
1992 : : nwords = RTE_MIN(lif_words, cmd_words);
1993 [ # # ]: 0 : for (i = 0; i < nwords; i++)
1994 : 0 : ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1995 : :
1996 : 0 : IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1997 : : rte_le_to_cpu_64(ident->lif.capabilities));
1998 : :
1999 : 0 : IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
2000 : : rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
2001 : 0 : IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
2002 : : rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
2003 : :
2004 : 0 : IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
2005 : : rte_le_to_cpu_64(cfg->features));
2006 : 0 : IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
2007 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
2008 : 0 : IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
2009 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
2010 : 0 : IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
2011 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
2012 : 0 : IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
2013 : : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
2014 : :
2015 : 0 : return 0;
2016 : : }
2017 : :
2018 : : int
2019 : 0 : ionic_lifs_size(struct ionic_adapter *adapter)
2020 : : {
2021 : : struct ionic_identity *ident = &adapter->ident;
2022 : : union ionic_lif_config *cfg = &ident->lif.eth.config;
2023 : 0 : uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
2024 : :
2025 : 0 : adapter->max_ntxqs_per_lif =
2026 : 0 : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
2027 : 0 : adapter->max_nrxqs_per_lif =
2028 : 0 : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
2029 : :
2030 : : nintrs = 1 /* notifyq */;
2031 : :
2032 [ # # ]: 0 : if (nintrs > dev_nintrs) {
2033 : 0 : IONIC_PRINT(ERR,
2034 : : "At most %d intr supported, minimum req'd is %u",
2035 : : dev_nintrs, nintrs);
2036 : 0 : return -ENOSPC;
2037 : : }
2038 : :
2039 : 0 : adapter->nintrs = nintrs;
2040 : :
2041 : 0 : return 0;
2042 : : }
|